imgtools/romtools/maksym/maksym.pl
changeset 694 c3fbb20e86f0
parent 590 360bd6b35136
child 714 e5a58c351011
equal deleted inserted replaced
692:1dfff72f0961 694:c3fbb20e86f0
    17 
    17 
    18 require 5.003_07;
    18 require 5.003_07;
    19 no strict 'vars';
    19 no strict 'vars';
    20 use English;
    20 use English;
    21 use FindBin;		# for FindBin::Bin
    21 use FindBin;		# for FindBin::Bin
       
    22 use File::Copy;
    22 
    23 
    23 # Version
    24 # Version
    24 my $MajorVersion = 1;
    25 my $MajorVersion = 1;
    25 my $MinorVersion = 1;
    26 my $MinorVersion = 1;
    26 my $PatchVersion = 0;
    27 my $PatchVersion = 0;
    45 #
    46 #
    46 # main
    47 # main
    47 #
    48 #
    48 sub main()
    49 sub main()
    49 {
    50 {
    50   my $file;
    51   my $symbolfile = $rombuild;
    51   my $mapfile;
    52   $symbolfile =~ s/\.log$/\.symbol/i;
    52   my $mapfile2;
    53   my @cmdres = `rombuild -loginput=$rombuild`;
    53   my $text;
    54   print "@cmdres\n";
    54   my $data;
       
    55   my $bss;
       
    56   my $textsize;
       
    57   my $datasize;
       
    58   my $bsssize;
       
    59   my $totaldatasize;
       
    60   my $totalsize;
       
    61 
    55 
    62   open (ROM, "<$rombuild")
    56   if(($maksym ne "") && ($maksym ne $symbolfile))
    63     or die "ERROR: Can't open rombuild log file \"$rombuild\"\n";
    57   {
    64   if ($maksym ne "") {
    58 	  copy($symbolfile, $maksym);
    65     open (SYM, ">$maksym")
    59 	  unlink $symbolfile;
    66       or die "ERROR: Can't open output file \"$maksym\"\n";
       
    67     print "Creating $maksym...\n";
       
    68   }
    60   }
    69 
       
    70   while (<ROM>) {
       
    71     # Start of ROM
       
    72     if (/^Creating Rom image (\S*)/) {
       
    73       if ($maksym eq "") {
       
    74 	# For backwards compatibility, replace trailing .img with .symbol
       
    75 	# if no trailing .img, just append .symbol anyway
       
    76 	$maksym = $1;
       
    77 	$maksym =~ s/(\.img)?$/.symbol/i;
       
    78 	close SYM;
       
    79 	open (SYM, ">$maksym")
       
    80 	  or die "ERROR: Can't open output file \"$maksym\"\n";
       
    81 	print "\nCreating $maksym...\n";
       
    82       }
       
    83       next;
       
    84     }
       
    85     # end of ROM
       
    86     if (/^Writing Rom image/) {
       
    87       close SYM;
       
    88       $maksym = "";
       
    89       next;
       
    90     }
       
    91     # Data file
       
    92     if (/^Reading resource (.*) to rom linear address (.*)/) {
       
    93       $file = $1;
       
    94       my $data = hex($2);
       
    95       $file =~ /([^\\]+)$/;
       
    96       printf SYM "\nFrom    $file\n\n%08x    0000    $1\n", $data;
       
    97     }
       
    98     # Executable file
       
    99     elsif (/^Processing file (.*)/) {
       
   100       $file = $1;
       
   101       $text = 0;
       
   102       $data = 0;
       
   103       $bss = 0;
       
   104       $textsize = 0;
       
   105       $datasize = 0;
       
   106       $bsssize = 0;
       
   107       $totaldatasize = 0;
       
   108 
       
   109       # Work out final addresses of sections
       
   110       while (defined($_=<ROM>) && !/^$/) {
       
   111 	if (/^Size:\s+(\w+)/) {
       
   112 	  $totalsize = hex($1);
       
   113 	} elsif (/^Code start addr:\s+(\w+)/) {
       
   114 	  $text = hex($1);
       
   115 	} elsif (/^Data start addr:\s+(\w+)/) {
       
   116 	  $data = hex($1);
       
   117 	} elsif (/^DataBssLinearBase:\s+(\w+)/) {
       
   118 	  $bss = hex($1);
       
   119 	} elsif (/^Text size:\s+(\w+)/) {
       
   120 	  $textsize = hex($1);
       
   121 	} elsif (/^Data size:\s+(\w+)/) {
       
   122 	  $datasize = hex($1);
       
   123 	} elsif (/^Bsssize:\s+(\w+)/) {
       
   124 	  $bsssize = hex($1);
       
   125 	} elsif (/^Total data size:\s+(\w+)/) {
       
   126 	  $totaldatasize = hex($1);
       
   127 	}
       
   128       }
       
   129 
       
   130       # Sanity check - text section can't be zero
       
   131       die "ERROR: Can't find rombuild info for \"$file\"\n"
       
   132 	if (!$text);
       
   133 
       
   134       print SYM "\nFrom    $file\n\n";
       
   135 
       
   136       # Look in map file for symbols in .text and relocate them
       
   137       $mapfile2 = $file.".map";
       
   138       $mapfile = $file;
       
   139       $mapfile =~ s/\.\w+$/\.map/;
       
   140       if (!(open (MAP, "$mapfile2") || open (MAP, "$mapfile"))) {
       
   141 	print "$file\nWarning: Can't open \"$mapfile2\" or \"$mapfile\"\n";
       
   142 	$file =~ /([^\\]+)$/;
       
   143 	printf SYM "%08x    %04x    $1\n", $text, $totalsize;
       
   144       } else {
       
   145 	local $/ = undef;
       
   146 	my (@maplines) = split(/\n/, <MAP>);
       
   147 	close MAP;
       
   148 	# See if we're dealing with the RVCT output
       
   149 	if ($maplines[0] =~ /^ARM Linker/) {
       
   150 	  print "$file\n";
       
   151 	 
       
   152 		my %syms;
       
   153 		my @hasharray;
       
   154 		# Starts from begining of map file.		
       
   155 		while (@maplines) {
       
   156 		  $_ = shift @maplines;
       
   157 		  if (/Global Symbols/) {
       
   158 		    last;
       
   159 		  } elsif (!/(ARM Code|Thumb Code)/) {
       
   160 		    next;
       
   161 		  }
       
   162 		# name address type size section
       
   163 		if (/^\s*(.+)\s*(0x\S+)\s+(ARM Code|Thumb Code)\s+[^\d]*(\d+)\s+(.*)$/) {
       
   164 			# Check for static methods in local symbols section.
       
   165 			my $sym = $1;
       
   166 			my $addr = hex($2);
       
   167 			my $size = sprintf("%04x",$4);
       
   168 			my $section = $5;
       
   169 			$size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/);
       
   170 			if(exists($syms{$addr})) {
       
   171 				push @{ $syms{$addr} }, "$size    $sym $section";	   
       
   172 			}
       
   173 			elsif ($addr > 0){
       
   174 				@hasharray = "$size    $sym $section";
       
   175 				$syms{$addr} = [@hasharray];
       
   176 			}
       
   177 		}
       
   178 		}	
       
   179 	
       
   180 	  foreach (@maplines) {
       
   181 	    # name address ignore size section
       
   182 	    if (/^\s*(.+)\s*(0x\S+)\s+[^\d]*(\d+)\s+(.*)$/) {
       
   183 	      my $sym = $1;
       
   184 	      my $addr = hex($2);
       
   185 	      my $size = sprintf("%04x",$3);
       
   186 	      my $section = $4;
       
   187 	      $size = sprintf("%04x", 8) if ($section =~ /\(StubCode\)/);
       
   188 		  if(exists($syms{$addr})) {
       
   189 			push @{ $syms{$addr} }, "$size    $sym $section";	   
       
   190 		  }
       
   191 	      elsif ($addr > 0) {
       
   192 			@hasharray = "$size    $sym $section"; 
       
   193 			$syms{$addr} = [@hasharray];
       
   194 		  }
       
   195 	    }
       
   196 	  } # end of foreach
       
   197 
       
   198 	  # .text gets linked at 0x00008000
       
   199 	  # .data gets linked at 0x00400000
       
   200 	  my $srctext = hex(8000);
       
   201 	  my $srcdata = hex(400000);
       
   202 	  my $j; 
       
   203 	  # Write symbols in address order
       
   204 	  my @addrs = sort CompareAddrs keys %syms;
       
   205 	  for ($i = 0; $i < @addrs ; $i++) {
       
   206 	    my $thisaddr = $addrs[$i];
       
   207 	    my $romaddr = 0;
       
   208 	    # see if its in the text segment
       
   209 		if ($thisaddr >= $srctext && $thisaddr <= ($srctext+$textsize)) {
       
   210 	      $romaddr = $thisaddr-$srctext+$text;
       
   211 	    } elsif ( $data && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$datasize))) {
       
   212 	      # its in the data segment
       
   213 	      # is it from .data or .bss
       
   214 
       
   215   			# confusingly (?) $bss is the right value to use here
       
   216 			# since we're interested in where the data gets copied to
       
   217 			# in RAM rather than where it sits in ROM
       
   218 		$romaddr = $thisaddr-$srcdata+$bss;
       
   219 	      } elsif ( $bss && ( $thisaddr >= $srcdata && $thisaddr <= ($srcdata+$totaldatasize))) {
       
   220 				# its BSS
       
   221 		$romaddr = $thisaddr-$srcdata+$bss;
       
   222 	      } else {
       
   223 		my $errsym = $syms{$thisaddr}[0];
       
   224 		my $erraddr = sprintf("%08x", $thisaddr);
       
   225 		print "WARNING: Symbol $errsym @ $erraddr not in text or data segments\n";
       
   226 		print "WARNING: The map file for binary $file is out-of-sync with the binary itself\n\n";
       
   227 		next;
       
   228 	      }
       
   229 
       
   230 	    printf SYM "%08x    %s\n", $romaddr, $_ for @{$syms{$addrs[$i]}};
       
   231 	  } # end of for.
       
   232         # See if we're dealing with the GCC output
       
   233 	} elsif ($maplines[0] =~ /^Archive member included/) {
       
   234 	  
       
   235 	  my $imgtext;
       
   236 	  my $textlen;
       
   237 	  my %syms;
       
   238 	  my $stubhex=1;
       
   239 
       
   240 	  # Find text section
       
   241 	  while (@maplines) {
       
   242 	      $_ = shift @maplines;
       
   243 	      last if /^\.text\s+/;
       
   244 	  }
       
   245 
       
   246 	  /^\.text\s+(\w+)\s+(\w+)/
       
   247 			or die "ERROR: Can't get .text section info for \"$file\"\n";
       
   248 
       
   249 		    $imgtext=hex($1);
       
   250 		    $textlen=hex($2);
       
   251 
       
   252 		    print "$file\n";
       
   253 
       
   254 		# Slurp symbols 'til the end of the text section
       
   255 		foreach (@maplines) {
       
   256 
       
   257 			# blank line marks the end of the text section
       
   258 			last if (/^$/);
       
   259 
       
   260 			# .text <addr> <len>  <library(member)>
       
   261 			# .text$something
       
   262 			#       <addr> <len>  <library(member)>
       
   263 			#       <addr> <len>  LONG 0x0
       
   264 
       
   265 			if (/^\s(\.text)?\s+(0x\w+)\s+(0x\w+)\s+(.*)$/io) {
       
   266 				my $address = hex($2);
       
   267 				my $length = hex($3);
       
   268 				my $libraryfile = $4;
       
   269 				next if ($libraryfile =~ /^LONG 0x/);
       
   270 				$syms{$address+$length} = ' ';	# impossible symbol as end marker
       
   271 
       
   272 				# EUSER.LIB(ds01423.o)
       
   273 				# EUSER.LIB(C:/TEMP/d1000s_01423.o)
       
   274 				if ($libraryfile =~ /.*lib\(.*d\d*s_?\d{5}.o\)$/io) {
       
   275 					$stubhex=$address;
       
   276 				}
       
   277 				next;
       
   278 			}
       
   279 
       
   280 			#  <addr>  <symbol name possibly including spaces>
       
   281 			if (/^\s+(\w+)\s\s+([a-zA-Z_].+)/o) {
       
   282 				my $addr = hex($1);
       
   283 				my $symbol = $2;
       
   284 				$symbol = "stub $symbol" if ($addr == $stubhex);
       
   285 				$syms{$addr} = $symbol;
       
   286 				next;
       
   287 			}
       
   288 		}
       
   289 
       
   290 		# Write symbols in address order
       
   291 		@addrs = sort CompareAddrs keys %syms;
       
   292 		for ($i = 0; $i < @addrs - 1; $i++) {
       
   293 			my $symbol = $syms{$addrs[$i]};
       
   294 			next if ($symbol eq ' ');
       
   295 			printf SYM "%08x    %04x    %s\n",
       
   296 			$addrs[$i]-$imgtext+$text, $addrs[$i+1]-$addrs[$i], $symbol;
       
   297 		}
       
   298 		# last address assumed to be imgtext+lentext
       
   299 
       
   300 		close MAP;
       
   301 	}
       
   302 	# Must be x86 output
       
   303 	else {
       
   304 		while (@maplines) {
       
   305 	      $_ = shift @maplines;
       
   306 	      last if /^  Address/;
       
   307 		}
       
   308 	    shift @maplines;
       
   309 	    
       
   310 	    my ($lastname, $lastaddr);
       
   311 		while (@maplines) {
       
   312 	      $_ = shift @maplines;
       
   313 	      last unless /^ 0001:(\w+)\s+(\S+)/;
       
   314 		  my ($addr, $name) = (hex $1, $2);
       
   315 		  if ($lastname) {
       
   316 			  my $size = $addr - $lastaddr;
       
   317 			  printf SYM "%08x    %04x    %s\n", $lastaddr + $text, $size, $lastname;
       
   318 		  }
       
   319 		  ($lastname, $lastaddr) = ($name, $addr);
       
   320 	    }	    
       
   321 	    printf SYM "%08x    %04x    %s\n", $lastaddr + $text, 0, $lastname if $lastname;
       
   322 	}
       
   323 	
       
   324 	    }
       
   325 	  }
       
   326 	}
       
   327     close SYM;
       
   328     close ROM;
       
   329 }
    61 }
   330 
    62 
   331 #
    63 #
   332 # args - get command line args
    64 # args - get command line args
   333 #
    65 #