diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2009-06-28 18:51:38 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2009-06-28 18:51:38 +0000 |
commit | e8f75ede181858c30a7b1d3955d545899e1548be (patch) | |
tree | 07e1ea04a65296e8d5e87302676118560e89b2c6 /utils | |
parent | 41ff287e07d555f5f667812003dcf2f8fd86eec3 (diff) | |
download | rockbox-e8f75ede181858c30a7b1d3955d545899e1548be.tar.gz rockbox-e8f75ede181858c30a7b1d3955d545899e1548be.zip |
Add an utility to easily find the assembled instructions at a specific memory location in a Rockbox binary
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21548 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/analysis/find_addr.pl | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/utils/analysis/find_addr.pl b/utils/analysis/find_addr.pl new file mode 100755 index 0000000000..2dcc84ab8a --- /dev/null +++ b/utils/analysis/find_addr.pl | |||
@@ -0,0 +1,176 @@ | |||
1 | #!/usr/bin/env perl | ||
2 | # __________ __ ___. | ||
3 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | # \/ \/ \/ \/ \/ | ||
8 | # $Id$ | ||
9 | # | ||
10 | # Copyright (C) 2009 by Maurus Cuelenaere | ||
11 | # | ||
12 | # This program is free software; you can redistribute it and/or | ||
13 | # modify it under the terms of the GNU General Public License | ||
14 | # as published by the Free Software Foundation; either version 2 | ||
15 | # of the License, or (at your option) any later version. | ||
16 | # | ||
17 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | # KIND, either express or implied. | ||
19 | # | ||
20 | use String::Scanf; | ||
21 | |||
22 | sub check_boundaries | ||
23 | { | ||
24 | my $fits = 0, $start = $_[0], $end = $_[0] + $_[1]; | ||
25 | foreach my $boundary (@ram_boundaries) | ||
26 | { | ||
27 | if(defined(@$boundary{'name'}) && $start >= @$boundary{'start'} && $end <= @$boundary{'end'}) | ||
28 | { | ||
29 | return 1; | ||
30 | } | ||
31 | } | ||
32 | |||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | ($lookaddr) = sscanf("0x%lx", $ARGV[0]); | ||
37 | ($context_size) = $#ARGV > 0 ? $ARGV[1] : 5; | ||
38 | |||
39 | if($lookaddr != 0) | ||
40 | { | ||
41 | # Determine the used objdump utility | ||
42 | |||
43 | open MAKEFILE, "<Makefile" or die "Can't open Makefile: $!"; | ||
44 | my $objdump; | ||
45 | while(<MAKEFILE>) | ||
46 | { | ||
47 | chomp($_); | ||
48 | |||
49 | if(/^export OC=(.+)$/) | ||
50 | { | ||
51 | $objdump = $1; | ||
52 | $objdump =~ s/objcopy/objdump/; | ||
53 | } | ||
54 | } | ||
55 | close MAKEFILE; | ||
56 | |||
57 | open MAPFILE, "<rockbox.map" or die "Can't open rockbox.map: $!"; | ||
58 | my $addr, $size, $library, $match, $prev_function; | ||
59 | while(<MAPFILE>) | ||
60 | { | ||
61 | chomp($_); | ||
62 | |||
63 | if(/^\s*\.text\.([^\s]+)$/) | ||
64 | { | ||
65 | $prev_function = $1; | ||
66 | } | ||
67 | |||
68 | if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/) | ||
69 | { | ||
70 | ($addr) = sscanf("0x%lx", $1); | ||
71 | ($size) = sscanf("0x%lx", $2); | ||
72 | $library = $3; | ||
73 | |||
74 | if(check_boundaries($addr, $size) != 0 | ||
75 | && $lookaddr >= $addr && $lookaddr <= ($addr + $size)) | ||
76 | { | ||
77 | #printf "0x%x 0x%x %s %s\n", $addr, $size, $prev_function, $library; | ||
78 | |||
79 | my $diff = abs($lookaddr - $addr); | ||
80 | if(!defined($match{'diff'}) || $diff <= $match{'diff'}) | ||
81 | { | ||
82 | $match{'diff'} = $diff; | ||
83 | $match{'library'} = $library; | ||
84 | $match{'function'} = $prev_function; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | elsif(/^\s*(0x[0-9a-fA-F]+)\s*([^\s]+)$/) | ||
89 | { | ||
90 | ($addr) = sscanf("0x%lx", $1); | ||
91 | my $function = $2; | ||
92 | |||
93 | if(check_boundaries($addr, 0) != 0 && $lookaddr >= $addr) | ||
94 | { | ||
95 | #printf "0x%x %s\n", $addr, $function; | ||
96 | |||
97 | my $diff = abs($lookaddr - $addr); | ||
98 | if(!defined($match{'diff'}) || $diff <= $match{'diff'}) | ||
99 | { | ||
100 | $match{'diff'} = $diff; | ||
101 | $match{'library'} = $library; | ||
102 | $match{'function'} = $function; | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | elsif(/^(.RAM) *(0x[0-9a-fA-F]+) (0x[0-9a-fA-F]+)/) | ||
107 | { | ||
108 | (my $start_addr) = sscanf("0x%lx", $2); | ||
109 | (my $addr_length) = sscanf("0x%lx", $3); | ||
110 | push(@ram_boundaries, {"name", $1, | ||
111 | "start", $start_addr, | ||
112 | "end", $start_addr + $addr_length | ||
113 | }); | ||
114 | } | ||
115 | } | ||
116 | close MAPFILE; | ||
117 | |||
118 | printf "%s -> %s\n\n", $match{'library'}, $match{'function'}; | ||
119 | |||
120 | # Replace path/libfoo.a(bar.o) with path/libfoo.a | ||
121 | $match{'library'} =~ s/\(.+\)//; | ||
122 | |||
123 | open OBJDUMP, "$objdump -S $match{'library'} 2>&1 |" or die "Can't open pipe: $!"; | ||
124 | my $found = 0, $addr; | ||
125 | while(<OBJDUMP>) | ||
126 | { | ||
127 | chomp($_); | ||
128 | |||
129 | if(/^[0-9]+ \<(.+)\>:$/) | ||
130 | { | ||
131 | $found = ($1 eq $match{'function'}); | ||
132 | } | ||
133 | elsif(/Disassembly of section/) | ||
134 | { | ||
135 | $found = 0; | ||
136 | } | ||
137 | elsif($found == 1) | ||
138 | { | ||
139 | if(/^\s*([0-9a-fA-F]+):\s*[0-9a-fA-F]+\s*.+$/) | ||
140 | { | ||
141 | ($addr) = sscanf("%lx", $1); | ||
142 | |||
143 | if(abs($match{'diff'} - $addr) <= $context_size * 4) | ||
144 | { | ||
145 | printf "%s%s\n", ($addr == $match{'diff'} ? ">": " "), $_; | ||
146 | } | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | # TODO: be able to also show source code (within context_size) | ||
151 | # printf " %s\n", $_; | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | close OBJDUMP; | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | print "find_addr.pl 0xABCDEF [CONTEXT_SIZE]\n\n"; | ||
160 | print <<EOF | ||
161 | 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). | ||
163 | |||
164 | Usage example: | ||
165 | mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 3 | ||
166 | /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info | ||
167 | |||
168 | 23c: 00601021 move v0,v1 | ||
169 | > 240: 80620000 lb v0,0(v1) | ||
170 | 244: 0002180a movz v1,zero,v0 | ||
171 | |||
172 | |||
173 | Don't forget to build with -g ! | ||
174 | EOF | ||
175 | ; | ||
176 | } \ No newline at end of file | ||