| #!/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; |
| } |
| } |