diff options
Diffstat (limited to 'utils/analysis')
-rwxr-xr-x | utils/analysis/find_addr.pl | 105 |
1 files changed, 100 insertions, 5 deletions
diff --git a/utils/analysis/find_addr.pl b/utils/analysis/find_addr.pl index 2dcc84ab8a..dca85fdbdc 100755 --- a/utils/analysis/find_addr.pl +++ b/utils/analysis/find_addr.pl | |||
@@ -18,6 +18,7 @@ | |||
18 | # KIND, either express or implied. | 18 | # KIND, either express or implied. |
19 | # | 19 | # |
20 | use String::Scanf; | 20 | use String::Scanf; |
21 | use Cwd; | ||
21 | 22 | ||
22 | sub check_boundaries | 23 | sub check_boundaries |
23 | { | 24 | { |
@@ -33,15 +34,59 @@ sub check_boundaries | |||
33 | return 0; | 34 | return 0; |
34 | } | 35 | } |
35 | 36 | ||
37 | sub dynamic_space | ||
38 | { | ||
39 | my $space = $_[0], $space_array = $_[1], $ret; | ||
40 | |||
41 | printf "This address is in %s space, please select the %s which was used with this address:\n", $space, $space; | ||
42 | $count = 1; | ||
43 | foreach my $el (@$space_array) | ||
44 | { | ||
45 | printf " [%d]: %s\n", $count++, $el; | ||
46 | } | ||
47 | |||
48 | print "\n"; | ||
49 | my $sel = -1; | ||
50 | do | ||
51 | { | ||
52 | print "Selection: "; | ||
53 | $sel = <STDIN>; | ||
54 | } while($sel <= 0 || $sel > $count - 1 || !($sel =~ /^[+-]?\d+$/)); | ||
55 | |||
56 | my $file = sprintf("apps/%ss/%s", $space, @$space_array[$sel - 1]); | ||
57 | $ret{'library'} = sprintf("%s/%s", cwd(), $file); | ||
58 | open FILE, "$objdump -t $file |" or die "Can't open pipe: $!"; | ||
59 | while(<FILE>) | ||
60 | { | ||
61 | chomp($_); | ||
62 | if(/^([0-9a-fA-F]+).+\s([0-9a-fA-F]{3,})\s(?:[^\s]+\s)?(.+)$/) | ||
63 | { | ||
64 | (my $addr) = sscanf("%lx", $1); | ||
65 | (my $size) = sscanf("%lx", $2); | ||
66 | |||
67 | if($lookaddr >= $addr && $lookaddr <= ($addr + $size)) | ||
68 | { | ||
69 | my $diff = abs($lookaddr - $addr); | ||
70 | if(!defined($ret{'diff'}) || $diff <= $ret{'diff'}) | ||
71 | { | ||
72 | $ret{'diff'} = $diff; | ||
73 | $ret{'function'} = $3; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | close FILE; | ||
79 | |||
80 | return %ret; | ||
81 | } | ||
82 | |||
36 | ($lookaddr) = sscanf("0x%lx", $ARGV[0]); | 83 | ($lookaddr) = sscanf("0x%lx", $ARGV[0]); |
37 | ($context_size) = $#ARGV > 0 ? $ARGV[1] : 5; | 84 | ($context_size) = $#ARGV > 0 ? $ARGV[1] : 5; |
38 | 85 | ||
39 | if($lookaddr != 0) | 86 | if($lookaddr != 0) |
40 | { | 87 | { |
41 | # Determine the used objdump utility | 88 | # Determine the used objdump utility |
42 | |||
43 | open MAKEFILE, "<Makefile" or die "Can't open Makefile: $!"; | 89 | open MAKEFILE, "<Makefile" or die "Can't open Makefile: $!"; |
44 | my $objdump; | ||
45 | while(<MAKEFILE>) | 90 | while(<MAKEFILE>) |
46 | { | 91 | { |
47 | chomp($_); | 92 | chomp($_); |
@@ -54,8 +99,29 @@ if($lookaddr != 0) | |||
54 | } | 99 | } |
55 | close MAKEFILE; | 100 | close MAKEFILE; |
56 | 101 | ||
102 | # Generate a list of all codecs | ||
103 | open FINDCODECS, "find apps/codecs/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!"; | ||
104 | my @codecs; | ||
105 | while(<FINDCODECS>) | ||
106 | { | ||
107 | chomp($_); | ||
108 | $_ =~ s/apps\/codecs\///; | ||
109 | push(@codecs, $_); | ||
110 | } | ||
111 | close FINDCODECS; | ||
112 | # Generate a list of all plugins | ||
113 | open FINDPLUGINS, "find apps/plugins/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!"; | ||
114 | my @plugins; | ||
115 | while(<FINDPLUGINS>) | ||
116 | { | ||
117 | chomp($_); | ||
118 | $_ =~ s/apps\/plugins\///; | ||
119 | push(@plugins, $_); | ||
120 | } | ||
121 | close FINDPLUGINS; | ||
122 | |||
57 | open MAPFILE, "<rockbox.map" or die "Can't open rockbox.map: $!"; | 123 | open MAPFILE, "<rockbox.map" or die "Can't open rockbox.map: $!"; |
58 | my $addr, $size, $library, $match, $prev_function; | 124 | my $addr, $size, $library, $match, $prev_function, $codec_addr, $plugin_addr; |
59 | while(<MAPFILE>) | 125 | while(<MAPFILE>) |
60 | { | 126 | { |
61 | chomp($_); | 127 | chomp($_); |
@@ -65,6 +131,20 @@ if($lookaddr != 0) | |||
65 | $prev_function = $1; | 131 | $prev_function = $1; |
66 | } | 132 | } |
67 | 133 | ||
134 | if(/^\.([^\s]+)\s*(0x[0-9a-fA-F]+)/) | ||
135 | { | ||
136 | ($addr) = sscanf("0x%lx", $2); | ||
137 | if($1 eq "plugin" || $1 eq "codec") | ||
138 | { | ||
139 | $plugin_addr = $addr; | ||
140 | } | ||
141 | elsif($1 eq "codec") | ||
142 | { | ||
143 | $codec_addr = $addr; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | |||
68 | if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/) | 148 | if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/) |
69 | { | 149 | { |
70 | ($addr) = sscanf("0x%lx", $1); | 150 | ($addr) = sscanf("0x%lx", $1); |
@@ -115,6 +195,17 @@ if($lookaddr != 0) | |||
115 | } | 195 | } |
116 | close MAPFILE; | 196 | close MAPFILE; |
117 | 197 | ||
198 | if($lookaddr >= $codec_addr && $lookaddr < $plugin_addr) | ||
199 | { | ||
200 | # look for codec | ||
201 | %match = dynamic_space("codec", \@codecs); | ||
202 | } | ||
203 | elsif($lookaddr >= $plugin_addr) | ||
204 | { | ||
205 | # look for plugin | ||
206 | %match = dynamic_space("plugin", \@plugins); | ||
207 | } | ||
208 | |||
118 | printf "%s -> %s\n\n", $match{'library'}, $match{'function'}; | 209 | printf "%s -> %s\n\n", $match{'library'}, $match{'function'}; |
119 | 210 | ||
120 | # Replace path/libfoo.a(bar.o) with path/libfoo.a | 211 | # Replace path/libfoo.a(bar.o) with path/libfoo.a |
@@ -126,7 +217,7 @@ if($lookaddr != 0) | |||
126 | { | 217 | { |
127 | chomp($_); | 218 | chomp($_); |
128 | 219 | ||
129 | if(/^[0-9]+ \<(.+)\>:$/) | 220 | if(/^[0-9a-fA-F]+\s\<(.+)\>:$/) |
130 | { | 221 | { |
131 | $found = ($1 eq $match{'function'}); | 222 | $found = ($1 eq $match{'function'}); |
132 | } | 223 | } |
@@ -140,6 +231,10 @@ if($lookaddr != 0) | |||
140 | { | 231 | { |
141 | ($addr) = sscanf("%lx", $1); | 232 | ($addr) = sscanf("%lx", $1); |
142 | 233 | ||
234 | if($addr - $lookaddr > 0) | ||
235 | { | ||
236 | $addr -= $lookaddr; | ||
237 | } | ||
143 | if(abs($match{'diff'} - $addr) <= $context_size * 4) | 238 | if(abs($match{'diff'} - $addr) <= $context_size * 4) |
144 | { | 239 | { |
145 | printf "%s%s\n", ($addr == $match{'diff'} ? ">": " "), $_; | 240 | printf "%s%s\n", ($addr == $match{'diff'} ? ">": " "), $_; |
@@ -162,7 +257,7 @@ This makes it possible to find the exact assembly instruction at the specified | |||
162 | memory location (depends on Makefile, rockbox.map and the object files). | 257 | memory location (depends on Makefile, rockbox.map and the object files). |
163 | 258 | ||
164 | Usage example: | 259 | Usage example: |
165 | mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 3 | 260 | mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 1 |
166 | /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info | 261 | /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info |
167 | 262 | ||
168 | 23c: 00601021 move v0,v1 | 263 | 23c: 00601021 move v0,v1 |