diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/fix_eabi_thunk_offsets/fix_eabi_thunk_offsets.bat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/fix_eabi_thunk_offsets/fix_eabi_thunk_offsets.bat Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,427 @@ +:: Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +:: All rights reserved. +:: This component and the accompanying materials are made available +:: under the terms of "Eclipse Public License v1.0" +:: which accompanies this distribution, and is available +:: at the URL "http://www.eclipse.org/legal/epl-v10.html". +:: +:: Initial Contributors: +:: Nokia Corporation - initial contribution. +:: +:: Contributors: +:: +:: Description: +:: + +@rem = '--*-Perl-*-- +@echo off +if "%OS%" == "Windows_NT" goto WinNT +perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 +goto endofperl +:WinNT +perl -x -S "%0" %* +if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl +if %errorlevel% == 9009 echo You do not have Perl in your PATH. +goto endofperl +@rem '; +#!perl +#line 28 + +use strict; +use Getopt::Long; + +my $toolVersion = "1.0"; + +my $update = 0; +my $use_perforce = 0; +my $verbose = 0; +my $defFile; + +# 1. Check arguments, output help etc. + +GetOptions ( + 'update' => \$update, # modify the files + 'perforce' => \$use_perforce, # apply "p4 edit" to changed files + 'v+' => \$verbose, # print extra diagnostic info + 'match=s' => \$defFile # only process DEF files matching a pattern + ); + +if (@ARGV == 0) + { + print STDERR "\nfix_eabi_thunk_offsets.bat - Version $toolVersion\n"; + + print STDERR << 'END_OF_HELP'; + +Usage: fix_eabi_think_offsets [-update] [-perforce] [-match exp] build_log ... + +Parse the output from one or more build logs, extracting MAKEDEF errors and +warnings which relate to EABI virtual function override thunks. Using this +information, prepare modified DEF files in which each "missing" export is +replaced by a corresponding "unfrozen" export. + +-update Overwrite the existing .def files with the modified versions +-perforce Apply "p4 edit" to each of the modified .def files +-match exp Process only .def files with names that contain "\exp" + +NOTE: The tool assumes that the original build source layout is replicated on +the drive where it is being executed. + +Build logs will sometimes contain corrupted warning messages, in which case +the tool will probably report that there is nothing to replace some missing +symbol. It may help to edit the log file and try again: it is always safe to +run this tool more than once on the same log file. + +END_OF_HELP + + exit(1); + } + +my $parseWarnings = 1; +my $parseErrors = 1; + + +# 2. Parse the build logs, extracting the Makedef warnings & errors + +my $line; +my $header; +my $parseWarning = 0; +my $parseError = 0; +my $variant; +my $component; +my $sourceDefFile; +my @errorOutput; +my @warningOutput; + +my %DefFiles; +my %TempDefFiles; + +sub newDefFile($) + { + my ($defFile) = @_; + if (!defined $DefFiles{$defFile}) + { + @{$DefFiles{$defFile}} = \(); + } + } + +while ($line = <>) + { + if ($line =~ /^Chdir /) + { + $component = $line; + $component =~ s/^Chdir //; + $component =~ s/\s//g; + next; + } + + if (($line =~ /^ make/) && ($line =~ / CFG\=/)) + { + $variant = $line; + $variant =~ s/^.*CFG\=//; + $variant =~ s/ .*$//; + $variant =~ s/\s//g; + next; + } + + if ($parseWarnings && ($line =~ /MAKEDEF WARNING:/)) + { + $parseWarning = 1; + $parseError = 0; + $header = $line; + next; + } + + if ($parseErrors && ($line =~ /MAKEDEF ERROR:/)) + { + $parseWarning = 0; + $parseError = 1; + $header = $line; + next; + } + + if ($line !~ /^ /) + { + $parseWarning = 0; + $parseError = 0; + next; + } + + if ($parseWarning) + { + if ($header) + { + if ($defFile && ($header !~ /\\$defFile/i)) + { + $parseWarning = 0; + $parseError = 0; + next; + } + + $sourceDefFile = $header; + $sourceDefFile =~ s/^.*not yet Frozen in//; + $sourceDefFile =~ s/://; + $sourceDefFile =~ s/\s//g; + + push @warningOutput, "--\n$sourceDefFile ($variant)\n$component\n$header"; + newDefFile($sourceDefFile); + $header = ""; + } + + next if ($line =~ /\*\*\*/); + if ($line =~ /^ (\S.*}\.def)(\(\d+\) : \S+.*)$/) + { + push @{$DefFiles{$sourceDefFile}}, "W$2"; + $TempDefFiles{$1} = $sourceDefFile; + } + push @warningOutput, $line; + + next; + } + + if ($parseError) + { + if ($defFile && ($line !~ /\\$defFile/i)) + { + $parseWarning = 0; + $parseError = 0; + next; + } + + if ($header) + { + $sourceDefFile = $line; + $sourceDefFile =~ s/\(.*$//; + $sourceDefFile =~ s/\s//g; + + push @errorOutput, "--\n$sourceDefFile ($variant)\n$component\n$header"; + newDefFile($sourceDefFile); + $header = ""; + } + + next if ($line =~ /\*\*\*/); + if ($line =~ /(\(\d+\) : \S+.*)$/) + { + push @{$DefFiles{$sourceDefFile}}, "E$1"; + } + push @errorOutput, $line; + + next; + } + + # Catch a orphaned warning line... + + if ($line =~ /^ (\S.*}\.def)(\(\d+\) : \S+.*)$/) + { + my $tempDefFile = $1; + my $newline = $2; + + next if ($defFile && ($tempDefFile !~ /\\$defFile/i)); + + my $sourceDefFile = $TempDefFiles{$tempDefFile}; + push @{$DefFiles{$sourceDefFile}}, "W$newline"; + push @warningOutput, $line; + } + + } + +close BUILD_LOG; + +# 3. Process the information for each DEF file + +my %Classes; +my @DefFileList; + +foreach my $def (sort keys %DefFiles) + { + my @replacements; + my @errors; + my @warnings; + my $problems = 0; + + print "\n----\n$def\n"; + if ($verbose > 1) + { + print "Information extracted from Makedef warnings and errors:\n"; + # printed inside the following loop... + } + + # Process into lists of errors and warnings which can be sorted + + my $previousline = ""; + foreach $line (sort @{$DefFiles{$def}}) + { + next if ($line eq $previousline); # skip duplicates + $previousline = $line; + print "\t$line\n" if ($verbose > 1); + + if ($line =~ /^(.)\((\d+)\) : (((_ZTh|_ZTv)([n0-9_]+)_(NK?(\d+)(\S+)))\s.*)$/) + { + my $msgtype = $1; + my $lineno = $2; + my $defline = $3; + my $symbol = $4; + my $thunkprefix = $5; + my $thunkoffset = $6; + my $unthunked = $7; + my $topnamelen = $8; + my $restofsymbol = $9; + + if ($msgtype eq "E") + { + push @errors, "$unthunked\@$thunkprefix $thunkoffset $lineno $symbol"; + } + else + { + push @warnings, "$unthunked\@$thunkprefix $thunkoffset $symbol"; + } + + my $class = substr $restofsymbol, 0, $topnamelen; + $Classes{$class} = 1; + } + else + { + print "WARNING: Ignored - not a thunk: $line\n"; + } + } + + # Match up the errors and warnings for related symbols + + @errors = sort @errors; + @warnings = sort @warnings; + my $error; + my $warning; + while (scalar @errors && scalar @warnings) + { + # Unpack the first entry in each of the lists + + $error = shift @errors; + my ($ekey, $eoffset, $eline, $esymbol) = split / /, $error; + $warning = shift @warnings; + my ($wkey, $woffset, $wsymbol) = split / /, $warning; + + # Are they for the same thunk? + + if ($ekey lt $wkey) + { + # no - unmatched error, so put back the warning + unshift @warnings, $warning; + print "Nothing to replace missing symbol on $eline : $esymbol\n"; + $problems += 1; + next; + } + + if ($ekey gt $wkey) + { + # no - unmatched warning, so put back the error + unshift @errors, $error; + print "Nothing missing for replacement symbol : $wsymbol\n"; + $problems += 1; + next; + } + + # Yes - create replacement instruction + + push @replacements, "$eline $esymbol => $wsymbol"; + } + + # drain remaining problems, if any + + foreach my $error (@errors) + { + my ($ekey, $eoffset, $eline, $esymbol) = split / /, $error; + print "Nothing to replace missing symbol on $eline : $esymbol\n"; + $problems += 1; + } + foreach my $warning (@warnings) + { + my ($wkey, $woffset, $wsymbol) = split / /, $warning; + print "Nothing missing for replacement symbol : $wsymbol\n"; + $problems += 1; + } + + if ($verbose) + { + print "\nSubstitions identified:\n\t"; + print join("\n\t", sort @replacements); + print "\n"; + } + + open DEFFILE, "<$def" or print "Can't open $def: $!\n" and next; + my @deflines = ; + close DEFFILE; + my $changedlines = 0; + + foreach my $fix (@replacements) + { + my ($lineno, $before, $to, $after) = split ' ', $fix; + + my $line = @deflines[$lineno-1]; + if ($line =~ /\s($after)\s/) + { + print "$lineno - already fixed\n"; + next; + } + if ($line =~ /\s($before)\s/) + { + $line =~ s/(\s)$before(\s)/$1$after$2/; + @deflines[$lineno-1] = $line; + print "Changed $lineno to $line" if ($verbose > 1); + $changedlines += 1; + next; + } + print "$lineno doesn't contain $before\n"; + $problems += 1; + } + print "\n"; + + if ($problems != 0) + { + print "WARNING: $problems thunks could not be repaired\n"; + } + + if ($changedlines == 0) + { + print "Nothing to change\n"; + next; + } + print "Will change $changedlines lines\n\n"; + + # Now update the file (and edit in Perforce if required) + + if ($update) + { + chmod 0666, $def; # make it writeable + + open DEFFILE, ">$def" or print "Can't open $def for writing: $!\n" and next; + print DEFFILE @deflines; + close DEFFILE; + + print "Updated $def\n"; + push @DefFileList, $def; + + if ($use_perforce) + { + print "* p4 edit $def\n"; + system "p4 edit $def"; + print "\n"; + } + } + } + +# 5. More diagnostic information + +if (scalar @DefFileList) + { + print "\nList of updated def files\n"; + print join("\n", @DefFileList); + print "\n"; + } + +if ($verbose && scalar keys %Classes != 0) + { + print "\nList of affected classes:\n"; + print join("\n", sort keys %Classes), "\n"; + } + +__END__ +:endofperl