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   2054 use 5.010; # $+{}
  2         8  
2 2     2   12 use strict;
  2         3  
  2         55  
3 2     2   11 use warnings;
  2         4  
  2         169  
4              
5             package ELF::Extract::Sections::Scanner::Objdump;
6              
7             # ABSTRACT: An objdump based section scanner.
8              
9             our $VERSION = '1.001003'; # TRIAL
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 2     2   738 use Moose qw( with has );
  2         459108  
  2         20  
14             with 'ELF::Extract::Sections::Meta::Scanner';
15              
16 2     2   14174 use Carp qw( croak );
  2         4  
  2         122  
17 2     2   1005 use MooseX::Has::Sugar 0.0300;
  2         756  
  2         15  
18              
19 2     2   897 use MooseX::Types::Moose (qw( Bool HashRef RegexpRef FileHandle Undef Str Int));
  2         61353  
  2         30  
20 2     2   12759 use MooseX::Types::Path::Tiny ('File');
  2         148863  
  2         21  
21 2     2   6196 use MooseX::Params::Validate (qw( validated_list ));
  2         75780  
  2         19  
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33             sub open_file {
34 4     4 1 32 my ( $self, $file ) = validated_list( \@_, file => { isa => File, }, );
35 4         5798 $self->log->debug("Opening $file");
36 4         1312 $self->_file($file);
37 4         18 $self->_filehandle( $self->_objdump );
38 4         180 return 1;
39             }
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51             sub next_section {
52 5672     5672 1 7902 my ($self) = @_;
53 5672         241071 my $re = $self->_section_header_identifier;
54 5672         225854 my $fh = $self->_filehandle;
55 5672         648078 while ( my $line = <$fh> ) {
56 482385 100       3438781 next if $line !~ $re;
57 2     2   2403 my ( $header, $offset ) = ( $+{header}, $+{offset} );
  2         978  
  2         1058  
  5668         52221  
58 5668         252423 $self->_state( { header => $header, offset => $offset } );
59 5668         19270 $self->log->info("objdump -D -F : Section $header at $offset");
60 5668         289127 return 1;
61             }
62 4         217 $self->_clear_file;
63 4         204 $self->_clear_filehandle;
64 4         209 $self->_clear_state;
65 4         390 return 0;
66             }
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77              
78             sub section_offset {
79 5668     5668 1 7235 my ($self) = @_;
80 5668 50       242096 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         218237 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 7502 my ($self) = @_;
115 5668 50       247140 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         219598 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 20 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   12 no Moose;
  2         4  
  2         18  
167              
168             sub _build__section_header_identifier {
169 4     4   27 my ($self) = @_;
170 4         226 my $header = $self->_header_regex;
171 4         200 my $offset = $self->_offset_regex;
172              
173 4         361 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   9 my ($self) = @_;
196 4 50 33     46 if ( 'MSWin32' eq $^O or $ENV{OBJDUMP_SLURP} ) {
197 0         0 return $self->_objdump_win32;
198             }
199 4 50       182 if ( open my $fh, q{-|}, q{objdump}, qw( -D -F ), $self->_file->realpath->absolute ) {
200 4         36794 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.001003
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