File Coverage

lib/ELF/Extract/Sections/Scanner/Objdump.pm
Criterion Covered Total %
statement 64 73 87.6
branch 5 8 62.5
condition n/a
subroutine 18 19 94.7
pod 6 6 100.0
total 93 106 87.7


line stmt bran cond sub pod time code
1 2     2   2788 use 5.010; # $+{}
  2         8  
2 2     2   11 use strict;
  2         3  
  2         50  
3 2     2   9 use warnings;
  2         4  
  2         170  
4              
5             package ELF::Extract::Sections::Scanner::Objdump;
6              
7             # ABSTRACT: An objdump based section scanner.
8              
9             our $VERSION = '1.001002'; # TRIAL
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 2     2   775 use Moose qw( with has );
  2         437688  
  2         17  
14             with 'ELF::Extract::Sections::Meta::Scanner';
15              
16 2     2   11702 use Carp qw( croak );
  2         5  
  2         136  
17 2     2   944 use MooseX::Has::Sugar 0.0300;
  2         711  
  2         14  
18              
19 2     2   868 use MooseX::Types::Moose (qw( Bool HashRef RegexpRef FileHandle Undef Str Int));
  2         57540  
  2         29  
20 2     2   12488 use MooseX::Types::Path::Tiny ('File');
  2         142885  
  2         22  
21 2     2   6031 use MooseX::Params::Validate (qw( validated_list ));
  2         72002  
  2         21  
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33             sub open_file {
34 4     4 1 26 my ( $self, $file ) = validated_list( \@_, file => { isa => File, }, );
35 4         5123 $self->log->debug("Opening $file");
36 4         1099 $self->_file($file);
37 4         17 $self->_filehandle( $self->_objdump );
38 4         192 return 1;
39             }
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51             sub next_section {
52 5672     5672 1 8128 my ($self) = @_;
53 5672         241746 my $re = $self->_section_header_identifier;
54 5672         225842 my $fh = $self->_filehandle;
55 5672         60424 while ( my $line = <$fh> ) {
56 482385 100       2986272 next if $line !~ $re;
57 2     2   2486 my ( $header, $offset ) = ( $+{header}, $+{offset} );
  2         1019  
  2         1041  
  5668         49968  
58 5668         252302 $self->_state( { header => $header, offset => $offset } );
59 5668         18204 $self->log->info("objdump -D -F : Section $header at $offset");
60 5668         287216 return 1;
61             }
62 4         268 $self->_clear_file;
63 4         247 $self->_clear_filehandle;
64 4         227 $self->_clear_state;
65 4         438 return 0;
66             }
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77              
78             sub section_offset {
79 5668     5668 1 7942 my ($self) = @_;
80 5668 50       242153 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         215996 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 7301 my ($self) = @_;
115 5668 50       247891 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         220666 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 14 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         3  
  2         18  
167              
168             sub _build__section_header_identifier {
169 4     4   14 my ($self) = @_;
170 4         308 my $header = $self->_header_regex;
171 4         254 my $offset = $self->_offset_regex;
172              
173 4         433 return qr/${header}\s*${offset}:/;
174             }
175              
176             sub _objdump {
177 4     4   7 my ($self) = @_;
178 4 50       170 if ( open my $fh, q{-|}, q{objdump}, qw( -D -F ), $self->_file->realpath->absolute ) {
179 4         43292 return $fh;
180             }
181 0           $self->log->logconfess(qq{An error occured requesting section data from objdump $^ $@ });
182 0           return;
183             }
184              
185             1;
186              
187             __END__
188              
189             =pod
190              
191             =encoding UTF-8
192              
193             =head1 NAME
194              
195             ELF::Extract::Sections::Scanner::Objdump - An objdump based section scanner.
196              
197             =head1 VERSION
198              
199             version 1.001002
200              
201             =head1 SYNOPSIS
202              
203             This module is a model implementation of a Naive and system reliant ELF Section detector.
204             Its currently highly inefficient due to having to run the entire ELF through a disassembly
205             process to determine the section positions and only I<guesses> at section lengths by
206             advertising that it can't compute sizes.
207              
208             TO use this module, simply initialise L<ELF::Extract::Sections> as so
209              
210             my $extractor = ELF::Extract::Sections->new(
211             file => "/path/to/file.so" ,
212             scanner => "Objdump",
213             );
214              
215             =head1 METHODS
216              
217             =head2 C<open_file>
218              
219             my $boolean = $scanner->open_file( file => File );
220              
221             Opens the file and assigns our state to that file.
222              
223             L<ELF::Extract::Sections::Meta::Scanner/open_file>
224              
225             =head2 C<next_section>
226              
227             my $boolean = $scanner->next_section();
228              
229             Advances our state to the next section.
230              
231             L<ELF::Extract::Sections::Meta::Scanner/next_section>
232              
233             =head2 C<section_offset>
234              
235             my $return = $scanner->section_offset(); # Int | Undef
236              
237             Reports the offset of the currently open section
238              
239             L<ELF::Extract::Sections::Meta::Scanner/section_offset>
240              
241             =head2 C<section_size>
242              
243             my $return = $scanner->section_size(); # BANG
244              
245             Dies, because this module can't compute section sizes.
246              
247             L<ELF::Extract::Sections::Meta::Scanner/section_size>
248              
249             =head2 C<section_name>
250              
251             my $name = $scanner->section_name(); # Str | Undef
252              
253             Returns the name of the current section
254              
255             L<ELF::Extract::Sections::Meta::Scanner/section_name>
256              
257             =head2 C<can_compute_size>
258              
259             my $bool = $scanner->can_compute_size;
260              
261             Returns false
262              
263             L<ELF::Extract::Sections::Meta::Scanner/can_compute_size>
264              
265             =head1 IMPLEMENTS ROLES
266              
267             =head2 ELF::Extract::Sections::Meta::Scanner
268              
269             L<ELF::Extract::Sections::Meta::Scanner>
270              
271             =head1 AUTHOR
272              
273             Kent Fredric <kentnl@cpan.org>
274              
275             =head1 COPYRIGHT AND LICENSE
276              
277             This software is copyright (c) 2015 by Kent Fredric <kentfredric@gmail.com>.
278              
279             This is free software; you can redistribute it and/or modify it under
280             the same terms as the Perl 5 programming language system itself.
281              
282             =cut