| 
									
										
										
										
											2017-04-26 15:16:04 +02:00
										 |  |  | #!/usr/bin/env perl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use warnings; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  |     return "$cmd -m $mach --disassemble-all -b binary"; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $objdump[1] = mkobjcommand($hobjdump, $hmachine); | 
					
						
							|  |  |  | $objdump[2] = mkobjcommand($tobjdump, $tmachine); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Zero-initialize current dumping state. | 
					
						
							|  |  |  | my $mem = ""; | 
					
						
							|  |  |  | my $inobjd = 0; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  | my $vma = 0; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 (<>) { | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  |     # Collect the data from the relevant OBJD-* lines ... | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  |     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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  |         my $cmd = objcommand(); | 
					
						
							|  |  |  |         $cmd = $cmd . " --adjust-vma=" . $vma if $vma; | 
					
						
							|  |  |  |         $cmd = $cmd . " " . $outname; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  |         # Pipe from objdump... | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  |         open IN, "-|", $cmd; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # ... 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; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:47 -07:00
										 |  |  |         $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; | 
					
						
							| 
									
										
										
										
											2013-08-16 23:29:46 -07:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         print; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |