File Coverage

blib/lib/Binutils/Objdump.pm
Criterion Covered Total %
statement 15 77 19.4
branch 1 42 2.3
condition 0 11 0.0
subroutine 5 15 33.3
pod 10 10 100.0
total 31 155 20.0


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2009, 2011 Slade Maurer, Alexander Sviridenko
3             #
4             # See COPYRIGHT section in pod text below for usage and distribution rights.
5             #
6             package Binutils::Objdump;
7              
8             our $VERSION = '0.1.2';
9              
10             our @ISA = qw(Exporter);
11             our @EXPORT = qw(objdump objdumpopt objdumpwrap);
12             our @EXPORT_OK = qw(objdump objdumpopt objdumppath objdumpwrap
13             objdump_dynamic_reloc_info objdump_symtab
14             objdump_section_headers objdump_dynamic_symtab
15             objdump_sec_contents objdump_sec_disasm
16             );
17             our %EXPORT_TAGS = (
18             ALL => [qw(objdump objdumpopt objdumppath objdumpwrap
19             objdump_dynamic_reloc_info objdump_symtab objdump_section_headers
20             objdump_dynamic_symtab objdump_sec_contents objdump_sec_disasm)],
21             );
22              
23 1     1   49378 use strict;
  1         3  
  1         40  
24 1     1   4 use warnings;
  1         3  
  1         32  
25              
26             # Constants
27 1     1   6 use constant DEF_WRAPPER => 0; # default wrapper
  1         6  
  1         92  
28 1     1   5 use constant USR_WRAPPER => 1; # user's wrapper
  1         2  
  1         2723  
29              
30             # By default, if none of object files will not be set,
31             # will be used object file with such name.
32             our $default_objfile = 'a.out';
33              
34             # Try to define the path for objdump automatically. Also can be changed by user.
35             if (($^O =~ /MSWin/) or ($^O eq "Windows NT")) {
36             }
37             # Use `which' on linux.
38             elsif ($^O =~ /linux/) {
39             my $path = `which objdump`;
40             chomp $path;
41             objdumppath($path);
42             }
43              
44             # Information.
45             our %objdumpinfo = ();
46              
47             sub __objdumpinfo
48             {
49 0     0   0 my ($id, @lines) = (shift, @_);
50 0         0 my $ref = \%objdumpinfo;
51 0         0 for (1..scalar(@$id)) {
52 0 0       0 if ($_ < scalar(@$id)) {
53 0 0       0 $ref->{$id->[$_-1]} = {}
54             if !defined $ref->{$id->[$_-1]};
55 0         0 $ref = $ref->{$id->[$_-1]};
56             } else {
57 0         0 $ref->{$id->[$_-1]} = \@lines;
58             }
59             }
60             }
61              
62             # The labels and their wrappers, that will be used during
63             # parsing process.
64             our %objdumpwrappers = (
65             # Dynamic symbol table
66             'DYNAMIC SYMBOL TABLE:' => [sub { __objdumpinfo(['dynamic symbol table' ] , @_) }], # -T
67             # The summary information from the section headers of the object file
68             'Sections:' => [sub { __objdumpinfo(['sections' ] , @_) }], # -h
69             # The symbol table entries of the file
70             'SYMBOL TABLE:' => [sub { __objdumpinfo(['symbol table' ] , @_) }], # -t
71             # The dynamic relocation entries of the file
72             'DYNAMIC RELOCATION RECORDS:' => [sub { __objdumpinfo(['dynamic relocation records' ] , @_) }], # -R
73             # Dump contents of section...
74             'Contents of section .interp' => [sub { __objdumpinfo(['contents' , '.interp' ] , @_) }],
75             'Contents of section .note.ABI-tag' => [sub { __objdumpinfo(['contents' , '.note.ABI-tag' ] , @_) }],
76             'Contents of section .hash' => [sub { __objdumpinfo(['contents' , '.hash' ] , @_) }],
77             'Contents of section .gnu.hash' => [sub { __objdumpinfo(['contents' , '.gnu.hash' ] , @_) }],
78             'Contents of section .dynsym' => [sub { __objdumpinfo(['contents' , '.dynsym' ] , @_) }],
79             'Contents of section .dynstr' => [sub { __objdumpinfo(['contents' , '.dynstr' ] , @_) }],
80             'Contents of section .gnu.version' => [sub { __objdumpinfo(['contents' , '.gnu.version' ] , @_) }],
81             'Contents of section .gnu.version_r' => [sub { __objdumpinfo(['contents' , '.gnu.version_r' ] , @_) }],
82             'Contents of section .rel.dyn' => [sub { __objdumpinfo(['contents' , '.rel.dyn' ] , @_) }],
83             'Contents of section .rel.plt' => [sub { __objdumpinfo(['contents' , '.rel.plt' ] , @_) }],
84             'Contents of section .init' => [sub { __objdumpinfo(['contents' , '.init' ] , @_) }],
85             'Contents of section .plt' => [sub { __objdumpinfo(['contents' , '.plt' ] , @_) }],
86             'Contents of section .text' => [sub { __objdumpinfo(['contents' , '.text' ] , @_) }],
87             'Contents of section .fini' => [sub { __objdumpinfo(['contents' , '.fini' ] , @_) }],
88             'Contents of section .rodata' => [sub { __objdumpinfo(['contents' , '.rodata' ] , @_) }],
89             'Contents of section .eh_frame_hdr' => [sub { __objdumpinfo(['contents' , '.eh_frame_hdr' ] , @_) }],
90             'Contents of section .eh_frame' => [sub { __objdumpinfo(['contents' , '.eh_frame' ] , @_) }],
91             'Contents of section .ctors' => [sub { __objdumpinfo(['contents' , '.ctors' ] , @_) }],
92             'Contents of section .dtors' => [sub { __objdumpinfo(['contents' , '.dtors' ] , @_) }],
93             'Contents of section .jcr' => [sub { __objdumpinfo(['contents' , '.jcr' ] , @_) }],
94             'Contents of section .dynamic' => [sub { __objdumpinfo(['contents' , '.dynamic' ] , @_) }],
95             'Contents of section .got' => [sub { __objdumpinfo(['contents' , '.got' ] , @_) }],
96             'Contents of section .got.plt' => [sub { __objdumpinfo(['contents' , '.got.plt' ] , @_) }],
97             'Contents of section .data' => [sub { __objdumpinfo(['contents' , '.data' ] , @_) }],
98             'Contents of section .comment' => [sub { __objdumpinfo(['contents' , '.comment' ] , @_) }],
99             'Contents of section .debug_aranges' => [sub { __objdumpinfo(['contents' , '.debug_aranges' ] , @_) }],
100             'Contents of section .debug_pubnames' => [sub { __objdumpinfo(['contents' , '.debug_pubnames'] , @_) }],
101             'Contents of section .debug_info' => [sub { __objdumpinfo(['contents' , '.debug_info' ] , @_) }],
102             'Contents of section .debug_abbrev' => [sub { __objdumpinfo(['contents' , '.debug_abbrev' ] , @_) }],
103             'Contents of section .debug_line' => [sub { __objdumpinfo(['contents' , '.debug_line' ] , @_) }],
104             'Contents of section .debug_str' => [sub { __objdumpinfo(['contents' , '.debug_str' ] , @_) }],
105             'Contents of section .debug_ranges' => [sub { __objdumpinfo(['contents' , '.debug_ranges' ] , @_) }],
106             # Disassembly of section...
107             'Disassembly of section .text' => [sub { __objdumpinfo(['disassembly' , '.text'] , @_) }],
108             'Disassembly of section .plt' => [sub { __objdumpinfo(['disassembly' , '.plt' ] , @_) }],
109             'Disassembly of section .init' => [sub { __objdumpinfo(['disassembly' , '.init'] , @_) }],
110             'Disassembly of section .fini' => [sub { __objdumpinfo(['disassembly' , '.fini'] , @_) }],
111             );
112              
113             sub objdumpwrap ($$)
114             {
115 0     0 1 0 my ($label, $wrapper) = (shift, shift);
116 0 0       0 if (ref($wrapper) eq 'CODE') {
117             # Try to find out, if such label (but, maybe, not exactly the same)
118             # already exist.
119 0         0 foreach (keys %objdumpwrappers) {
120 0 0       0 $label = $_
121             if (/^\s*$label\s*(\:)?\s*$/);
122             }
123             # Set a second wrapper by user.
124 0         0 $objdumpwrappers{$label}->[USR_WRAPPER] = $wrapper;
125             }
126             }
127              
128             # The path to the objdump.
129             our $objdumppath;
130              
131             sub objdumppath
132             {
133 1 50   1 1 18 if (scalar(@_)) {
134 1         5 $objdumppath = shift;
135             }
136 1         5 return $objdumppath;
137             }
138              
139             # The string with options for objdump.
140             my $objdumpoptstr;
141              
142             sub objdumpopt
143             {
144             # If none options defined, then return current string of options
145 0 0   0 1   if (!scalar(@_)) {
146 0   0       return $objdumpoptstr || "";
147             }
148             # Form new string of options.
149 0           $objdumpoptstr = "";
150 0           foreach (@_) {
151 0           $objdumpoptstr = join " ", $objdumpoptstr, split(/\s/, $_);
152             }
153             }
154              
155             sub objdump
156             {
157 0     0 1   my @objfiles = @_;
158             # Update information.
159 0           %objdumpinfo = ();
160              
161             # If objdump cannot be found, then print an
162             # error message and die.
163 0 0 0       if (!-e objdumppath() || !-f objdumppath()) {
164 0           die "Objdump '". objdumppath() ."' cannot be found.\n";
165             }
166              
167             # If object files was not set, use default object file.
168 0 0         if (!scalar(@objfiles)) {
169 0           push @objfiles, $default_objfile;
170             }
171              
172 0           my @infos = ();
173 0           foreach my $objfile (@objfiles) {
174 0           my $cmd = join(' ', objdumppath(), objdumpopt(), $objfile, '2>&1');
175 0           my $info = `$cmd`;
176              
177 0           my @lines = split /\n/, $info;
178              
179 0           my @buff = ();
180 0           my %passed_labels = ();
181 0           my $label;
182             my $wrappers;
183              
184 0           LINE: while (scalar(@lines)) {
185 0           my $line = shift @lines;
186 0 0         do {
187 0           foreach (keys %objdumpwrappers) {
188 0 0         next if defined $passed_labels{$_};
189 0 0         if ($line =~/$_/) {
190 0 0         do { for (@$wrappers) { $_->(@buff) if defined $_ } } if defined $wrappers;
  0 0          
  0            
191 0           @buff = ();
192 0           ($label, $wrappers) = ($_, $objdumpwrappers{$_});
193 0           $passed_labels{$label}++;
194 0           next LINE;
195             }
196             }
197             } if (scalar(keys %passed_labels) < scalar(keys %objdumpwrappers));
198 0           push @buff, $line;
199             }
200             # Run the last wrapper if such defined...
201 0 0         do { for (@$wrappers) { $_->(@buff) if defined $_ } } if defined $wrappers;
  0 0          
  0            
202              
203 0           push @infos, $info;
204             }
205              
206 0           return @infos;
207             }
208              
209 0 0   0 1   sub objdump_dynamic_reloc_info { if (defined (my $lines = $objdumpinfo{'dynamic relocation records'})) { return @$lines } }
  0            
210 0 0   0 1   sub objdump_symtab { if (defined (my $lines = $objdumpinfo{'symbol table'})) { return @$lines } }
  0            
211 0 0   0 1   sub objdump_section_headers { if (defined (my $lines = $objdumpinfo{'sections'})) { return @$lines } }
  0            
212 0 0   0 1   sub objdump_dynamic_symtab { if (defined (my $lines = $objdumpinfo{'dynamic symbol table'})) { return @$lines } }
  0            
213 0 0 0 0 1   sub objdump_sec_contents { if (defined $_[0] && defined (my $lines = $objdumpinfo{'contents'}->{$_[0]})) { return @$lines } }
  0            
214 0 0 0 0 1   sub objdump_sec_disasm { if (defined $_[0] && defined (my $lines = $objdumpinfo{'disassembly'}->{$_[0]})) { return @$lines } }
  0            
215              
216             1;
217              
218             __END__