File Coverage

lib/ELF/Extract/Sections/Scanner/Objdump.pm
Criterion Covered Total %
statement 65 84 77.3
branch 6 14 42.8
condition 1 3 33.3
subroutine 18 21 85.7
pod 6 6 100.0
total 96 128 75.0


line stmt bran cond sub pod time code
1 2     2   2303 use 5.010; # $+{}
  2         7  
2 2     2   9 use strict;
  2         4  
  2         50  
3 2     2   10 use warnings;
  2         4  
  2         167  
4              
5             package ELF::Extract::Sections::Scanner::Objdump;
6              
7             # ABSTRACT: An objdump based section scanner.
8              
9             our $VERSION = '1.001004'; # TRIAL
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 2     2   828 use Moose qw( with has );
  2         430429  
  2         18  
14             with 'ELF::Extract::Sections::Meta::Scanner';
15              
16 2     2   11469 use Carp qw( croak );
  2         4  
  2         142  
17 2     2   914 use MooseX::Has::Sugar 0.0300;
  2         707  
  2         16  
18              
19 2     2   827 use MooseX::Types::Moose (qw( Bool HashRef RegexpRef FileHandle Undef Str Int));
  2         56947  
  2         29  
20 2     2   12783 use MooseX::Types::Path::Tiny ('File');
  2         138181  
  2         23  
21 2     2   6184 use MooseX::Params::Validate (qw( validated_list ));
  2         71473  
  2         19  
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33             sub open_file {
34 4     4 1 31 my ( $self, $file ) = validated_list( \@_, file => { isa => File, }, );
35 4         5007 $self->log->debug("Opening $file");
36 4         1162 $self->_file($file);
37 4         22 $self->_filehandle( $self->_objdump );
38 4         325 return 1;
39             }
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51             sub next_section {
52 5672     5672 1 8783 my ($self) = @_;
53 5672         252054 my $re = $self->_section_header_identifier;
54 5672         233979 my $fh = $self->_filehandle;
55 5672         396503 while ( my $line = <$fh> ) {
56 482385 100       3035536 next if $line !~ $re;
57 2     2   2772 my ( $header, $offset ) = ( $+{header}, $+{offset} );
  2         970  
  2         999  
  5668         55177  
58 5668         260648 $self->_state( { header => $header, offset => $offset } );
59 5668         18971 $self->log->info("objdump -D -F : Section $header at $offset");
60 5668         302961 return 1;
61             }
62 4         210 $self->_clear_file;
63 4         224 $self->_clear_filehandle;
64 4         222 $self->_clear_state;
65 4         373 return 0;
66             }
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77              
78             sub section_offset {
79 5668     5668 1 9209 my ($self) = @_;
80 5668 50       248282 if ( not $self->_has_state ) {
81 0         0 $self->log->logcroak('Invalid call to section_offset outside of file scan');
82 0         0 return;
83             }
84 5668         224470 return hex( $self->_state->{offset} );
85             }
86              
87              
88              
89              
90              
91              
92              
93              
94              
95              
96              
97             sub section_size {
98 0     0 1 0 my ($self) = @_;
99 0         0 $self->log->logcroak('Can\'t perform section_size on this type of object.');
100 0         0 return;
101             }
102              
103              
104              
105              
106              
107              
108              
109              
110              
111              
112              
113             sub section_name {
114 5668     5668 1 8598 my ($self) = @_;
115 5668 50       255549 if ( not $self->_has_state ) {
116 0         0 $self->log->logcroak('Invalid call to section_name outside of file scan');
117 0         0 return;
118             }
119 5668         227194 return $self->_state->{header};
120             }
121              
122              
123              
124              
125              
126              
127              
128              
129              
130              
131              
132             sub can_compute_size {
133 4     4 1 13 return 0;
134             }
135              
136             has _header_regex => (
137             isa => RegexpRef,
138             ro,
139             default => sub {
140             return qr/<(?<header>[^>]+)>/;
141             },
142             );
143              
144             has _offset_regex => (
145             isa => RegexpRef,
146             ro,
147             default => sub {
148             ## no critic (RegularExpressions::ProhibitEnumeratedClasses)
149             return qr/[(]File Offset:\s*(?<offset>0x[0-9a-f]+)[)]/;
150             },
151             );
152              
153             has _section_header_identifier => ( isa => RegexpRef, ro, lazy_build, );
154              
155             has _file => ( isa => File, rw, clearer => '_clear_file', );
156              
157             has _filehandle => ( isa => FileHandle, rw, clearer => '_clear_filehandle', );
158              
159             has _state => (
160             isa => HashRef,
161             rw,
162             predicate => '_has_state',
163             clearer => '_clear_state',
164             );
165             __PACKAGE__->meta->make_immutable;
166 2     2   18 no Moose;
  2         2  
  2         19  
167              
168             sub _build__section_header_identifier {
169 4     4   20 my ($self) = @_;
170 4         315 my $header = $self->_header_regex;
171 4         355 my $offset = $self->_offset_regex;
172              
173 4         580 return qr/${header}\s*${offset}:/;
174             }
175              
176             sub _objdump_win32 {
177 0     0   0 my ($self) = @_;
178 0         0 require Capture::Tiny;
179             ## no critic (Subroutines::ProhibitCallsToUnexportedSubs)
180             my ( $stdout, $result ) = Capture::Tiny::capture_stdout(
181             sub {
182 0     0   0 system 'objdump', qw( -D -F ), $self->_file->realpath->absolute;
183             },
184 0         0 );
185 0 0       0 if ( $result != 0 ) {
186 0         0 $self->log->logconfess(qq{An error occured requesting section data from objdump $^E $@ });
187             }
188 0 0       0 open my $fh, '<', \$stdout or do {
189 0         0 $self->log->logconfess(qq{An error occured making a string IO filehandle $! $@ });
190             };
191 0         0 return $fh;
192             }
193              
194             sub _objdump {
195 4     4   8 my ($self) = @_;
196 4 50 33     50 if ( 'MSWin32' eq $^O or $ENV{OBJDUMP_SLURP} ) {
197 0         0 return $self->_objdump_win32;
198             }
199 4 50       169 if ( open my $fh, q{-|}, q{objdump}, qw( -D -F ), $self->_file->realpath->absolute ) {
200 4         34777 return $fh;
201             }
202 0           $self->log->logconfess(qq{An error occured requesting section data from objdump $! $@ });
203 0           return;
204             }
205              
206             1;
207              
208             __END__
209              
210             =pod
211              
212             =encoding UTF-8
213              
214             =head1 NAME
215              
216             ELF::Extract::Sections::Scanner::Objdump - An objdump based section scanner.
217              
218             =head1 VERSION
219              
220             version 1.001004
221              
222             =head1 SYNOPSIS
223              
224             This module is a model implementation of a Naive and system reliant ELF Section detector.
225             Its currently highly inefficient due to having to run the entire ELF through a disassembly
226             process to determine the section positions and only I<guesses> at section lengths by
227             advertising that it can't compute sizes.
228              
229             TO use this module, simply initialise L<ELF::Extract::Sections> as so
230              
231             my $extractor = ELF::Extract::Sections->new(
232             file => "/path/to/file.so" ,
233             scanner => "Objdump",
234             );
235              
236             =head1 METHODS
237              
238             =head2 C<open_file>
239              
240             my $boolean = $scanner->open_file( file => File );
241              
242             Opens the file and assigns our state to that file.
243              
244             L<ELF::Extract::Sections::Meta::Scanner/open_file>
245              
246             =head2 C<next_section>
247              
248             my $boolean = $scanner->next_section();
249              
250             Advances our state to the next section.
251              
252             L<ELF::Extract::Sections::Meta::Scanner/next_section>
253              
254             =head2 C<section_offset>
255              
256             my $return = $scanner->section_offset(); # Int | Undef
257              
258             Reports the offset of the currently open section
259              
260             L<ELF::Extract::Sections::Meta::Scanner/section_offset>
261              
262             =head2 C<section_size>
263              
264             my $return = $scanner->section_size(); # BANG
265              
266             Dies, because this module can't compute section sizes.
267              
268             L<ELF::Extract::Sections::Meta::Scanner/section_size>
269              
270             =head2 C<section_name>
271              
272             my $name = $scanner->section_name(); # Str | Undef
273              
274             Returns the name of the current section
275              
276             L<ELF::Extract::Sections::Meta::Scanner/section_name>
277              
278             =head2 C<can_compute_size>
279              
280             my $bool = $scanner->can_compute_size;
281              
282             Returns false
283              
284             L<ELF::Extract::Sections::Meta::Scanner/can_compute_size>
285              
286             =head1 IMPLEMENTS ROLES
287              
288             =head2 ELF::Extract::Sections::Meta::Scanner
289              
290             L<ELF::Extract::Sections::Meta::Scanner>
291              
292             =head1 AUTHOR
293              
294             Kent Fredric <kentnl@cpan.org>
295              
296             =head1 COPYRIGHT AND LICENSE
297              
298             This software is copyright (c) 2015 by Kent Fredric <kentfredric@gmail.com>.
299              
300             This is free software; you can redistribute it and/or modify it under
301             the same terms as the Perl 5 programming language system itself.
302              
303             =cut