imgtools/romtools/maksym/fixupsym.pl
changeset 0 044383f39525
child 590 360bd6b35136
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/maksym/fixupsym.pl	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,470 @@
+#
+# Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "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: 
+# Relinks the debug exe/dlls in a ROM if the make file is present
+#
+
+require 5.003_07;
+use strict;
+no strict 'vars';
+use English;
+use Cwd;
+use FindBin;		# for FindBin::Bin
+
+my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
+
+BEGIN {
+# check user has a version of perl that will cope
+	require 5.005_03;
+# establish the path to the Perl libraries: currently the same directory as this script
+	$PerlLibPath = $FindBin::Bin;	# X:/epoc32/tools
+	$PerlLibPath =~ s/\//\\/g;	# X:\epoc32\tools
+	$PerlLibPath .= "\\";
+}
+
+use lib $PerlLibPath;
+use Modload;
+Load_SetModulePath($PerlLibPath);
+
+# Globals
+my $debug = 0;
+my $rombuild;
+my @executables = ( 'euser' );
+
+cwd =~ /^(.:)/o;
+my $drive = $1;
+
+# get EPOCROOT for searching directories
+my $epocroot = lc $ENV{EPOCROOT};
+
+&args;
+&main;
+
+exit 0;
+
+
+#
+# main
+#
+sub main
+  {
+	my $file;
+	my $text;
+	my $data;
+	my $bss;
+	my $textlen;
+	my $datalen;
+	my $bsslen;
+
+	open (ROM, "<$rombuild")
+	  or die "ERROR: Can't open rombuild log file \"$rombuild\"\n";
+
+	die "ERROR: \"$rombuild\" isn't a rombuild log file\n"
+	  unless ((<ROM> =~ /^ROMBUILD/) || (<ROM> =~ /^ROMBUILD/));
+	
+	# build up a hash of all the make files indexed by build and exe name
+	#
+	# do this in a more directed way based on the map files for the
+	# executables we are interested in.
+
+	%map = ();
+	&dirsearch($epocroot . "EPOC32\\", "BUILD");
+
+	while (<ROM>)
+	  {
+		if (/^Writing Rom image/)
+		  {
+		  # stop at end of first ROM, ignoring any extension ROMs
+		  # This is necessary because the same file could appear
+		  # at different places in different extensions.
+		  #
+		  last;
+		  } 
+		if (/^Processing file (.*)/)
+		  {
+			my $datalen;
+			my $skip;
+			
+			$file = lc $1;
+			$text = $bss = $data = $datalen = 0;
+			
+			# Work out final addresses of sections
+			while (defined($_=<ROM>) && !/^$/)
+			  {
+				if (/^Code start addr:\s+(\w+)/)
+				  {
+					$text = hex($1);
+				  }
+				elsif (/^DataBssLinearBase:\s+(\w+)/)
+				  {
+					$data = hex($1);
+				  }
+				elsif (/^Code size:\s+(\w+)/)
+				  {
+					$textlen = hex($1);
+				  }
+				elsif (/^Data size:\s+(\w+)/)
+				  {
+					$datalen = hex($1);
+					$bss = $data + $datalen;
+				  }
+				elsif (/^BssSize:\s+(\w+)/)
+				  {
+					$bsslen = hex($1);
+				  }
+			  }
+			
+			# Sanity check - text section can't be zero (other sections may be)
+			die "ERROR: Can't find rombuild info for \"$file\"\n"
+			  if (!$text);
+			
+			# get the build and exe name
+			# protect $epocroot with \Q and \E to stop it 
+			# using \ as a special character
+			if ($file =~ /^\Q$epocroot\Eepoc32\\release\\(.*)\\(.*)\\(.*)$/o)
+			  {
+				$build = lc $1;
+				$debrel = uc $2;
+				$executablefile = lc $3;
+			  }
+			
+			# Only relink this file if it's kernel-side or matches the regexp
+			if ($build =~ /^(M|S)/i)
+			  {
+				$skip = 0;
+			  }
+			else
+			  {
+				$skip = 1;
+				foreach $re (@executables)
+				  {
+					$skip = 0 if ($file =~ /$re/i);
+				  }
+			  }
+			print "$file - skipped\n" if ($skip && $debug);
+			next if ($skip);
+
+			if (! defined $map{"$build $executablefile"})
+			    {
+			    print "$file - no makefile\n";
+			    next;
+			    }
+			if ($debrel ne "UDEB")
+			    {
+			    print "$file - can't fixup $debrel\n";
+			    next;
+			    }
+
+			# relink this file
+			print "$file";
+			
+			# lookup the makefile name
+			($makepath, $workdir) = @{$map{"$build $executablefile"}};
+
+			# only relink if we have a makefile
+			if ($makepath && $workdir)
+			  {
+				# optimisation: don't relink if already at correct address
+				$file =~ /(.+\.)[^\.]+/;
+				my $symfile = $drive.$1."sym";
+				my $buf;
+				my $elffile;
+				open SYMFILE, $symfile or print"\nCannot open $symfile\n";	
+				read SYMFILE, $buf, 4;
+				if ($buf =~/^\x7F\x45\x4C\x46/){
+					$elffile = $buf;
+				}
+				close SYMFILE;
+				if ($elffile){
+					if ((-e $file) && (-e $symfile) &&
+						open (CHILD, "fromelf -v $symfile |"))
+					{
+						my $oldtext;
+						my $olddata;
+						my $foundcode = 0;
+						my $founddata = 0;
+						while (<CHILD>)
+						{
+							if (/ER_RO/)
+							{
+								$foundcode = 1;
+							}
+							if (/ER_RW/)
+							{
+								$founddata = 1;
+							}
+                
+							if (/Addr : 0x\w+/)
+							{
+								$_=~tr/0-9//dc;
+								if ($founddata == 1)
+								{
+									$founddata = 0;
+									$olddata = hex($_);
+								}
+                
+								if ($foundcode == 1)
+								{
+									$foundcode = 0;
+									$oldtext = hex($_);
+								}
+							}
+						}
+						close CHILD;
+						$skip = 1 if ((!$textlen || ($text == $oldtext)) && (!$datalen || ($data == $olddata)));
+					}
+				}
+				else {
+					if ((-e $file) && (-e $symfile) &&
+						open (CHILD, "objdump --headers $symfile |"))
+					{
+						my $oldtext;
+						my $olddata;
+						my $oldbss;
+						while (<CHILD>)
+						{
+							if (/^\s+\d+\s+(\.\w+)\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)\s/)
+							{
+								if ($1 eq '.text')
+								{
+									$oldtext = hex($2);
+								}
+								elsif ($1 eq '.data')
+								{
+									$olddata = hex($2);
+								}
+								elsif ($1 eq '.bss')
+								{
+									$oldbss = hex($2);
+								}
+							}
+						}
+						close CHILD;
+						$skip = 1 if ((!$textlen || ($text == $oldtext)) &&
+									(!$datalen || ($data == $olddata)) &&
+									(!$bsslen	 || ($bss  == $oldbss)));
+						print " - current" if ($skip && $debug);
+					}
+				}
+				
+				if (!$skip)
+				  {
+					chdir $workdir
+					  or die "Can't cd to build directory \"$workdir\"\n";
+
+					# save executable in case relink fails
+					rename $file, "$file.bak"
+					  or die "Can't rename \"$file\": $ERRNO\n"
+						if -e $file;
+						
+						$makepath = &fixMakefile($makepath);
+						my $command;
+						if ($elffile){
+							if($makepath =~ /\.gcce/i){
+								$command =
+									sprintf ("make -r -s -f \"$makepath\" $debrel " .
+									"USERLDFLAGS=\"-Ttext 0x%lx -Tdata 0x%lx\"", $text, $data);
+							}
+							else {
+								$command =
+									sprintf ("make -r -s -f \"$makepath\" $debrel " .
+									"USERLDFLAGS=\"--ro-base 0x%lx --rw-base 0x%lx\"", $text, $data);
+							}
+						}
+						else {
+							$command =
+								sprintf ("make -r -s -f \"$makepath\" $debrel " .
+								"USERLDFLAGS=\"--image-base 0 -Ttext 0x%lx " .
+								"-Tdata 0x%lx -Tbss 0x%lx\"",
+								$text, $data, $bss);
+						}
+						print "\n\"$command\"" if ($debug);
+
+					open (CHILD, "$command |")
+					  or die "\nERROR: Can't run \"$command\": $ERRNO\n";
+					close CHILD;
+
+					unlink $makepath;
+					if (-e $file)
+					  {
+						unlink "$file.bak";
+					  }
+					else	# relink failed for some reason - restore saved
+					  {
+						rename "$file.bak", $file;
+					  }
+				  }
+
+				print "\n";
+			  }
+			else
+			  {
+				print " - can't fixup\n";
+			  }
+		  }
+	  }
+	close ROM;
+  }
+
+#
+# args - get command line args
+#
+sub args
+  {
+	my $arg;
+	my @args;
+	my $flag;
+	
+	&help if (!@ARGV);
+	
+	while (@ARGV)
+	  {
+		$arg = shift @ARGV;
+		
+		if ($arg=~/^[\-\/](\S*)$/)
+		  {
+			$flag=$1;
+			
+			if ($flag=~/^[\?h]$/i)
+			  {
+				&help;
+			  }
+			else
+			  {
+				print "\nERROR: Unknown flag \"-$flag\"\n";
+				&usage;
+				exit 1;
+			  }
+		  }
+		else
+		  {
+			push @args,$arg;
+		  }
+	  }
+	
+	$rombuild = shift @args;
+	
+	if (@args)
+	  {
+		foreach $file (@args)
+		  {
+			push @executables, quotemeta($file);
+		  }
+	  }
+  }
+
+
+# recursive directory search
+sub dirsearch
+	{
+	my ($input_path, $dir) = @_;
+	my $searchpath = "$input_path$dir\\";
+	my $workdir;
+
+	return unless (opendir DIRHANDLE, $searchpath);
+	my @allfiles = grep !/^\.\.?$/, readdir DIRHANDLE;
+	closedir DIRHANDLE;
+
+	# Breadth first search: scan files and collect list of subdirectories
+	my @dirlist;
+	foreach $entry (@allfiles)
+		{
+		my $entrypath = "$searchpath$entry";
+		if (-d $entrypath)
+			{
+			# don't look in udeb & urel directories which contain objects and binaries
+			push @dirlist, $entry unless ($entry =~ /(deb|rel)$/i);
+			}
+		elsif ($entry =~ /$dir$/i)
+			{
+			# ARM4/xxx.ARM4 => generated makefile
+			my $liney;
+			open (FILE, "<$entrypath");
+			while ($liney=<FILE>)
+				{
+				if ($liney =~ /^\# CWD\s(.+)\\/)
+					{
+					$workdir = lc $1;
+					}
+				if ($liney =~ /^\# Target\s(.*)$/)
+					{
+					my $target = lc $1;
+ 
+					# add to the hash table
+					my $build = lc $dir;
+					$map{"$build $target"} = [lc "$entrypath", $workdir];
+					$workdir = undef;
+					last;
+					}
+				}
+			close FILE;
+			}
+		}
+	undef @allfiles;
+	# Now process the subdirectories...
+	foreach $entry (@dirlist)
+		{
+		&dirsearch ($searchpath,$entry);
+		}
+	undef @dirlist;
+	}
+	
+sub help ()
+  {
+	my $build;
+	
+	&Load_ModuleL('E32TPVER');
+	print "\nfixupsym - " .
+	  "Fix up executables with locations taken from a ROM image (Build ",
+	  &E32tpver, ")\n";
+	&usage;
+	exit 0;
+  }
+	
+sub usage ()
+  {
+	print <<EOF
+		  
+Usage:
+  fixupsym <logfile> [<executables>]
+
+Where:
+  <logfile>     Log file from rombuild tool.
+  <executables> Names of additional executables to fix up.
+                ASSP-specific executables and EUSER are always included.
+
+Example:
+  fixupsym rombuild.log efile efsrv .fsy
+EOF
+  ;
+	exit 0;
+  }
+sub fixMakefile()
+  {
+	my $makefile = shift @_;
+	my $tmpMakfile = $makefile.".TMP";
+	open (FILEIN, $makefile) or die "Can't open file \"$makefile\" \n";
+	open (FILEOUT, ">".$tmpMakfile) or die "Can't create file \"$tmpMakfile\" \n";
+	while(<FILEIN>) {
+		if ($_ =~ /^\s*elf2e32/){
+			print FILEOUT "#".$_;
+		}
+		else {
+			print FILEOUT $_;
+		}
+	}
+	close FILEIN;
+	close FILEOUT;
+	$tmpMakfile;
+  }