-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfixup-rel
executable file
·132 lines (109 loc) · 2.46 KB
/
fixup-rel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/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";