| #!/usr/bin/env perl | |
| use warnings; | |
| use File::Temp qw/ tempfile /; | |
| use Getopt::Long; | |
| # Default to the system objdump if a cross-compiler edition not given. | |
| my $aobjdump = "objdump"; | |
| my $hobjdump = ""; | |
| my $tobjdump = ""; | |
| my $hmachine = ""; | |
| my $tmachine = ""; | |
| GetOptions ('O|objdump=s' => \$aobjdump, | |
| 'host-objdump=s' => \$hobjdump, | |
| 'target-objdump=s' => \$tobjdump, | |
| 'h|host-machine=s' => \$hmachine, | |
| 't|target-machine=s' => \$tmachine); | |
| # But we can't default the machines. Sanity check that we've at least one. | |
| die "No host or target machine type" if !$hmachine && !$tmachine; | |
| # Reuse one temp file for all of the hunks. | |
| my ($outh, $outname) = tempfile(); | |
| binmode($outh); | |
| END { unlink $outname; } | |
| # Pre-construct the command-lines for executing the dump. | |
| sub mkobjcommand ($$) { | |
| my ($cmd, $mach) = @_; | |
| return 0 if !$mach; | |
| $cmd = $aobjdump if !$cmd; | |
| return "$cmd -m $mach --disassemble-all -b binary"; | |
| } | |
| $objdump[1] = mkobjcommand($hobjdump, $hmachine); | |
| $objdump[2] = mkobjcommand($tobjdump, $tmachine); | |
| # Zero-initialize current dumping state. | |
| my $mem = ""; | |
| my $inobjd = 0; | |
| my $vma = 0; | |
| sub objcommand { | |
| my $ret = $objdump[$inobjd]; | |
| if (!$ret) { | |
| die "Host machine type not specified" if $inobjd == 1; | |
| die "Target machine type not specified" if $inobjd == 2; | |
| die "Internal error"; | |
| } | |
| return $ret; | |
| } | |
| while (<>) { | |
| # Collect the data from the relevant OBJD-* lines ... | |
| if (/^OBJD-H: /) { | |
| die "Internal error" if $inobjd == 2; | |
| $mem = $mem . pack("H*", substr($_, 8, -1)); | |
| $inobjd = 1; | |
| } elsif (/^OBJD-T: /) { | |
| die "Internal error" if $inobjd == 1; | |
| $mem = $mem . pack("H*", substr($_, 8, -1)); | |
| $inobjd = 2; | |
| } | |
| # ... which will always be followed by a blank line, | |
| # at which point we should produce our dump. | |
| elsif ($inobjd) { | |
| # Rewrite the temp file in one go; it will usually be small. | |
| sysseek $outh, 0, 0; | |
| truncate $outh, 0; | |
| syswrite $outh, $mem; | |
| my $cmd = objcommand(); | |
| $cmd = $cmd . " --adjust-vma=" . $vma if $vma; | |
| $cmd = $cmd . " " . $outname; | |
| # Pipe from objdump... | |
| open IN, "-|", $cmd; | |
| # ... copying all but the first 7 lines of boilerplate to our stdout. | |
| my $i = 0; | |
| while (<IN>) { | |
| print if (++$i > 7); | |
| } | |
| close IN; | |
| print "\n"; | |
| $mem = ""; | |
| $inobjd = 0; | |
| $vma = 0; | |
| } | |
| # The line before "OBJD-*" will be of the form "0x<hex>+: +\n". | |
| # Extract the value for passing to --adjust-vma. | |
| elsif (/^(0x[0-9a-fA-F]+):\s*$/) { | |
| $vma = $1; | |
| print; | |
| } else { | |
| print; | |
| } | |
| } |