CHDK Wiki
Advertisement
#!/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