fixup-rel
#!/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( <MAP> )
{
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";