summaryrefslogtreecommitdiff
path: root/utils/analysis/find_addr.pl
diff options
context:
space:
mode:
Diffstat (limited to 'utils/analysis/find_addr.pl')
-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 @@
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#
20use String::Scanf;
21
22sub 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
39if($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}
157else
158{
159 print "find_addr.pl 0xABCDEF [CONTEXT_SIZE]\n\n";
160 print <<EOF
161This makes it possible to find the exact assembly instruction at the specified
162memory location (depends on Makefile, rockbox.map and the object files).
163
164Usage 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
173Don't forget to build with -g !
174EOF
175;
176} \ No newline at end of file