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