1*b1cdbd2cSJim Jagielski: 2*b1cdbd2cSJim Jagielskieval 'exec perl -wS $0 ${1+"$@"}' 3*b1cdbd2cSJim Jagielski if 0; 4*b1cdbd2cSJim Jagielski#************************************************************** 5*b1cdbd2cSJim Jagielski# 6*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 7*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 8*b1cdbd2cSJim Jagielski# distributed with this work for additional information 9*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 10*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 11*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 12*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 13*b1cdbd2cSJim Jagielski# 14*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 15*b1cdbd2cSJim Jagielski# 16*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 17*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 18*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 20*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 21*b1cdbd2cSJim Jagielski# under the License. 22*b1cdbd2cSJim Jagielski# 23*b1cdbd2cSJim Jagielski#************************************************************** 24*b1cdbd2cSJim Jagielski 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski# 28*b1cdbd2cSJim Jagielski# rebase.pl - rebase windows dlls 29*b1cdbd2cSJim Jagielski# 30*b1cdbd2cSJim Jagielski# This perl script is to rebase all windows dlls. In principle this could 31*b1cdbd2cSJim Jagielski# be done with one simple command line like f.e. 32*b1cdbd2cSJim Jagielski# rebase -b 0x68000000 -d -R foo_dir -N bar.txt $(SOLARBINDIR)$/*.dll 33*b1cdbd2cSJim Jagielski# That would work fine for creating complete office install sets, but it 34*b1cdbd2cSJim Jagielski# could fail as soon as we are going to ship single dlls for a product 35*b1cdbd2cSJim Jagielski# patch. Therefore, this wrapper perl script is used. It reads a given base 36*b1cdbd2cSJim Jagielski# address file and rebases all files mentioned to the same address as 37*b1cdbd2cSJim Jagielski# previously. New dlls get appended to the list. 38*b1cdbd2cSJim Jagielski 39*b1cdbd2cSJim Jagielskiuse strict; 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski#### globals ##### 42*b1cdbd2cSJim Jagielski 43*b1cdbd2cSJim Jagielskimy $myname = ''; 44*b1cdbd2cSJim Jagielskimy $options_string = ''; # order of options is important 45*b1cdbd2cSJim Jagielskimy %options_hash; 46*b1cdbd2cSJim Jagielskimy $rebase_files; 47*b1cdbd2cSJim Jagielskimy $misc_dir = $ENV{TEMP}; 48*b1cdbd2cSJim Jagielskimy $lastaddress; 49*b1cdbd2cSJim Jagielskimy @old_files; 50*b1cdbd2cSJim Jagielskimy @new_files; 51*b1cdbd2cSJim Jagielski 52*b1cdbd2cSJim Jagielski#### main ##### 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski$myname = script_id(); 55*b1cdbd2cSJim Jagielskiparse_options(); 56*b1cdbd2cSJim Jagielskimy %lastrun = read_coffbase( \$lastaddress ); 57*b1cdbd2cSJim Jagielski# Get files specified on command line. Differ between those already 58*b1cdbd2cSJim Jagielski# listed in coffbase (%options_hash{'C'}) and additional ones. 59*b1cdbd2cSJim Jagielskiget_files( \@old_files, \@new_files ); 60*b1cdbd2cSJim Jagielski# Rebase libraries already listed in coffbase to the addresses given there. 61*b1cdbd2cSJim Jagielskirebase_again( \@old_files, \@new_files ) if ( @old_files ); 62*b1cdbd2cSJim Jagielski# Rebase additional files. 63*b1cdbd2cSJim Jagielskirebase_initially( \@new_files, $lastaddress ) if ( @new_files ); 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielskiexit 0; 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski 68*b1cdbd2cSJim Jagielski#### subroutines #### 69*b1cdbd2cSJim Jagielski 70*b1cdbd2cSJim Jagielskisub script_id 71*b1cdbd2cSJim Jagielski{ 72*b1cdbd2cSJim Jagielski ( my $script_name = $0 ) =~ s/^.*[\\\/]([\w\.]+)$/$1/; 73*b1cdbd2cSJim Jagielski 74*b1cdbd2cSJim Jagielski my $script_rev; 75*b1cdbd2cSJim Jagielski my $id_str = ' $Revision$ '; 76*b1cdbd2cSJim Jagielski $id_str =~ /Revision:\s+(\S+)\s+\$/ 77*b1cdbd2cSJim Jagielski ? ($script_rev = $1) : ($script_rev = "-"); 78*b1cdbd2cSJim Jagielski# print "\n$script_name -- version: $script_rev\n"; 79*b1cdbd2cSJim Jagielski return $script_name; 80*b1cdbd2cSJim Jagielski} 81*b1cdbd2cSJim Jagielski 82*b1cdbd2cSJim Jagielski 83*b1cdbd2cSJim Jagielskisub parse_options 84*b1cdbd2cSJim Jagielski{ 85*b1cdbd2cSJim Jagielski use Getopt::Std; 86*b1cdbd2cSJim Jagielski if ( !getopts('C:b:de:l:m:R:N:v', \%options_hash) || ($#ARGV < 0) ) { 87*b1cdbd2cSJim Jagielski print STDERR "Error: invalid command line.\n\n"; 88*b1cdbd2cSJim Jagielski usage (); 89*b1cdbd2cSJim Jagielski exit 1; 90*b1cdbd2cSJim Jagielski } 91*b1cdbd2cSJim Jagielski # create options string (we cannot rely on a hash because for some options the 92*b1cdbd2cSJim Jagielski # order is important. -R option has to be specified before -N!) 93*b1cdbd2cSJim Jagielski foreach my $var ( 'C', 'b', 'e', 'l', 'R', 'N' ) { 94*b1cdbd2cSJim Jagielski if ($options_hash{$var} ) { 95*b1cdbd2cSJim Jagielski $options_string .= "-$var $options_hash{$var} "; 96*b1cdbd2cSJim Jagielski } 97*b1cdbd2cSJim Jagielski } 98*b1cdbd2cSJim Jagielski $options_string .= "-d " if $options_hash{"d"}; 99*b1cdbd2cSJim Jagielski $options_string .= "-v " if $options_hash{"v"}; 100*b1cdbd2cSJim Jagielski # some basic tests 101*b1cdbd2cSJim Jagielski if ( ! $options_hash{'C'}) { 102*b1cdbd2cSJim Jagielski print STDERR "Error: no coffbase specified\n\n"; 103*b1cdbd2cSJim Jagielski usage (); 104*b1cdbd2cSJim Jagielski exit 2; 105*b1cdbd2cSJim Jagielski } 106*b1cdbd2cSJim Jagielski if ( ! $options_hash{'b'}) { 107*b1cdbd2cSJim Jagielski print STDERR "Error: no initial base address specified\n\n"; 108*b1cdbd2cSJim Jagielski usage (); 109*b1cdbd2cSJim Jagielski exit 2; 110*b1cdbd2cSJim Jagielski } 111*b1cdbd2cSJim Jagielski if ($options_hash{"m"}) { 112*b1cdbd2cSJim Jagielski $misc_dir = $options_hash{"m"}; 113*b1cdbd2cSJim Jagielski } 114*b1cdbd2cSJim Jagielski if ( ! -d $misc_dir ) { 115*b1cdbd2cSJim Jagielski print STDERR "Error: no directory to write work files. Please specify with -m\n"; 116*b1cdbd2cSJim Jagielski usage (); 117*b1cdbd2cSJim Jagielski exit 3; 118*b1cdbd2cSJim Jagielski } 119*b1cdbd2cSJim Jagielski if ( $misc_dir !~ /[\/\\]$/ ) { 120*b1cdbd2cSJim Jagielski # append finishing path separator: 121*b1cdbd2cSJim Jagielski if ( $misc_dir =~ /([\/\\])/ ) { 122*b1cdbd2cSJim Jagielski $misc_dir .= $1; 123*b1cdbd2cSJim Jagielski } 124*b1cdbd2cSJim Jagielski } 125*b1cdbd2cSJim Jagielski $rebase_files = join " ", @ARGV; 126*b1cdbd2cSJim Jagielski # Cygwin's perl in a W32-4nt configuration wants / instead of \ . 127*b1cdbd2cSJim Jagielski $rebase_files =~ s/\\/\//g; 128*b1cdbd2cSJim Jagielski return; 129*b1cdbd2cSJim Jagielski} 130*b1cdbd2cSJim Jagielski 131*b1cdbd2cSJim Jagielski 132*b1cdbd2cSJim Jagielskisub read_coffbase 133*b1cdbd2cSJim Jagielski{ 134*b1cdbd2cSJim Jagielski my ($addref) = shift; 135*b1cdbd2cSJim Jagielski my %baseaddresses; 136*b1cdbd2cSJim Jagielski my @entry; 137*b1cdbd2cSJim Jagielski if ( $options_hash{'C'} ) { 138*b1cdbd2cSJim Jagielski my $filename = $options_hash{'C'}; 139*b1cdbd2cSJim Jagielski if ( -e $filename ) { 140*b1cdbd2cSJim Jagielski print "Repeated run, $filename present\n"; 141*b1cdbd2cSJim Jagielski open( COFFBASE, $filename) or die "Error: cannot open $filename"; 142*b1cdbd2cSJim Jagielski while ( my $line = <COFFBASE> ) { 143*b1cdbd2cSJim Jagielski # each row consists of three entries, separated by white space: 144*b1cdbd2cSJim Jagielski # dll-name base-address size 145*b1cdbd2cSJim Jagielski @entry = split /\s+/ , $line ; 146*b1cdbd2cSJim Jagielski if ( $entry[3] || ( ! $entry[2] ) ) { 147*b1cdbd2cSJim Jagielski print STDERR "Warning: coffbase file structure invalid?\n"; 148*b1cdbd2cSJim Jagielski } 149*b1cdbd2cSJim Jagielski $baseaddresses{$entry[0]} = $entry[1]; 150*b1cdbd2cSJim Jagielski if ( $entry[3] ) { 151*b1cdbd2cSJim Jagielski print STDERR "Warning: coffbase file structure invalid?\n"; 152*b1cdbd2cSJim Jagielski } 153*b1cdbd2cSJim Jagielski } 154*b1cdbd2cSJim Jagielski close( COFFBASE ); 155*b1cdbd2cSJim Jagielski $$addref = $entry[1]; 156*b1cdbd2cSJim Jagielski } else { 157*b1cdbd2cSJim Jagielski print "Initial run, $filename not yet present\n"; 158*b1cdbd2cSJim Jagielski } 159*b1cdbd2cSJim Jagielski } else { 160*b1cdbd2cSJim Jagielski die "Error: no coffbase specified."; 161*b1cdbd2cSJim Jagielski } 162*b1cdbd2cSJim Jagielski return %baseaddresses; 163*b1cdbd2cSJim Jagielski} 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski 166*b1cdbd2cSJim Jagielskisub get_files 167*b1cdbd2cSJim Jagielski{ 168*b1cdbd2cSJim Jagielski use File::Basename; 169*b1cdbd2cSJim Jagielski my ( $oldfiles_ref, $newfiles_ref ) = @_; 170*b1cdbd2cSJim Jagielski my @target = split / /, $rebase_files; 171*b1cdbd2cSJim Jagielski foreach my $pattern ( @target ) { 172*b1cdbd2cSJim Jagielski foreach my $i ( glob( $pattern ) ) { 173*b1cdbd2cSJim Jagielski my $lib = File::Basename::basename $i; 174*b1cdbd2cSJim Jagielski $lib =~ s/\+/\\\+/g; 175*b1cdbd2cSJim Jagielski if ( grep /^$lib$/i, (keys %lastrun) ) { 176*b1cdbd2cSJim Jagielski push @$oldfiles_ref, $i; 177*b1cdbd2cSJim Jagielski } else { 178*b1cdbd2cSJim Jagielski push @$newfiles_ref, $i; 179*b1cdbd2cSJim Jagielski } 180*b1cdbd2cSJim Jagielski } 181*b1cdbd2cSJim Jagielski } 182*b1cdbd2cSJim Jagielski return; 183*b1cdbd2cSJim Jagielski} 184*b1cdbd2cSJim Jagielski 185*b1cdbd2cSJim Jagielski 186*b1cdbd2cSJim Jagielskisub rebase_again 187*b1cdbd2cSJim Jagielski# rebase using given coffbase file 188*b1cdbd2cSJim Jagielski{ 189*b1cdbd2cSJim Jagielski my $oldfiles_ref = shift; 190*b1cdbd2cSJim Jagielski my $newfiles_ref = shift; 191*b1cdbd2cSJim Jagielski my @grownfiles; 192*b1cdbd2cSJim Jagielski my $solarbin ="$ENV{SOLARVERSION}/$ENV{INPATH}/bin$ENV{UPDMINOREXT}"; 193*b1cdbd2cSJim Jagielski my $command = "rebase " . $options_string; 194*b1cdbd2cSJim Jagielski if ( $ENV{WRAPCMD} ) { 195*b1cdbd2cSJim Jagielski $command = $ENV{WRAPCMD} . " " . $command; 196*b1cdbd2cSJim Jagielski } 197*b1cdbd2cSJim Jagielski $command =~ s/-C /-i /; 198*b1cdbd2cSJim Jagielski $command =~ s/-d//; 199*b1cdbd2cSJim Jagielski $command =~ s/-b $options_hash{'b'}//; 200*b1cdbd2cSJim Jagielski my $fname = $misc_dir . "rebase_again.txt"; 201*b1cdbd2cSJim Jagielski open ( FILES, "> $fname") or die "Error: cannot open file $fname"; 202*b1cdbd2cSJim Jagielski my $filesstring = join " ", @$oldfiles_ref; 203*b1cdbd2cSJim Jagielski print FILES "$filesstring\n"; 204*b1cdbd2cSJim Jagielski close FILES; 205*b1cdbd2cSJim Jagielski $command .= "\@$fname"; 206*b1cdbd2cSJim Jagielski # Cygwin's perl needs escaped \ in system() and open( COMMAND ... ) 207*b1cdbd2cSJim Jagielski if ( "$^O" eq "cygwin" ) { $command =~ s/\\/\\\\/g; } 208*b1cdbd2cSJim Jagielski print "\n$command\n"; 209*b1cdbd2cSJim Jagielski open( COMMAND, "$command 2>&1 |") or die "Error: Can't execute $command\n"; 210*b1cdbd2cSJim Jagielski if ( $? ) { 211*b1cdbd2cSJim Jagielski die "Error: rebase failed: $?!\n"; 212*b1cdbd2cSJim Jagielski } 213*b1cdbd2cSJim Jagielski while( <COMMAND> ) { 214*b1cdbd2cSJim Jagielski print; 215*b1cdbd2cSJim Jagielski # evaluate error messages 216*b1cdbd2cSJim Jagielski if ( /REBASE: ([^\s]+).*Grew too large/ ) { 217*b1cdbd2cSJim Jagielski my $toobig_name = $1; 218*b1cdbd2cSJim Jagielski if ( -e "$solarbin/so/$toobig_name" ) { 219*b1cdbd2cSJim Jagielski push @grownfiles, "$solarbin/so/$toobig_name"; 220*b1cdbd2cSJim Jagielski print "name was : $toobig_name\n"; 221*b1cdbd2cSJim Jagielski print "push $solarbin/so/$toobig_name\n"; 222*b1cdbd2cSJim Jagielski } else { 223*b1cdbd2cSJim Jagielski push @grownfiles, "$solarbin/$toobig_name"; 224*b1cdbd2cSJim Jagielski } 225*b1cdbd2cSJim Jagielski } 226*b1cdbd2cSJim Jagielski } 227*b1cdbd2cSJim Jagielski close( COMMAND ); 228*b1cdbd2cSJim Jagielski if ( @grownfiles ) { 229*b1cdbd2cSJim Jagielski # Some files are larger than expected and therefore could not be rebased. 230*b1cdbd2cSJim Jagielski # Remove respective entries from coffbase and schedule rebase in 'rebase_initially'. 231*b1cdbd2cSJim Jagielski push @$newfiles_ref, @grownfiles; 232*b1cdbd2cSJim Jagielski my $coffbase = $options_hash{'C'}; 233*b1cdbd2cSJim Jagielski my $coffbase_new = $options_hash{'C'} . ".new"; 234*b1cdbd2cSJim Jagielski open( COFFBASENEW, "> $coffbase_new") or die "Error: cannot open $coffbase_new"; 235*b1cdbd2cSJim Jagielski open( COFFBASE, $coffbase) or die "Error: cannot open $coffbase"; 236*b1cdbd2cSJim Jagielski my @entry; 237*b1cdbd2cSJim Jagielski while ( my $line = <COFFBASE> ) { 238*b1cdbd2cSJim Jagielski @entry = split /\s+/ , $line ; 239*b1cdbd2cSJim Jagielski if ( $entry[3] ) { 240*b1cdbd2cSJim Jagielski print STDERR "Warning: coffbase file structure invalid?\n"; 241*b1cdbd2cSJim Jagielski } 242*b1cdbd2cSJim Jagielski grep /^$entry[0]$/, @grownfiles or print COFFBASENEW $line; 243*b1cdbd2cSJim Jagielski } 244*b1cdbd2cSJim Jagielski close( COFFBASE ); 245*b1cdbd2cSJim Jagielski close( COFFBASENEW ); 246*b1cdbd2cSJim Jagielski rename $coffbase, $coffbase . ".old" or warn "Error: cannot rename $coffbase"; 247*b1cdbd2cSJim Jagielski rename $coffbase_new, $coffbase or warn "Error: cannot rename $coffbase_new"; 248*b1cdbd2cSJim Jagielski } 249*b1cdbd2cSJim Jagielski} 250*b1cdbd2cSJim Jagielski 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielskisub rebase_initially 253*b1cdbd2cSJim Jagielski{ 254*b1cdbd2cSJim Jagielski my ($files_ref, $start_address) = @_; 255*b1cdbd2cSJim Jagielski my $command = "rebase "; 256*b1cdbd2cSJim Jagielski if ( $ENV{WRAPCMD} ) { 257*b1cdbd2cSJim Jagielski $command = $ENV{WRAPCMD} . " " . $command; 258*b1cdbd2cSJim Jagielski } 259*b1cdbd2cSJim Jagielski $command .= $options_string; 260*b1cdbd2cSJim Jagielski if ( $start_address ) { 261*b1cdbd2cSJim Jagielski $command =~ s/-b $options_hash{'b'}/ -b $start_address/; 262*b1cdbd2cSJim Jagielski } 263*b1cdbd2cSJim Jagielski my $fname = $misc_dir . "rebase_new.txt"; 264*b1cdbd2cSJim Jagielski open ( FILES, "> $fname") or die "Error: cannot open file $fname"; 265*b1cdbd2cSJim Jagielski my $filesstring = join " ", @$files_ref; 266*b1cdbd2cSJim Jagielski print FILES "$filesstring\n"; 267*b1cdbd2cSJim Jagielski close FILES; 268*b1cdbd2cSJim Jagielski $command .= "\@$fname"; 269*b1cdbd2cSJim Jagielski # Cygwin's perl needs escaped \ in system() and open( COMMAND ... ) 270*b1cdbd2cSJim Jagielski if ( "$^O" eq "cygwin" ) { $command =~ s/\\/\\\\/g; } 271*b1cdbd2cSJim Jagielski print "\n$command\n"; 272*b1cdbd2cSJim Jagielski my $error = system("$command"); 273*b1cdbd2cSJim Jagielski if ($error) { 274*b1cdbd2cSJim Jagielski $error /= 256; 275*b1cdbd2cSJim Jagielski die "Error: rebase failed with exit code $error!\n"; 276*b1cdbd2cSJim Jagielski } 277*b1cdbd2cSJim Jagielski} 278*b1cdbd2cSJim Jagielski 279*b1cdbd2cSJim Jagielski 280*b1cdbd2cSJim Jagielskisub usage 281*b1cdbd2cSJim Jagielski{ 282*b1cdbd2cSJim Jagielski print "Usage:\t $myname <-C filename> <-b address> [-d] [-e <Size>] [-l <filename>] [-v] [-m dir] [-R <roordir>] [-N <filename>] <file[list]> \n"; 283*b1cdbd2cSJim Jagielski # Options similar to rebase binary. Additional options: -m misc-directory 284*b1cdbd2cSJim Jagielski print "Options:\n"; 285*b1cdbd2cSJim Jagielski print "\t -C coffbase_filename Write the list of base adresses to file coffbase_filename. "; 286*b1cdbd2cSJim Jagielski print "Mandatory.\n"; 287*b1cdbd2cSJim Jagielski print "\t -b address Initial base address. Mandatory.\n"; 288*b1cdbd2cSJim Jagielski print "\t -e SizeAdjustment Extra size to allow for image growth.\n"; 289*b1cdbd2cSJim Jagielski print "\t -d Top down rebase.\n"; 290*b1cdbd2cSJim Jagielski print "\t -l filename Write logfile filename.\n"; 291*b1cdbd2cSJim Jagielski print "\t -m directory Directory to write work files.\n"; 292*b1cdbd2cSJim Jagielski print "\t -R directory Root directory.\n"; 293*b1cdbd2cSJim Jagielski print "\t -N filename Specify list of files not to be rebased.\n"; 294*b1cdbd2cSJim Jagielski print "\t -v Verbose.\n"; 295*b1cdbd2cSJim Jagielski return; 296*b1cdbd2cSJim Jagielski} 297*b1cdbd2cSJim Jagielski 298*b1cdbd2cSJim Jagielski 299