#!/usr/bin/perl
# scan chdk's stub_entry*.S for
# NSTUB(CreateController, 0xFF86A6E4)
# and add this information to a disassemble file
#
# (c) 2008 chr
# GPL V3+
#
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
if (@ARGV != 1) {
print("Usage e.g.:\n cat stubs_entry.S stubs_entry_2.S | $0 dump.bin.dis > outfile\n\n");
exit;
}
$dissfile = $ARGV[0];
#$stubfile = $ARGV[1];
#####
print STDERR "scan stub file\n";
my %nstub;
my %nstub_names; # hash by name to eliminate doubles
#open(IN, "<$stubfile") or die "cannot open $stubfile: $!";
while (<STDIN>) {
if (/^NH?STUB\((.*),.*0x([[:xdigit:]]*)/i) {
my $addr = sprintf("%08x", hex($2));
#$nstub{$addr} = $1;
$nstub_names{$1} = $addr;
}
}
close IN;
# hash by address
foreach (keys %nstub_names) {
$nstub{ $nstub_names{$_} } = $_;
}
$nstub{'ff81000c'} = "TEST start";
print Dumper(\%nstub);
#exit;
#####
print STDERR "scan diss file\n";
open(IN, "<$dissfile") or die "cannot read $dissfile: $!";
while (<IN>) {
if ($_ eq " ...\n") { print $_; next;}
# print $_;
my ($addr, $op, $line) = $_ =~ /^([[:xdigit:]]*): \t([[:xdigit:]]*) \t(.*)/;
unless ($addr) {
print $_;
next;
}
$op_n = hex($op);
if ( ($op_n & 0x0e000000) == 0x0a000000) {
# any branch op
# ff8771c4: ebfe91c5 bl ff81b8e0 <_binary_dump_bin_start+0xb8e0>
my ($goto) = $line =~ /\t([[:xdigit:]]*)/;
if (my $func = $nstub{$goto}) {
$line =~ s/<.*>/<$func>/;
}
my $rel = hex($goto)-hex($addr);
$rel = "+$rel" if ($rel>0);
$line =~ s/<(.*)>/<$1 $rel>/;
}
$line = "$op \t$line";
##
## TODO: handle DEF() from stub_min.S
##
## if (
## ($line =~ /^(.*\tldr.*\[pc, #([-\d]+).*; )/) ||
## ($line =~ /^(.*\tadd.*pc, #([-\d]+).*; )/)
## ) {
## $line = $1;
## my $off = hex($addr) - hex($offset) + $2 + 8;
## my $point = sprintf("%08x", hex($addr) + $2 + 8);
## my $value = &get_word($off);
## $line .= "$point: ($value) ";
## if (my $str = $nstub{$point}) {
## $line .= qq| *"$str"|;
## }
## elsif (my $str = $nstub{$value}) {
## $line .= qq| **"$str"|;
## }
## }
## # ff815e1c: e24f0090 sub r0, pc, #144 ; 0x90
## elsif ($line =~ /^(.*\tsub.*pc, #([-\d]+).*; )/) {
## $line = $1;
## my $off = hex($addr) - hex($offset) - $2 + 8;
## my $point = sprintf("%08x", hex($addr) - $2 + 8);
## my $value = &get_word($off);
## $line .= "$point: ($value) ";
## if (my $str = $nstub{$point}) {
## $line .= qq| *"$str"|;
## }
## elsif (my $str = $nstub{$value}) {
## $line .= qq| **"$str"|;
## }
## }
if (my $str = $nstub{$addr}) {
print qq|\nNSTUB($str, 0x$addr):\n|;
}
print "$addr: \t$line\n";
# progress
print STDERR "\r0x$addr ";
}
close IN;
Advertisement
GPL:stubs2dis.pl
Advertisement