toolsandutils/e32tools/fix_eabi_thunk_offsets/fix_eabi_thunk_offsets.bat
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 :: Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 :: All rights reserved.
       
     3 :: This component and the accompanying materials are made available
       
     4 :: under the terms of "Eclipse Public License v1.0"
       
     5 :: which accompanies this distribution, and is available
       
     6 :: at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 ::
       
     8 :: Initial Contributors:
       
     9 :: Nokia Corporation - initial contribution.
       
    10 ::
       
    11 :: Contributors:
       
    12 ::
       
    13 :: Description:
       
    14 ::
       
    15 
       
    16 @rem = '--*-Perl-*--
       
    17 @echo off
       
    18 if "%OS%" == "Windows_NT" goto WinNT
       
    19 perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
       
    20 goto endofperl
       
    21 :WinNT
       
    22 perl -x -S "%0" %*
       
    23 if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
       
    24 if %errorlevel% == 9009 echo You do not have Perl in your PATH.
       
    25 goto endofperl
       
    26 @rem ';
       
    27 #!perl
       
    28 #line 28
       
    29 
       
    30 use strict;
       
    31 use Getopt::Long;
       
    32 
       
    33 my $toolVersion = "1.0";
       
    34 
       
    35 my $update = 0;
       
    36 my $use_perforce = 0;
       
    37 my $verbose = 0;
       
    38 my $defFile;
       
    39 
       
    40 # 1. Check arguments, output help etc.
       
    41 
       
    42 GetOptions (
       
    43 	'update' => \$update,			# modify the files
       
    44 	'perforce' => \$use_perforce,	# apply "p4 edit" to changed files
       
    45 	'v+' => \$verbose,				# print extra diagnostic info
       
    46 	'match=s' => \$defFile			# only process DEF files matching a pattern
       
    47 	);
       
    48 
       
    49 if (@ARGV == 0)
       
    50 	{
       
    51 	print STDERR "\nfix_eabi_thunk_offsets.bat - Version $toolVersion\n";
       
    52 
       
    53 	print STDERR << 'END_OF_HELP';
       
    54 
       
    55 Usage: fix_eabi_think_offsets [-update] [-perforce] [-match exp] build_log ... 
       
    56 
       
    57 Parse the output from one or more build logs, extracting MAKEDEF errors and
       
    58 warnings which relate to EABI virtual function override thunks. Using this
       
    59 information, prepare modified DEF files in which each "missing" export is 
       
    60 replaced by a corresponding "unfrozen" export.
       
    61 
       
    62 -update     Overwrite the existing .def files with the modified versions
       
    63 -perforce   Apply "p4 edit" to each of the modified .def files
       
    64 -match exp  Process only .def files with names that contain "\exp"
       
    65 
       
    66 NOTE: The tool assumes that the original build source layout is replicated on 
       
    67 the drive where it is being executed.
       
    68 
       
    69 Build logs will sometimes contain corrupted warning messages, in which case
       
    70 the tool will probably report that there is nothing to replace some missing
       
    71 symbol. It may help to edit the log file and try again: it is always safe to 
       
    72 run this tool more than once on the same log file.
       
    73 
       
    74 END_OF_HELP
       
    75 
       
    76 	exit(1);
       
    77 	}
       
    78 
       
    79 my $parseWarnings = 1;
       
    80 my $parseErrors = 1;
       
    81 
       
    82 
       
    83 # 2. Parse the build logs, extracting the Makedef warnings & errors
       
    84 
       
    85 my $line;
       
    86 my $header;
       
    87 my $parseWarning = 0;
       
    88 my $parseError = 0;
       
    89 my $variant;
       
    90 my $component;
       
    91 my $sourceDefFile;
       
    92 my @errorOutput;
       
    93 my @warningOutput;
       
    94 
       
    95 my %DefFiles;
       
    96 my %TempDefFiles;
       
    97 
       
    98 sub newDefFile($)
       
    99 	{
       
   100 	my ($defFile) = @_;
       
   101 	if (!defined $DefFiles{$defFile})
       
   102 		{
       
   103 		@{$DefFiles{$defFile}} = \();
       
   104 		}
       
   105 	}
       
   106 
       
   107 while ($line = <>)
       
   108 	{
       
   109 	if ($line =~ /^Chdir /)
       
   110 		{
       
   111 		$component = $line;
       
   112 		$component =~ s/^Chdir //;
       
   113 		$component =~ s/\s//g;
       
   114 		next;
       
   115 		}
       
   116 		
       
   117 	if (($line =~ /^  make/) && ($line =~ / CFG\=/))
       
   118 		{
       
   119 		$variant = $line;
       
   120 		$variant =~ s/^.*CFG\=//;
       
   121 		$variant =~ s/ .*$//;
       
   122 		$variant =~ s/\s//g;
       
   123 		next;
       
   124 		}
       
   125 
       
   126 	if ($parseWarnings && ($line =~ /MAKEDEF WARNING:/))
       
   127 		{
       
   128 		$parseWarning =  1;
       
   129 		$parseError = 0;
       
   130 		$header = $line;
       
   131 		next;		
       
   132 		}
       
   133 		
       
   134 	if ($parseErrors && ($line =~ /MAKEDEF ERROR:/))
       
   135 		{
       
   136 		$parseWarning =  0;
       
   137 		$parseError = 1;
       
   138 		$header = $line;
       
   139 		next;		
       
   140 		}
       
   141 
       
   142 	if ($line !~ /^  /)
       
   143 		{
       
   144 		$parseWarning = 0;
       
   145 		$parseError = 0;
       
   146 		next;
       
   147 		}
       
   148 
       
   149 	if ($parseWarning)
       
   150 		{
       
   151 		if ($header)
       
   152 			{
       
   153 			if ($defFile && ($header !~ /\\$defFile/i))
       
   154 				{
       
   155 				$parseWarning = 0;
       
   156 				$parseError = 0;
       
   157 				next;
       
   158 				}
       
   159 			
       
   160 			$sourceDefFile = $header;
       
   161 			$sourceDefFile =~ s/^.*not yet Frozen in//;
       
   162 			$sourceDefFile =~ s/://;
       
   163 			$sourceDefFile =~ s/\s//g;
       
   164 			
       
   165 			push @warningOutput, "--\n$sourceDefFile ($variant)\n$component\n$header";
       
   166 			newDefFile($sourceDefFile);
       
   167 			$header = "";
       
   168 			}
       
   169 
       
   170 		next if ($line =~ /\*\*\*/);
       
   171 		if ($line =~ /^  (\S.*}\.def)(\(\d+\) : \S+.*)$/)
       
   172 			{
       
   173 			push @{$DefFiles{$sourceDefFile}}, "W$2";
       
   174 			$TempDefFiles{$1} = $sourceDefFile;
       
   175 			}
       
   176 		push @warningOutput, $line;
       
   177 		
       
   178 		next;		
       
   179 		}
       
   180 
       
   181 	if ($parseError)
       
   182 		{
       
   183 		if ($defFile && ($line !~ /\\$defFile/i))
       
   184 			{
       
   185 			$parseWarning = 0;
       
   186 			$parseError = 0;
       
   187 			next;
       
   188 			}
       
   189 			
       
   190 		if ($header)
       
   191 			{
       
   192 			$sourceDefFile = $line;
       
   193 			$sourceDefFile =~ s/\(.*$//;
       
   194 			$sourceDefFile =~ s/\s//g;
       
   195 
       
   196 			push @errorOutput, "--\n$sourceDefFile ($variant)\n$component\n$header";
       
   197 			newDefFile($sourceDefFile);
       
   198 			$header = "";
       
   199 			}
       
   200 
       
   201 		next if ($line =~ /\*\*\*/);
       
   202 		if ($line =~ /(\(\d+\) : \S+.*)$/)
       
   203 			{
       
   204 			push @{$DefFiles{$sourceDefFile}}, "E$1";
       
   205 			}
       
   206 		push @errorOutput, $line;
       
   207 		
       
   208 		next;
       
   209 		}
       
   210 
       
   211 	# Catch a orphaned warning line...
       
   212 	
       
   213 	if ($line =~ /^  (\S.*}\.def)(\(\d+\) : \S+.*)$/)
       
   214 		{
       
   215 		my $tempDefFile = $1;
       
   216 		my $newline = $2;
       
   217 		
       
   218 		next if ($defFile && ($tempDefFile !~ /\\$defFile/i));
       
   219 
       
   220 		my $sourceDefFile = $TempDefFiles{$tempDefFile};
       
   221 		push @{$DefFiles{$sourceDefFile}}, "W$newline";
       
   222 		push @warningOutput, $line;
       
   223 		}
       
   224 
       
   225 	}
       
   226 
       
   227 close BUILD_LOG;
       
   228 
       
   229 # 3. Process the information for each DEF file
       
   230 
       
   231 my %Classes;
       
   232 my @DefFileList;
       
   233 
       
   234 foreach my $def (sort keys %DefFiles)
       
   235 	{
       
   236 	my @replacements;
       
   237 	my @errors;
       
   238 	my @warnings;
       
   239 	my $problems = 0;
       
   240 	
       
   241 	print "\n----\n$def\n";
       
   242 	if ($verbose > 1)
       
   243 		{
       
   244 		print "Information extracted from Makedef warnings and errors:\n";
       
   245 		# printed inside the following loop...
       
   246 		}
       
   247 
       
   248 	# Process into lists of errors and warnings which can be sorted
       
   249 	
       
   250 	my $previousline = "";
       
   251 	foreach $line (sort @{$DefFiles{$def}})
       
   252 		{
       
   253 		next if ($line eq $previousline);	# skip duplicates
       
   254 		$previousline = $line;
       
   255 		print "\t$line\n" if ($verbose > 1);
       
   256 			
       
   257 		if ($line =~ /^(.)\((\d+)\) : (((_ZTh|_ZTv)([n0-9_]+)_(NK?(\d+)(\S+)))\s.*)$/)
       
   258 			{
       
   259 			my $msgtype = $1;
       
   260 			my $lineno = $2;
       
   261 			my $defline = $3;
       
   262 			my $symbol = $4;
       
   263 			my $thunkprefix = $5;
       
   264 			my $thunkoffset = $6;
       
   265 			my $unthunked = $7;
       
   266 			my $topnamelen = $8;
       
   267 			my $restofsymbol = $9;
       
   268 			
       
   269 			if ($msgtype eq "E")
       
   270 				{
       
   271 				push @errors, "$unthunked\@$thunkprefix $thunkoffset $lineno $symbol";
       
   272 				}
       
   273 			else
       
   274 				{
       
   275 				push @warnings, "$unthunked\@$thunkprefix $thunkoffset $symbol";
       
   276 				}
       
   277 				
       
   278 			my $class = substr $restofsymbol, 0, $topnamelen;
       
   279 			$Classes{$class} = 1;
       
   280 			}
       
   281 		else
       
   282 			{
       
   283 			print "WARNING: Ignored - not a thunk: $line\n";
       
   284 			}
       
   285 		}
       
   286 	
       
   287 	# Match up the errors and warnings for related symbols
       
   288 	
       
   289 	@errors = sort @errors;
       
   290 	@warnings = sort @warnings;
       
   291 	my $error;
       
   292 	my $warning;
       
   293 	while (scalar @errors && scalar @warnings)
       
   294 		{
       
   295 		# Unpack the first entry in each of the lists
       
   296 		
       
   297 		$error = shift @errors;
       
   298 		my ($ekey, $eoffset, $eline, $esymbol) = split / /, $error;
       
   299 		$warning = shift @warnings;
       
   300 		my ($wkey, $woffset, $wsymbol) = split / /, $warning;
       
   301 		
       
   302 		# Are they for the same thunk?
       
   303 		
       
   304 		if ($ekey lt $wkey) 
       
   305 			{
       
   306 			# no - unmatched error, so put back the warning
       
   307 			unshift @warnings, $warning;
       
   308 			print "Nothing to replace missing symbol on $eline : $esymbol\n";
       
   309 			$problems += 1;
       
   310 			next;
       
   311 			}
       
   312 		
       
   313 		if ($ekey gt $wkey)
       
   314 			{
       
   315 			# no - unmatched warning, so put back the error
       
   316 			unshift @errors, $error;
       
   317 			print "Nothing missing for replacement symbol : $wsymbol\n";
       
   318 			$problems += 1;
       
   319 			next;
       
   320 			}
       
   321 		
       
   322 		# Yes - create replacement instruction
       
   323 		
       
   324 		push @replacements, "$eline $esymbol => $wsymbol";
       
   325 		}
       
   326 	
       
   327 	# drain remaining problems, if any
       
   328 	
       
   329 	foreach my $error (@errors)
       
   330 		{
       
   331 		my ($ekey, $eoffset, $eline, $esymbol) = split / /, $error;
       
   332 		print "Nothing to replace missing symbol on $eline : $esymbol\n";
       
   333 		$problems += 1;
       
   334 		}
       
   335 	foreach my $warning (@warnings)
       
   336 		{
       
   337 		my ($wkey, $woffset, $wsymbol) = split / /, $warning;
       
   338 		print "Nothing missing for replacement symbol : $wsymbol\n";
       
   339 		$problems += 1;
       
   340 		}
       
   341 		
       
   342 	if ($verbose)
       
   343 		{
       
   344 		print "\nSubstitions identified:\n\t";
       
   345 		print join("\n\t", sort @replacements);
       
   346 		print "\n";
       
   347 		}
       
   348 	
       
   349 	open DEFFILE, "<$def" or print "Can't open $def: $!\n" and next;
       
   350 	my @deflines = <DEFFILE>;
       
   351 	close DEFFILE;
       
   352 	my $changedlines = 0;
       
   353 
       
   354 	foreach my $fix (@replacements)
       
   355 		{
       
   356 		my ($lineno, $before, $to, $after) = split ' ', $fix;
       
   357 
       
   358 		my $line = @deflines[$lineno-1];
       
   359 		if ($line =~ /\s($after)\s/)
       
   360 			{
       
   361 			print "$lineno - already fixed\n";
       
   362 			next;
       
   363 			}
       
   364 		if ($line =~ /\s($before)\s/)
       
   365 			{
       
   366 			$line =~ s/(\s)$before(\s)/$1$after$2/;
       
   367 			@deflines[$lineno-1] = $line;
       
   368 			print "Changed $lineno to $line" if ($verbose > 1);
       
   369 			$changedlines += 1;
       
   370 			next;
       
   371 			}
       
   372 		print "$lineno doesn't contain $before\n";
       
   373 		$problems += 1;
       
   374 		}
       
   375 	print "\n";
       
   376 	
       
   377 	if ($problems != 0)
       
   378 		{
       
   379 		print "WARNING: $problems thunks could not be repaired\n";
       
   380 		}
       
   381 
       
   382 	if ($changedlines == 0)
       
   383 		{
       
   384 		print "Nothing to change\n";
       
   385 		next;
       
   386 		}
       
   387 	print "Will change $changedlines lines\n\n";
       
   388 
       
   389 	# Now update the file (and edit in Perforce if required)
       
   390 		
       
   391 	if ($update)
       
   392 		{
       
   393 		chmod 0666, $def;	# make it writeable
       
   394 		
       
   395 		open DEFFILE, ">$def" or print "Can't open $def for writing: $!\n" and next;
       
   396 		print DEFFILE @deflines;
       
   397 		close DEFFILE;
       
   398 		
       
   399 		print "Updated $def\n";
       
   400 		push @DefFileList, $def;
       
   401 		
       
   402 		if ($use_perforce)
       
   403 			{
       
   404 			print "* p4 edit $def\n";
       
   405 			system "p4 edit $def";
       
   406 			print "\n";
       
   407 			}
       
   408 		}
       
   409 	}
       
   410 
       
   411 # 5. More diagnostic information
       
   412 
       
   413 if (scalar @DefFileList)
       
   414 	{
       
   415 	print "\nList of updated def files\n";
       
   416 	print join("\n", @DefFileList);
       
   417 	print "\n";
       
   418 	}
       
   419 
       
   420 if ($verbose && scalar keys %Classes != 0)
       
   421 	{
       
   422 	print "\nList of affected classes:\n";
       
   423 	print join("\n", sort keys %Classes), "\n";
       
   424 	}
       
   425 
       
   426 __END__
       
   427 :endofperl