3 # Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 # Copyright (C) 2009 by Maurus Cuelenaere
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.
17 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 # KIND, either express or implied.
25 my $fits = 0, $start = $_[0], $end = $_[0] + $_[1];
26 foreach my $boundary (@ram_boundaries)
28 if(defined(@
$boundary{'name'}) && $start >= @
$boundary{'start'} && $end <= @
$boundary{'end'})
39 my $space = $_[0], $space_array = $_[1], $ret;
41 printf "This address is in %s space, please select the %s which was used with this address:\n", $space, $space;
43 foreach my $el (@
$space_array)
45 printf " [%d]: %s\n", $count++, $el;
54 } while($sel <= 0 || $sel > $count - 1 || !($sel =~ /^[+-]?\d+$/));
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: $!";
62 if(/^([0-9a-fA-F]+).+\s([0-9a-fA-F]{3,})\s(?:[^\s]+\s)?(.+)$/)
64 (my $addr) = sscanf
("%lx", $1);
65 (my $size) = sscanf
("%lx", $2);
67 if($lookaddr >= $addr && $lookaddr <= ($addr + $size))
69 my $diff = abs($lookaddr - $addr);
70 if(!defined($ret{'diff'}) || $diff <= $ret{'diff'})
73 $ret{'function'} = $3;
83 ($lookaddr) = sscanf
("0x%lx", $ARGV[0]);
84 ($context_size) = $#ARGV > 0 ?
$ARGV[1] : 5;
88 # Determine the used objdump utility
89 open MAKEFILE
, "<Makefile" or die "Can't open Makefile: $!";
94 if(/^export OC=(.+)$/)
97 $objdump =~ s/objcopy/objdump/;
102 # Generate a list of all codecs
103 open FINDCODECS
, "find apps/codecs/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!";
108 $_ =~ s/apps\/codecs\///;
112 # Generate a list of all plugins
113 open FINDPLUGINS
, "find apps/plugins/ -name '*.elf' 2>&1 |" or die "Can't open pipe: $!";
118 $_ =~ s/apps\/plugins\///;
123 open MAPFILE
, "<rockbox.map" or die "Can't open rockbox.map: $!";
124 my $addr, $size, $library, $match, $prev_function, $codec_addr, $plugin_addr;
129 if(/^\s*\.text\.([^\s]+)$/)
134 if(/^\.([^\s]+)\s*(0x[0-9a-fA-F]+)/)
136 ($addr) = sscanf
("0x%lx", $2);
139 $plugin_addr = $addr;
148 if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/)
150 ($addr) = sscanf
("0x%lx", $1);
151 ($size) = sscanf
("0x%lx", $2);
154 if(check_boundaries
($addr, $size) != 0
155 && $lookaddr >= $addr && $lookaddr <= ($addr + $size))
157 #printf "0x%x 0x%x %s %s\n", $addr, $size, $prev_function, $library;
159 my $diff = abs($lookaddr - $addr);
160 if(!defined($match{'diff'}) || $diff <= $match{'diff'})
162 $match{'diff'} = $diff;
163 $match{'library'} = $library;
164 $match{'function'} = $prev_function;
168 elsif(/^\s*(0x[0-9a-fA-F]+)\s*([^\s]+)$/)
170 ($addr) = sscanf
("0x%lx", $1);
173 if(check_boundaries
($addr, 0) != 0 && $lookaddr >= $addr)
175 #printf "0x%x %s\n", $addr, $function;
177 my $diff = abs($lookaddr - $addr);
178 if(!defined($match{'diff'}) || $diff <= $match{'diff'})
180 $match{'diff'} = $diff;
181 $match{'library'} = $library;
182 $match{'function'} = $function;
186 elsif(/^(.RAM) *(0x[0-9a-fA-F]+) (0x[0-9a-fA-F]+)/)
188 (my $start_addr) = sscanf
("0x%lx", $2);
189 (my $addr_length) = sscanf
("0x%lx", $3);
190 push(@ram_boundaries, {"name", $1,
191 "start", $start_addr,
192 "end", $start_addr + $addr_length
198 if($lookaddr >= $codec_addr && $lookaddr < $plugin_addr
202 %match = dynamic_space
("codec", \
@codecs);
204 elsif($lookaddr >= $plugin_addr && $plugin_addr != 0)
207 %match = dynamic_space
("plugin", \
@plugins);
210 printf "%s -> %s\n\n", $match{'library'}, $match{'function'};
212 # Replace path/libfoo.a(bar.o) with path/libfoo.a
213 $match{'library'} =~ s/\(.+\)//;
215 open OBJDUMP
, "$objdump -S $match{'library'} 2>&1 |" or die "Can't open pipe: $!";
216 my $found = 0, $addr;
221 if(/^[0-9a-fA-F]+\s\<(.+)\>:$/)
223 $found = ($1 eq $match{'function'});
225 elsif(/Disassembly of section/)
231 if(/^\s*([0-9a-fA-F]+):\s*[0-9a-fA-F]+\s*.+$/)
233 ($addr) = sscanf
("%lx", $1);
235 if($addr - $lookaddr > 0)
239 if(abs($match{'diff'} - $addr) <= $context_size * 4)
241 printf "%s%s\n", ($addr == $match{'diff'} ?
">": " "), $_;
246 # TODO: be able to also show source code (within context_size)
247 # printf " %s\n", $_;
255 print "find_addr.pl 0xABCDEF [CONTEXT_SIZE]\n\n";
257 This makes it possible to find the exact assembly instruction at the specified
258 memory location (depends on Makefile, rockbox.map and the object files).
261 mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 1
262 /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info
264 23c: 00601021 move v0,v1
265 > 240: 80620000 lb v0,0(v1)
266 244: 0002180a movz v1,zero,v0
269 Don't forget to build with -g !