blob: b66f35f48e8fd6fefee8cca21c884352316d15f8 [file] [log] [blame]
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +00001#!/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#
20use String::Scanf;
Maurus Cuelenaere11765532009-07-01 12:25:24 +000021use Cwd;
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +000022
23sub check_boundaries
24{
25 my $fits = 0, $start = $_[0], $end = $_[0] + $_[1];
26 foreach my $boundary (@ram_boundaries)
27 {
28 if(defined(@$boundary{'name'}) && $start >= @$boundary{'start'} && $end <= @$boundary{'end'})
29 {
30 return 1;
31 }
32 }
33
34 return 0;
35}
36
Maurus Cuelenaere11765532009-07-01 12:25:24 +000037sub 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
Amaury Poulycc59ea42012-05-31 15:56:34 +020056 my $prefix;
57 if($space eq 'plugin')
58 {
59 $prefix = 'apps';
60 }
61 else
62 {
63 $prefix = 'lib/rbcodec';
64 }
65 my $file = sprintf("%s/%ss/%s", $prefix, $space, @$space_array[$sel - 1]);
Maurus Cuelenaere11765532009-07-01 12:25:24 +000066 $ret{'library'} = sprintf("%s/%s", cwd(), $file);
67 open FILE, "$objdump -t $file |" or die "Can't open pipe: $!";
68 while(<FILE>)
69 {
70 chomp($_);
71 if(/^([0-9a-fA-F]+).+\s([0-9a-fA-F]{3,})\s(?:[^\s]+\s)?(.+)$/)
72 {
73 (my $addr) = sscanf("%lx", $1);
74 (my $size) = sscanf("%lx", $2);
75
76 if($lookaddr >= $addr && $lookaddr <= ($addr + $size))
77 {
78 my $diff = abs($lookaddr - $addr);
79 if(!defined($ret{'diff'}) || $diff <= $ret{'diff'})
80 {
81 $ret{'diff'} = $diff;
82 $ret{'function'} = $3;
83 }
84 }
85 }
86 }
87 close FILE;
88
89 return %ret;
90}
91
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +000092($lookaddr) = sscanf("0x%lx", $ARGV[0]);
93($context_size) = $#ARGV > 0 ? $ARGV[1] : 5;
94
95if($lookaddr != 0)
96{
97 # Determine the used objdump utility
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +000098 open MAKEFILE, "<Makefile" or die "Can't open Makefile: $!";
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +000099 while(<MAKEFILE>)
100 {
101 chomp($_);
102
103 if(/^export OC=(.+)$/)
104 {
105 $objdump = $1;
106 $objdump =~ s/objcopy/objdump/;
107 }
108 }
109 close MAKEFILE;
110
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000111 # Generate a list of all codecs
Sean Bartellf40bfc92011-06-25 21:32:25 -0400112 open FINDCODECS, "find lib/rbcodec/codecs/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!";
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000113 my @codecs;
114 while(<FINDCODECS>)
115 {
116 chomp($_);
Sean Bartellf40bfc92011-06-25 21:32:25 -0400117 $_ =~ s/lib\/rbcodec\/codecs\///;
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000118 push(@codecs, $_);
119 }
120 close FINDCODECS;
121 # Generate a list of all plugins
122 open FINDPLUGINS, "find apps/plugins/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!";
123 my @plugins;
124 while(<FINDPLUGINS>)
125 {
126 chomp($_);
127 $_ =~ s/apps\/plugins\///;
128 push(@plugins, $_);
129 }
130 close FINDPLUGINS;
131
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000132 open MAPFILE, "<rockbox.map" or die "Can't open rockbox.map: $!";
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000133 my $addr, $size, $library, $match, $prev_function, $codec_addr, $plugin_addr;
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000134 while(<MAPFILE>)
135 {
136 chomp($_);
137
138 if(/^\s*\.text\.([^\s]+)$/)
139 {
140 $prev_function = $1;
141 }
142
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000143 if(/^\.([^\s]+)\s*(0x[0-9a-fA-F]+)/)
144 {
145 ($addr) = sscanf("0x%lx", $2);
Maurus Cuelenaere0a59e042009-07-08 19:38:46 +0000146 if($1 eq "plugin")
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000147 {
148 $plugin_addr = $addr;
149 }
150 elsif($1 eq "codec")
151 {
152 $codec_addr = $addr;
153 }
154 }
155
156
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000157 if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/)
158 {
159 ($addr) = sscanf("0x%lx", $1);
160 ($size) = sscanf("0x%lx", $2);
161 $library = $3;
162
163 if(check_boundaries($addr, $size) != 0
164 && $lookaddr >= $addr && $lookaddr <= ($addr + $size))
165 {
166 #printf "0x%x 0x%x %s %s\n", $addr, $size, $prev_function, $library;
167
168 my $diff = abs($lookaddr - $addr);
169 if(!defined($match{'diff'}) || $diff <= $match{'diff'})
170 {
171 $match{'diff'} = $diff;
172 $match{'library'} = $library;
173 $match{'function'} = $prev_function;
174 }
175 }
176 }
177 elsif(/^\s*(0x[0-9a-fA-F]+)\s*([^\s]+)$/)
178 {
179 ($addr) = sscanf("0x%lx", $1);
180 my $function = $2;
181
182 if(check_boundaries($addr, 0) != 0 && $lookaddr >= $addr)
183 {
184 #printf "0x%x %s\n", $addr, $function;
185
186 my $diff = abs($lookaddr - $addr);
187 if(!defined($match{'diff'}) || $diff <= $match{'diff'})
188 {
189 $match{'diff'} = $diff;
190 $match{'library'} = $library;
191 $match{'function'} = $function;
192 }
193 }
194 }
195 elsif(/^(.RAM) *(0x[0-9a-fA-F]+) (0x[0-9a-fA-F]+)/)
196 {
197 (my $start_addr) = sscanf("0x%lx", $2);
198 (my $addr_length) = sscanf("0x%lx", $3);
199 push(@ram_boundaries, {"name", $1,
200 "start", $start_addr,
201 "end", $start_addr + $addr_length
202 });
203 }
204 }
205 close MAPFILE;
206
Maurus Cuelenaeree251df92009-08-17 13:42:52 +0000207 if($lookaddr >= $codec_addr && $lookaddr < $plugin_addr
208 && $codec_addr != 0)
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000209 {
210 # look for codec
211 %match = dynamic_space("codec", \@codecs);
212 }
Maurus Cuelenaeree251df92009-08-17 13:42:52 +0000213 elsif($lookaddr >= $plugin_addr && $plugin_addr != 0)
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000214 {
215 # look for plugin
216 %match = dynamic_space("plugin", \@plugins);
217 }
218
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000219 printf "%s -> %s\n\n", $match{'library'}, $match{'function'};
220
221 # Replace path/libfoo.a(bar.o) with path/libfoo.a
222 $match{'library'} =~ s/\(.+\)//;
223
224 open OBJDUMP, "$objdump -S $match{'library'} 2>&1 |" or die "Can't open pipe: $!";
225 my $found = 0, $addr;
226 while(<OBJDUMP>)
227 {
228 chomp($_);
229
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000230 if(/^[0-9a-fA-F]+\s\<(.+)\>:$/)
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000231 {
232 $found = ($1 eq $match{'function'});
233 }
234 elsif(/Disassembly of section/)
235 {
236 $found = 0;
237 }
238 elsif($found == 1)
239 {
240 if(/^\s*([0-9a-fA-F]+):\s*[0-9a-fA-F]+\s*.+$/)
241 {
242 ($addr) = sscanf("%lx", $1);
243
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000244 if($addr - $lookaddr > 0)
245 {
246 $addr -= $lookaddr;
247 }
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000248 if(abs($match{'diff'} - $addr) <= $context_size * 4)
249 {
250 printf "%s%s\n", ($addr == $match{'diff'} ? ">": " "), $_;
251 }
252 }
253 else
254 {
255 # TODO: be able to also show source code (within context_size)
256 # printf " %s\n", $_;
257 }
258 }
259 }
260 close OBJDUMP;
261}
262else
263{
264 print "find_addr.pl 0xABCDEF [CONTEXT_SIZE]\n\n";
265 print <<EOF
266This makes it possible to find the exact assembly instruction at the specified
267memory location (depends on Makefile, rockbox.map and the object files).
268
269Usage example:
Maurus Cuelenaere11765532009-07-01 12:25:24 +0000270 mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 1
Maurus Cuelenaeree8f75ed2009-06-28 18:51:38 +0000271 /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info
272
273 23c: 00601021 move v0,v1
274 > 240: 80620000 lb v0,0(v1)
275 244: 0002180a movz v1,zero,v0
276
277
278Don't forget to build with -g !
279EOF
280;
Maurus Cuelenaeree251df92009-08-17 13:42:52 +0000281}