xref: /AOO42X/main/postprocess/rebase/rebase.pl (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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