#!/usr/bin/perl use warnings; use strict; # Read the map file my %syms; my $map_file = shift; open MAP, "<$map_file" or die "$map_file: Unable to open: $!\n"; while( ) { my ($pc,$name) = /:([0-9A-Fa-f]+)\s*([^\s]+)/ or next; $pc = hex $pc; $syms{$pc} = $name; } # Generate a sorted list of symbols my @syms = map { [ $_ => $syms{$_} ] } sort { $a <=> $b } keys %syms; sub sym_lookup { my $pc = shift; return unless exists $syms{$pc}; return $syms{$pc}; } sub sym_lookup_approx { my $pc = shift; return if $pc < 1024; # Do a linear search for it for( my $i = 1 ; $i < @syms ; $i++ ) { my $sym_pc = $syms[$i]->[0]; next unless $sym_pc > $pc; $sym_pc = $syms[$i-1]->[0]; my $sym = $syms[$i-1]->[1]; return $sym if $sym_pc == $pc; return sprintf "%s+0x%x", $sym, $pc - $sym_pc; } return; } # Now read the list file while(<>) { chomp; my ($pc,$hex,$instr,$args) = / ^\s* ([0-9a-f]+): # pc \s+ ([0-9a-f]+) # hex \s+ ([^\s]+) # instruction \s* (.*) # args #(?:\s*;.*)? # comment $ /msgx or next; $pc = hex $pc; $hex = hex $hex; # Look for add instructions with pc relative, since those do not # get translated correctly. if( $instr =~ /^add/ and $args =~ /pc, #/ ) { # Strip any comment off the args $args =~ s/\s*;.*$//; my @args = split /,\s*/, $args; $args[2] =~ s/^#//; my $result = $pc + $args[2] + 8; $args .= sprintf " ; 0x%x", $result; } # Look for sub instructions with pc relative, since those do not # get translated correctly. if( $instr =~ /^sub/ and $args =~ /pc, #/ ) { # Strip any comment off the args $args =~ s/\s*;.*$//; my @args = split /,\s*/, $args; $args[2] =~ s/^#//; my $result = $pc - $args[2] + 8; $args .= sprintf " ; 0x%x", $result; } # Check to see if a branch instruction has a symbol # and it does not make a register indirect call if( $instr =~ /^b/ and $args =~ /^[0-9A-Fa-f]/ ) { my $sym = sym_lookup_approx( hex $args ); $args .= " $sym" if $sym; } my $sym = sym_lookup( $pc ); printf "\n%s()\n", $sym if $sym; # Check to see if a coment has an symbol? my ($comment_addr) = $args =~ /;\s+([0-9A-Fa-fx]+)/; if( $comment_addr ) { $comment_addr = hex $comment_addr; my $sym = sym_lookup_approx( $comment_addr ); $args .= " $sym" if $sym; } my $asc; for my $i (0..3) { my $c = chr( ($hex >> (8*$i)) & 0xFF ); $asc .= ($c =~ /[[:print:]]/) ? $c : '.'; } printf "%08x: %08x %s\t%s\t%s\n", $pc, $hex, $asc, $instr,$args; } print "\n";