summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xutils/analysis/find_addr.pl176
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 @@
+#!/usr/bin/env perl
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+# Copyright (C) 2009 by Maurus Cuelenaere
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+use String::Scanf;
+
+sub check_boundaries
+{
+ my $fits = 0, $start = $_[0], $end = $_[0] + $_[1];
+ foreach my $boundary (@ram_boundaries)
+ {
+ if(defined(@$boundary{'name'}) && $start >= @$boundary{'start'} && $end <= @$boundary{'end'})
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+($lookaddr) = sscanf("0x%lx", $ARGV[0]);
+($context_size) = $#ARGV > 0 ? $ARGV[1] : 5;
+
+if($lookaddr != 0)
+{
+ # Determine the used objdump utility
+
+ open MAKEFILE, "<Makefile" or die "Can't open Makefile: $!";
+ my $objdump;
+ while(<MAKEFILE>)
+ {
+ chomp($_);
+
+ if(/^export OC=(.+)$/)
+ {
+ $objdump = $1;
+ $objdump =~ s/objcopy/objdump/;
+ }
+ }
+ close MAKEFILE;
+
+ open MAPFILE, "<rockbox.map" or die "Can't open rockbox.map: $!";
+ my $addr, $size, $library, $match, $prev_function;
+ while(<MAPFILE>)
+ {
+ chomp($_);
+
+ if(/^\s*\.text\.([^\s]+)$/)
+ {
+ $prev_function = $1;
+ }
+
+ if(/^.*?\s*(0x[0-9a-fA-F]+)\s*(0x[0-9a-fA-F]+)\s(.+)$/)
+ {
+ ($addr) = sscanf("0x%lx", $1);
+ ($size) = sscanf("0x%lx", $2);
+ $library = $3;
+
+ if(check_boundaries($addr, $size) != 0
+ && $lookaddr >= $addr && $lookaddr <= ($addr + $size))
+ {
+ #printf "0x%x 0x%x %s %s\n", $addr, $size, $prev_function, $library;
+
+ my $diff = abs($lookaddr - $addr);
+ if(!defined($match{'diff'}) || $diff <= $match{'diff'})
+ {
+ $match{'diff'} = $diff;
+ $match{'library'} = $library;
+ $match{'function'} = $prev_function;
+ }
+ }
+ }
+ elsif(/^\s*(0x[0-9a-fA-F]+)\s*([^\s]+)$/)
+ {
+ ($addr) = sscanf("0x%lx", $1);
+ my $function = $2;
+
+ if(check_boundaries($addr, 0) != 0 && $lookaddr >= $addr)
+ {
+ #printf "0x%x %s\n", $addr, $function;
+
+ my $diff = abs($lookaddr - $addr);
+ if(!defined($match{'diff'}) || $diff <= $match{'diff'})
+ {
+ $match{'diff'} = $diff;
+ $match{'library'} = $library;
+ $match{'function'} = $function;
+ }
+ }
+ }
+ elsif(/^(.RAM) *(0x[0-9a-fA-F]+) (0x[0-9a-fA-F]+)/)
+ {
+ (my $start_addr) = sscanf("0x%lx", $2);
+ (my $addr_length) = sscanf("0x%lx", $3);
+ push(@ram_boundaries, {"name", $1,
+ "start", $start_addr,
+ "end", $start_addr + $addr_length
+ });
+ }
+ }
+ close MAPFILE;
+
+ printf "%s -> %s\n\n", $match{'library'}, $match{'function'};
+
+ # Replace path/libfoo.a(bar.o) with path/libfoo.a
+ $match{'library'} =~ s/\(.+\)//;
+
+ open OBJDUMP, "$objdump -S $match{'library'} 2>&1 |" or die "Can't open pipe: $!";
+ my $found = 0, $addr;
+ while(<OBJDUMP>)
+ {
+ chomp($_);
+
+ if(/^[0-9]+ \<(.+)\>:$/)
+ {
+ $found = ($1 eq $match{'function'});
+ }
+ elsif(/Disassembly of section/)
+ {
+ $found = 0;
+ }
+ elsif($found == 1)
+ {
+ if(/^\s*([0-9a-fA-F]+):\s*[0-9a-fA-F]+\s*.+$/)
+ {
+ ($addr) = sscanf("%lx", $1);
+
+ if(abs($match{'diff'} - $addr) <= $context_size * 4)
+ {
+ printf "%s%s\n", ($addr == $match{'diff'} ? ">": " "), $_;
+ }
+ }
+ else
+ {
+ # TODO: be able to also show source code (within context_size)
+ # printf " %s\n", $_;
+ }
+ }
+ }
+ close OBJDUMP;
+}
+else
+{
+ print "find_addr.pl 0xABCDEF [CONTEXT_SIZE]\n\n";
+ print <<EOF
+This makes it possible to find the exact assembly instruction at the specified
+memory location (depends on Makefile, rockbox.map and the object files).
+
+Usage example:
+ mcuelenaere\@wim2160:~/rockbox/build2\$ ../utils/analysis/find_addr.pl 0x8001a434 3
+ /home/mcuelenaere/rockbox/build2/apps/screens.o -> id3_get_info
+
+ 23c: 00601021 move v0,v1
+ > 240: 80620000 lb v0,0(v1)
+ 244: 0002180a movz v1,zero,v0
+
+
+Don't forget to build with -g !
+EOF
+;
+} \ No newline at end of file