--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/maksym/maksymrofs.pl Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,409 @@
+#
+# Copyright (c) 2005-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:
+# Produces symbolic information given a ROFS log file and .map files for relevant binary files
+#
+
+require 5.003_07;
+no strict 'vars';
+use English;
+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 $maksym = "";
+my $rofsbuild;
+my $debug = 0;
+
+&args;
+&main;
+exit 0;
+
+sub CompareAddrs()
+{
+ return -1 if ($a < $b);
+ return 1 if ($a > $b);
+ return 0;
+}
+
+#
+# main
+#
+sub main()
+{
+ open (ROFS, "<$rofsbuild") or die "ERROR: Can't open rofsbuild log file \"$rofsbuild\"\n";
+ if ($maksym ne "")
+ {
+ open (SYM, ">$maksym") or die "ERROR: Can't open output file \"$maksym\"\n";
+ print "Creating $maksym...\n"
+ }
+
+ my $curretnLine;
+ while ($currentLine = <ROFS>)
+ {
+ # Check that the given log file is from a rofs image and set up the name for the symbol file
+ if ($currentLine =~ /^Creating Rofs image (\S*)/)
+ {
+ if ($maksym eq "")
+ {
+ # For backwards compatibility, replace trailing .img with .symbol
+ # if no trailing .img, just append .symbol anyway
+ $maksym = $1;
+ $maksym =~ s/(\.img)?$/.symbol/i;
+ close SYM;
+ open (SYM, ">$maksym") or die "ERROR: Can't open output file \"$maksym\"\n";
+ print "\nCreating $maksym...\n"
+ }
+ next;
+ }
+
+ # found at end of file
+ if ($currentLine =~ /^Writing Rom image/)
+ {
+ close SYM;
+ $maksym = "";
+ next;
+ }
+
+ # Data file
+ if ($currentLine =~ /^File \'(.*)\' size: \S+\s*$/)
+ {
+ my $file = $1;
+ $file =~ /([^\\]+)$/;
+ printf SYM "\nFrom $file\n\n00000000 0000 $1\n";
+ }
+
+ # Executable file
+ elsif ($currentLine =~ /^Compressed executable File \'(.*)\' size: \S+\s*, mode:\S+\s*$/)
+ {
+ ProcessCompressedLine($1);
+ }
+ }
+ close SYM;
+ close ROFS;
+}
+
+sub ProcessCompressedLine
+{
+ my ($file) = @_;
+
+ my $mapfile;
+ my $mapfile2;
+ print SYM "\nFrom $file\n\n";
+
+ # Look in map file for symbols in .text and relocate them
+ $mapfile2 = $file.".map";
+ $mapfile = $file;
+ $mapfile =~ s/\.\w+$/\.map/;
+ if (!(open (MAP, "$mapfile2") || open (MAP, "$mapfile")))
+ {
+ print "$file\nWarning: Can't open \"$mapfile2\" or \"$mapfile\"\n";
+ # couldn't find map file so output in format that is used for non-binary files
+ my $BinSize = GetSizeFromBinFile($file);
+ $file =~ /([^\\]+)$/;
+ printf "00000000 %04x $1\n", $BinSize;
+ printf SYM "00000000 %04x $1\n", $BinSize;
+ }
+ else
+ {
+ my @maplines;
+ while ($_ = <MAP>)
+ {
+ push @maplines, $_;
+ }
+ close MAP;
+ # See if we're dealing with the RVCT output
+ if ($file =~m/ARMV5/i)
+ {
+ ProcessArmv5File($file, \@maplines);
+ }
+ elsif( ($file =~ /GCCE/i) || ($file =~ /ARM4/i) )
+ {
+ ProcessGcceOrArm4File($file, \@maplines);
+ }
+ else
+ {
+ print "\nWarning: cannot determine linker type used to create $file\n";
+ $file =~ /([^\\]+)$/;
+ printf SYM "00000000 0000 $1\n";
+ }
+ }
+}
+
+sub ProcessArmv5File
+{
+ my ($file, $mapLines) = @_;
+ my @maplines = @$mapLines;
+ if ($maplines[0] !~ /^ARM Linker/)
+ {
+ print "\nWarning: expecting $file to be generated by ARM linker\n";
+ # file not in format produced by ARMV5 linker so treat file as non-binary file
+ $file =~ /([^\\]+)$/;
+ printf SYM "00000000 0000 $1\n";
+ }
+ else
+ {
+ # scroll down to the global symbols
+ while ($_ = shift @maplines)
+ {
+ if ($_ =~ /Global Symbols/)
+ {
+ last;
+ }
+ }
+
+ my %syms;
+ my $baseOffset; # offset to subtract from each address so that the first entry has address 0x0
+
+ foreach (@maplines)
+ {
+ # name address ignore size section
+ if (/^\s*(.+)\s*(0x\S+)\s+[^\d]*(\d+)\s+(.*)$/)
+ {
+ my $sym = $1;
+ my $addr = hex($2);
+ my $size = sprintf("%04x",$3);
+ my $section = $4;
+ $size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/);
+
+ # it is possible that there will be more than one entry in a log file for a
+ # particular address, this is because aliases are included.
+ # The following code checks that the correct function (i.e. the one with
+ # non-zero size) is being included in the symbol file.
+ if(exists $syms{$addr})
+ { # an entry at this address exists, replace if it is an alias
+ if( ($size != 0) && ($addr > 0) )
+ {
+ if( ! defined $baseOffset )
+ {
+ $baseOffset = $addr;
+ }
+ $syms{$addr - $baseOffset} = "$size $sym $section";
+ }
+ }
+ else
+ { # no entry at this address so create one regardless of whether size is zero
+ if( $addr > 0 )
+ {
+ if( ! defined $baseOffset )
+ {
+ $baseOffset = $addr;
+ }
+ $syms{$addr - $baseOffset} = "$size $sym $section";
+ }
+ }
+
+ }
+ }
+
+ # Write symbols in address order
+ my @addrs = sort CompareAddrs keys %syms;
+ for ($i = 0; $i < @addrs ; $i++)
+ {
+ my $thisaddr = $addrs[$i];
+ printf SYM "%08x %s\n",
+ $thisaddr, $syms{$thisaddr};
+ }
+ }
+}
+
+sub ProcessGcceOrArm4File
+{
+ my ($file, $mapLines) = @_;
+ my @maplines = @$mapLines;
+ my %syms;
+ my $stubhex=1;
+
+ # Find text section
+ while (($_ = shift @maplines) && !(/^\.text\s+/))
+ {
+ }
+
+ /^\.text\s+(\w+)\s+\w+/ or die "ERROR: Can't get .text section info for \"$file\"\n";
+
+ my $imgtext=hex($1);
+
+ # Slurp symbols 'til the end of the text section
+ foreach (@maplines)
+ {
+
+ # blank line marks the end of the text section
+ last if (/^$/);
+
+ # .text <addr> <len> <library(member)>
+ # .text$something
+ # <addr> <len> <library(member)>
+ # <addr> <len> LONG 0x0
+
+ if (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io)
+ {
+ my $address = hex($2);
+ my $length = hex($3);
+ my $libraryfile = $4;
+ next if ($libraryfile =~ /^LONG 0x/);
+
+ $syms{$address+$length} = ' '; # impossible symbol as end marker
+
+ #set $stubhex value as $address if there is a match
+ if ($libraryfile =~ /.*lib\(.*d\d*s_?\d{5}.o\)$/io)
+ {
+ $stubhex=$address;
+ }
+ next;
+ }
+
+ # <addr> <symbol name possibly including spaces>
+ if (/^\s+(\w+)\s\s+([a-zA-Z_].+)/o)
+ {
+ my $addr = hex($1);
+ my $symbol = $2;
+ $symbol = "stub $symbol" if ($addr == $stubhex);
+ $syms{$addr} = $symbol;
+ next;
+ }
+ }
+
+ # Write symbols in address order
+ @addrs = sort CompareAddrs keys %syms;
+ for ($i = 0; $i < @addrs - 1; $i++)
+ {
+ my $symbol = $syms{$addrs[$i]};
+ next if ($symbol eq ' ');
+ printf SYM "%08x %04x %s\n",
+ $addrs[$i] - $imgtext, $addrs[$i+1]-$addrs[$i], $symbol;
+ }
+ # last address assumed to be imgtext+lentext
+
+ close MAP;
+}
+
+#
+# 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;
+ }
+ elsif ($flag=~/^d$/i)
+ {
+ $debug = 1;
+ }
+ else
+ {
+ print "\nERROR: Unknown flag \"-$flag\"\n";
+ &usage;
+ exit 1;
+ }
+ }
+ else
+ {
+ push @args,$arg;
+ }
+ }
+
+ if (@args)
+ {
+ $rofsbuild = shift @args;
+ if (@args)
+ {
+ $maksym = shift @args;
+ if (@args)
+ {
+ print "\nERROR: Incorrect argument(s) \"@args\"\n";
+ &usage;
+ exit 1;
+ }
+ }
+ }
+}
+
+sub help ()
+{
+ my $build;
+
+ &Load_ModuleL('E32TPVER');
+ print "\nmaksymrofs - Produce symbolic information given a ROFS image (Build ",
+ &E32tpver, ")\n";
+ &usage;
+ exit 0;
+}
+
+sub usage ()
+{
+ print <<EOF
+
+Usage:
+ maksymrofs <logfile> [<outfile>]
+
+Where:
+ <logfile> Log file from rofsbuild tool.
+ <outfile> Output file. Defaults to imagename.symbol.
+EOF
+ ;
+ exit 0;
+}
+
+sub GetSizeFromBinFile ()
+{
+ my ($file) = @_;
+ my $tmpfile = "temp.info";
+ system("readimage $file -o $tmpfile");
+ return 0 if (!-e $tmpfile);
+
+ open (TMP, "<$tmpfile");
+ my $line;
+ my $size = 0;
+ while ($line = <TMP>)
+ {
+ print $line;
+ if ($line =~ /^Code size\W+(\w+)$/)
+ {
+ $size = hex($1);
+ last;
+ }
+ }
+ close TMP;
+ unlink $tmpfile;
+ return $size;
+}
+