diff -r 820b22e13ff1 -r 39c28ec933dd imgtools/romtools/maksym/maksymrofs.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/maksym/maksymrofs.pl Mon May 10 19:54:49 2010 +0100 @@ -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 = ) + { + # 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 ($_ = ) + { + 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 + # .text$something + # + # 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; + } + + # + 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 < [] + +Where: + Log file from rofsbuild tool. + 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 = ) + { + print $line; + if ($line =~ /^Code size\W+(\w+)$/) + { + $size = hex($1); + last; + } + } + close TMP; + unlink $tmpfile; + return $size; +} +