forked from len0rd/rockbox
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21548 a1c6a512-1295-4272-9138-f99709370657
176 lines
No EOL
5.1 KiB
Perl
Executable file
176 lines
No EOL
5.1 KiB
Perl
Executable file
#!/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
|
|
;
|
|
} |