imgtools/romtools/maksym/maksym.pl
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #
       
     2 # Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 # Produces symbolic information given a ROM image
       
    16 #
       
    17 
       
    18 require 5.003_07;
       
    19 no strict 'vars';
       
    20 use English;
       
    21 use FindBin;		# for FindBin::Bin
       
    22 
       
    23 my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
       
    24 
       
    25 BEGIN {
       
    26     # check user has a version of perl that will cope require 5.005_03;
       
    27     # establish the path to the Perl libraries: currently the same directory as this script
       
    28     $PerlLibPath = $FindBin::Bin; # X:/epoc32/tools
       
    29     $PerlLibPath =~ s/\//\\/g;	# X:\epoc32\tools
       
    30     $PerlLibPath .= "\\";
       
    31 }
       
    32 
       
    33 use lib $PerlLibPath;
       
    34 use Modload;
       
    35 Load_SetModulePath($PerlLibPath);
       
    36 
       
    37 # Globals
       
    38 my $maksym = "";
       
    39 my $rombuild;
       
    40 my $debug = 0;
       
    41 
       
    42 &args;
       
    43 &main;
       
    44 
       
    45 exit 0;
       
    46 
       
    47 sub CompareAddrs()
       
    48 {
       
    49     return -1 if ($a < $b);
       
    50     return 1 if ($a > $b);
       
    51     return 0;
       
    52 }
       
    53 
       
    54 #
       
    55 # main
       
    56 #
       
    57 sub main()
       
    58 {
       
    59   my $file;
       
    60   my $mapfile;
       
    61   my $mapfile2;
       
    62   my $text;
       
    63   my $data;
       
    64   my $bss;
       
    65   my $textsize;
       
    66   my $datasize;
       
    67   my $bsssize;
       
    68   my $totaldatasize;
       
    69   my $totalsize;
       
    70 
       
    71   open (ROM, "<$rombuild")
       
    72     or die "ERROR: Can't open rombuild log file \"$rombuild\"\n";
       
    73   if ($maksym ne "") {
       
    74     open (SYM, ">$maksym")
       
    75       or die "ERROR: Can't open output file \"$maksym\"\n";
       
    76     print "Creating $maksym...\n";
       
    77   }
       
    78 
       
    79   while (<ROM>) {
       
    80     # Start of ROM
       
    81     if (/^Creating Rom image (\S*)/) {
       
    82       if ($maksym eq "") {
       
    83 	# For backwards compatibility, replace trailing .img with .symbol
       
    84 	# if no trailing .img, just append .symbol anyway
       
    85 	$maksym = $1;
       
    86 	$maksym =~ s/(\.img)?$/.symbol/i;
       
    87 	close SYM;
       
    88 	open (SYM, ">$maksym")
       
    89 	  or die "ERROR: Can't open output file \"$maksym\"\n";
       
    90 	print "\nCreating $maksym...\n";
       
    91       }
       
    92       next;
       
    93     }
       
    94     # end of ROM
       
    95     if (/^Writing Rom image/) {
       
    96       close SYM;
       
    97       $maksym = "";
       
    98       next;
       
    99     }
       
   100     # Data file
       
   101     if (/^Reading resource (.*) to rom linear address (.*)/) {
       
   102       $file = $1;
       
   103       my $data = hex($2);
       
   104       $file =~ /([^\\]+)$/;
       
   105       printf SYM "\nFrom    $file\n\n%08x    0000    $1\n", $data;
       
   106     }
       
   107     # Executable file
       
   108     elsif (/^Processing file (.*)/) {
       
   109       $file = $1;
       
   110       $text = 0;
       
   111       $data = 0;
       
   112       $bss = 0;
       
   113       $textsize = 0;
       
   114       $datasize = 0;
       
   115       $bsssize = 0;
       
   116       $totaldatasize = 0;
       
   117 
       
   118       # Work out final addresses of sections
       
   119       while (defined($_=<ROM>) && !/^$/) {
       
   120 	if (/^Size:\s+(\w+)/) {
       
   121 	  $totalsize = hex($1);
       
   122 	} elsif (/^Code start addr:\s+(\w+)/) {
       
   123 	  $text = hex($1);
       
   124 	} elsif (/^Data start addr:\s+(\w+)/) {
       
   125 	  $data = hex($1);
       
   126 	} elsif (/^DataBssLinearBase:\s+(\w+)/) {
       
   127 	  $bss = hex($1);
       
   128 	} elsif (/^Text size:\s+(\w+)/) {
       
   129 	  $textsize = hex($1);
       
   130 	} elsif (/^Data size:\s+(\w+)/) {
       
   131 	  $datasize = hex($1);
       
   132 	} elsif (/^Bsssize:\s+(\w+)/) {
       
   133 	  $bsssize = hex($1);
       
   134 	} elsif (/^Total data size:\s+(\w+)/) {
       
   135 	  $totaldatasize = hex($1);
       
   136 	}
       
   137       }
       
   138 
       
   139       # Sanity check - text section can't be zero
       
   140       die "ERROR: Can't find rombuild info for \"$file\"\n"
       
   141 	if (!$text);
       
   142 
       
   143       print SYM "\nFrom    $file\n\n";
       
   144 
       
   145       # Look in map file for symbols in .text and relocate them
       
   146       $mapfile2 = $file.".map";
       
   147       $mapfile = $file;
       
   148       $mapfile =~ s/\.\w+$/\.map/;
       
   149       if (!(open (MAP, "$mapfile2") || open (MAP, "$mapfile"))) {
       
   150 	print "$file\nWarning: Can't open \"$mapfile2\" or \"$mapfile\"\n";
       
   151 	$file =~ /([^\\]+)$/;
       
   152 	printf SYM "%08x    %04x    $1\n", $text, $totalsize;
       
   153       } else {
       
   154 	local $/ = undef;
       
   155 	my (@maplines) = split(/\n/, <MAP>);
       
   156 	close MAP;
       
   157 	# See if we're dealing with the RVCT output
       
   158 	if ($maplines[0] =~ /^ARM Linker/) {
       
   159 	  print "$file\n";
       
   160 	 
       
   161 		my %syms;
       
   162 		my @hasharray;
       
   163 		# Starts from begining of map file.		
       
   164 		while (@maplines) {
       
   165 		  $_ = shift @maplines;
       
   166 		  if (/Global Symbols/) {
       
   167 		    last;
       
   168 		  } elsif (!/(ARM Code|Thumb Code)/) {
       
   169 		    next;
       
   170 		  }
       
   171 		# name address type size section
       
   172 		if (/^\s*(.+)\s*(0x\S+)\s+(ARM Code|Thumb Code)\s+[^\d]*(\d+)\s+(.*)$/) {
       
   173 			# Check for static methods in local symbols section.
       
   174 			my $sym = $1;
       
   175 			my $addr = hex($2);
       
   176 			my $size = sprintf("%04x",$4);
       
   177 			my $section = $5;
       
   178 			$size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/);
       
   179 			if(exists($syms{$addr})) {
       
   180 				push @{ $syms{$addr} }, "$size    $sym $section";	   
       
   181 			}
       
   182 			elsif ($addr > 0){
       
   183 				@hasharray = "$size    $sym $section";
       
   184 				$syms{$addr} = [@hasharray];
       
   185 			}
       
   186 		}
       
   187 		}	
       
   188 	
       
   189 	  foreach (@maplines) {
       
   190 	    # name address ignore size section
       
   191 	    if (/^\s*(.+)\s*(0x\S+)\s+[^\d]*(\d+)\s+(.*)$/) {
       
   192 	      my $sym = $1;
       
   193 	      my $addr = hex($2);
       
   194 	      my $size = sprintf("%04x",$3);
       
   195 	      my $section = $4;
       
   196 	      $size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/);
       
   197 		  if(exists($syms{$addr})) {
       
   198 			push @{ $syms{$addr} }, "$size    $sym $section";	   
       
   199 		  }
       
   200 	      elsif ($addr > 0) {
       
   201 			@hasharray = "$size    $sym $section"; 
       
   202 			$syms{$addr} = [@hasharray];
       
   203 		  }
       
   204 	    }
       
   205 	  } # end of foreach
       
   206 
       
   207 	  # .text gets linked at 0x00008000
       
   208 	  # .data gets linked at 0x00400000
       
   209 	  my $srctext = hex(8000);
       
   210 	  my $srcdata = hex(400000);
       
   211 	  my $j; 
       
   212 	  # Write symbols in address order
       
   213 	  my @addrs = sort CompareAddrs keys %syms;
       
   214 	  for ($i = 0; $i < @addrs ; $i++) {
       
   215 	    my $thisaddr = $addrs[$i];
       
   216 	    my $romaddr = 0;
       
   217 	    # see if its in the text segment
       
   218 		if ($thisaddr >= $srctext && $thisaddr <= ($srctext+$textsize)) {
       
   219 	      $romaddr = $thisaddr-$srctext+$text;
       
   220 	    } elsif ( $data && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$datasize))) {
       
   221 	      # its in the data segment
       
   222 	      # is it from .data or .bss
       
   223 
       
   224   			# confusingly (?) $bss is the right value to use here
       
   225 			# since we're interested in where the data gets copied to
       
   226 			# in RAM rather than where it sits in ROM
       
   227 		$romaddr = $thisaddr-$srcdata+$bss;
       
   228 	      } elsif ( $bss && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$totaldatasize))) {
       
   229 				# its BSS
       
   230 		$romaddr = $thisaddr-$srcdata+$bss;
       
   231 	      } else {
       
   232 		my $errsym = $syms{$thisaddr}[0];
       
   233 		my $erraddr = sprintf("%08x", $thisaddr);
       
   234 		print "WARNING: Symbol $errsym @ $erraddr not in text or data segments\n";
       
   235 		print "WARNING: The map file for binary $file is out-of-sync with the binary itself\n\n";
       
   236 		next;
       
   237 	      }
       
   238 
       
   239 	    printf SYM "%08x    %s\n", $romaddr, $_ for @{$syms{$addrs[$i]}};
       
   240 	  } # end of for.
       
   241         # See if we're dealing with the GCC output
       
   242 	} elsif ($maplines[0] =~ /^Archive member included/) {
       
   243 	  
       
   244 	  my $imgtext;
       
   245 	  my $textlen;
       
   246 	  my %syms;
       
   247 	  my $stubhex=1;
       
   248 
       
   249 	  # Find text section
       
   250 	  while (@maplines) {
       
   251 	      $_ = shift @maplines;
       
   252 	      last if /^\.text\s+/;
       
   253 	  }
       
   254 
       
   255 	  /^\.text\s+(\w+)\s+(\w+)/
       
   256 			or die "ERROR: Can't get .text section info for \"$file\"\n";
       
   257 
       
   258 		    $imgtext=hex($1);
       
   259 		    $textlen=hex($2);
       
   260 
       
   261 		    print "$file\n";
       
   262 
       
   263 		# Slurp symbols 'til the end of the text section
       
   264 		foreach (@maplines) {
       
   265 
       
   266 			# blank line marks the end of the text section
       
   267 			last if (/^$/);
       
   268 
       
   269 			# .text <addr> <len>  <library(member)>
       
   270 			# .text$something
       
   271 			#       <addr> <len>  <library(member)>
       
   272 			#       <addr> <len>  LONG 0x0
       
   273 
       
   274 			if (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io) {
       
   275 				my $address = hex($2);
       
   276 				my $length = hex($3);
       
   277 				my $libraryfile = $4;
       
   278 				next if ($libraryfile =~ /^LONG 0x/);
       
   279 				$syms{$address+$length} = ' ';	# impossible symbol as end marker
       
   280 
       
   281 				# EUSER.LIB(ds01423.o)
       
   282 				# EUSER.LIB(C:/TEMP/d1000s_01423.o)
       
   283 				if ($libraryfile =~ /.*lib\(.*d\d*s_?\d{5}.o\)$/io) {
       
   284 					$stubhex=$address;
       
   285 				}
       
   286 				next;
       
   287 			}
       
   288 
       
   289 			#  <addr>  <symbol name possibly including spaces>
       
   290 			if (/^\s+(\w+)\s\s+([a-zA-Z_].+)/o) {
       
   291 				my $addr = hex($1);
       
   292 				my $symbol = $2;
       
   293 				$symbol = "stub $symbol" if ($addr == $stubhex);
       
   294 				$syms{$addr} = $symbol;
       
   295 				next;
       
   296 			}
       
   297 		}
       
   298 
       
   299 		# Write symbols in address order
       
   300 		@addrs = sort CompareAddrs keys %syms;
       
   301 		for ($i = 0; $i < @addrs - 1; $i++) {
       
   302 			my $symbol = $syms{$addrs[$i]};
       
   303 			next if ($symbol eq ' ');
       
   304 			printf SYM "%08x    %04x    %s\n",
       
   305 			$addrs[$i]-$imgtext+$text, $addrs[$i+1]-$addrs[$i], $symbol;
       
   306 		}
       
   307 		# last address assumed to be imgtext+lentext
       
   308 
       
   309 		close MAP;
       
   310 	}
       
   311 	# Must be x86 output
       
   312 	else {
       
   313 		while (@maplines) {
       
   314 	      $_ = shift @maplines;
       
   315 	      last if /^  Address/;
       
   316 		}
       
   317 	    shift @maplines;
       
   318 	    
       
   319 	    my ($lastname, $lastaddr);
       
   320 		while (@maplines) {
       
   321 	      $_ = shift @maplines;
       
   322 	      last unless /^ 0001:(\w+)\s+(\S+)/;
       
   323 		  my ($addr, $name) = (hex $1, $2);
       
   324 		  if ($lastname) {
       
   325 			  my $size = $addr - $lastaddr;
       
   326 			  printf SYM "%08x    %04x    %s\n", $lastaddr + $text, $size, $lastname;
       
   327 		  }
       
   328 		  ($lastname, $lastaddr) = ($name, $addr);
       
   329 	    }	    
       
   330 	    printf SYM "%08x    %04x    %s\n", $lastaddr + $text, 0, $lastname if $lastname;
       
   331 	}
       
   332 	
       
   333 	    }
       
   334 	  }
       
   335 	}
       
   336     close SYM;
       
   337     close ROM;
       
   338 }
       
   339 
       
   340 #
       
   341 # args - get command line args
       
   342 #
       
   343 sub args
       
   344 {
       
   345     my $arg;
       
   346     my @args;
       
   347     my $flag;
       
   348 
       
   349     &help if (!@ARGV);
       
   350 
       
   351     while (@ARGV) {
       
   352 	$arg = shift @ARGV;
       
   353 
       
   354 	if ($arg=~/^[\-\/](\S*)$/) {
       
   355 	    $flag=$1;
       
   356 
       
   357 	    if ($flag=~/^[\?h]$/i) {
       
   358 		&help;
       
   359 	    } elsif ($flag=~/^d$/i) {
       
   360 		$debug = 1;
       
   361 	    } else {
       
   362 		print "\nERROR: Unknown flag \"-$flag\"\n";
       
   363 		&usage;
       
   364 		exit 1;
       
   365 	    }
       
   366 	} else {
       
   367 	    push @args,$arg;
       
   368 	}
       
   369     }
       
   370 
       
   371     if (@args) {
       
   372 	$rombuild = shift @args;
       
   373 	if (@args) {
       
   374 	    $maksym = shift @args;
       
   375 	    if (@args) {
       
   376 		print "\nERROR: Incorrect argument(s) \"@args\"\n";
       
   377 		&usage;
       
   378 		exit 1;
       
   379 	    }
       
   380 	}
       
   381     }
       
   382 }
       
   383 
       
   384 sub help ()
       
   385 {
       
   386     my $build;
       
   387 
       
   388     &Load_ModuleL('E32TPVER');
       
   389     print "\nmaksym - Produce symbolic information given a ROM image (Build ",
       
   390 	&E32tpver, ")\n";
       
   391     &usage;
       
   392     exit 0;
       
   393 }
       
   394 
       
   395 sub usage ()
       
   396 {
       
   397     print <<EOF
       
   398 
       
   399 Usage:
       
   400   maksym <logfile> [<outfile>]
       
   401 
       
   402 Where:
       
   403   <logfile>   Log file from rombuild tool.
       
   404   <outfile>   Output file. Defaults to imagename.symbol.
       
   405 EOF
       
   406     ;
       
   407     exit 0;
       
   408 }