Magic Lantern / fixup-rel

#!/usr/bin/perl
use warnings;
use strict;

# Read the map file
my %syms;

my $map_file = shift;
open MAP, "<$map_file"
	or die "$map_file: Unable to open: $!\n";
while( <MAP> )
{
	my ($pc,$name) = /:([0-9A-Fa-f]+)\s*([^\s]+)/
		or next;
	$pc = hex $pc;
	$syms{$pc} = $name;
}

# Generate a sorted list of symbols
my @syms = map { [ $_ => $syms{$_} ] } sort { $a <=> $b } keys %syms;


sub sym_lookup
{
	my $pc = shift;
	return unless exists $syms{$pc};
	return $syms{$pc};
}


sub sym_lookup_approx
{
	my $pc = shift;
	return if $pc < 1024;

	# Do a linear search for it
	for( my $i = 1 ; $i < @syms ; $i++ )
	{
		my $sym_pc = $syms[$i]->[0];
		next unless $sym_pc > $pc;

		$sym_pc = $syms[$i-1]->[0];
		my $sym = $syms[$i-1]->[1];
		return $sym if $sym_pc == $pc;
		return sprintf "%s+0x%x", $sym, $pc - $sym_pc;
	}

	return;
}


# Now read the list file
while(<>)
{
	chomp;

	my ($pc,$hex,$instr,$args) = /
		^\s*
		([0-9a-f]+):	# pc
		\s+
		([0-9a-f]+)	# hex
		\s+
		([^\s]+)	# instruction
		\s*
		(.*)		# args
		#(?:\s*;.*)?	# comment
		$
	/msgx
		or next;

	$pc = hex $pc;
	$hex = hex $hex;

	# Look for add instructions with pc relative, since those do not 
	# get translated correctly.
	if( $instr =~ /^add/ and $args =~ /pc, #/ )
	{
		# Strip any comment off the args
		$args =~ s/\s*;.*$//;
		my @args = split /,\s*/, $args;
		$args[2] =~ s/^#//;
		my $result = $pc + $args[2] + 8;
		$args .= sprintf " ; 0x%x", $result;
	}

	# Look for sub instructions with pc relative, since those do not 
	# get translated correctly.
	if( $instr =~ /^sub/ and $args =~ /pc, #/ )
	{
		# Strip any comment off the args
		$args =~ s/\s*;.*$//;
		my @args = split /,\s*/, $args;
		$args[2] =~ s/^#//;
		my $result = $pc - $args[2] + 8;
		$args .= sprintf " ; 0x%x", $result;
	}

	# Check to see if a branch instruction has a symbol
	# and it does not make a register indirect call
	if( $instr =~ /^b/ and $args =~ /^[0-9A-Fa-f]/ )
	{
		my $sym = sym_lookup_approx( hex $args );
		$args .= " $sym"
			if $sym;
	}
	

	my $sym = sym_lookup( $pc );
	printf "\n%s()\n", $sym
		if $sym;
	
	# Check to see if a coment has an symbol?
	my ($comment_addr) = $args =~ /;\s+([0-9A-Fa-fx]+)/;
	if( $comment_addr )
	{
		$comment_addr = hex $comment_addr;
		my $sym = sym_lookup_approx( $comment_addr );
		$args .= " $sym"
			if $sym;
	}

	my $asc;
	for my $i (0..3)
	{
		my $c = chr( ($hex >> (8*$i)) & 0xFF );
		$asc .= ($c =~ /[[:print:]]/) ? $c : '.';
	}

	printf "%08x: %08x   %s\t%s\t%s\n", $pc, $hex, $asc, $instr,$args;
}

print "\n";
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.