#!/usr/bin/perl
# example:
# debug2line "bin/Simulator.so(_ZN9Simulator6motionER7Point6DS1_dddddPci+0xf60) [0x403d4470]"
# detects if bin/Simulator.so is arm-linux or X86 
# runs [arm-vfp-linux-gnu-]objdump to get the address of _ZN9Simulator6motionER7Point6DS1_dddddPci
# adds 0xf60 to the result, and feeds that result to [arm-vfp-linux-gnu-]addr2line

$usage = "usage: debug2line \"binaryName(symbolName+offset) [machine address -- ignored]\"\n";
die $usage unless @ARGV >= 1; #show usage if no parameters were passed

if($ARGV[0] =~ /([^\(]+).([^\+]+).([^\)]+).+$/)
{
    my($binaryName) = $1;
    my($symbolName) = $2;
    my($offset) = hex($3);
    
    open(BINARY, $binaryName) or die "can't open $binaryName: $!";
    binmode(BINARY);
    seek(BINARY, 7, 0);
    my $buffer = "";
    read(BINARY, $buffer, 1) or die "can't read from $binaryName: $!";
    close(BINARY);
    
    my $prefix = "";
    if( $buffer eq "a" )
    {
        $prefix = "arm-vfp-linux-gnu-";
        my $env="export PATH=/opt/nxp/gcc-4.3.2-glibc-2.7/bin/:\$PATH";
        if( system($env) ) { warn "could not run \"$env\": $?"; }
    }    
    
    my($objdump) = "$prefix" . "objdump -x $binaryName | grep $symbolName";
    my($dumpResult) = `$objdump 2>&1`;
    #print "*** dumpResult=$dumpResult\n"; 
    if($dumpResult =~ /([^\s]+).+$/ )
    {
        my($baseAddress) = hex($1);
        #printf("baseAddress=0x%x, $offset=0x%x\n",$baseAddress,$offset); 
        my($addr2line) = sprintf("%saddr2line -e %s 0x%x", $prefix, $binaryName, $baseAddress+$offset);
        #print "*** addr2line=$addr2line\n";
        if( system($addr2line) ) { die "could not run \"$addr2line\": $?"; }
    }
}
else
{
    die $usage;
} 
