File Coverage

blib/lib/Parse/Readelf/Debug/Info.pm
Criterion Covered Total %
statement 258 263 98.1
branch 214 236 90.6
condition 118 153 77.1
subroutine 12 12 100.0
pod 4 4 100.0
total 606 668 90.7


line stmt bran cond sub pod time code
1             package Parse::Readelf::Debug::Info;
2              
3             # Author, Copyright and License: see end of file
4              
5             =head1 NAME
6              
7             Parse::Readelf::Debug::Info - handle readelf's debug info section with a class
8              
9             =head1 SYNOPSIS
10              
11             use Parse::Readelf::Debug::Info;
12              
13             my $debug_info = new Parse::Readelf::Debug::Info($executable);
14              
15             my @item_ids = $debug_info->item_ids('l_object2a');
16             my @structure_layout1 = $debug_info->structure_layout($item_ids[0]);
17             my @some_item_ids = $debug_info->item_ids_matching('^var', 'variable');
18             my @all_item_ids = $debug_info->item_ids_matching('');
19             my @all_struct_ids = $debug_info->item_ids_matching('', '.*structure.*');
20              
21             =head1 ABSTRACT
22              
23             Parse::Readelf::Debug::Info parses the output of C
24             --debug-dump=info> and stores its interesting details in an object to
25             ease access.
26              
27             =head1 DESCRIPTION
28              
29             Normally an object of this class is constructed with the file name of
30             an object file to be parsed. Upon construction the file is analysed
31             and all relevant information about its debug info section is stored
32             inside of the object. This information can be accessed afterwards
33             using a bunch of getter methods, see L for details.
34              
35             AT THE MOMENT ONLY INFORMATION REGARDING THE BINARY ARRANGEMENT OF
36             VARIABLES (STRUCTURE LAYOUT) IS SUPPORTED. Other data is ignored for
37             now.
38              
39             Currently only output for B is supported. Please
40             contact the author for other versions and provide some example
41             C outputs.
42              
43             =cut
44              
45             #########################################################################
46              
47 3     3   1166 use 5.006001;
  3         10  
  3         106  
48 3     3   13 use strict;
  3         4  
  3         93  
49 3     3   26 use warnings;
  3         6  
  3         76  
50 3     3   12 use Carp;
  3         4  
  3         243  
51              
52             our $VERSION = '0.18';
53              
54 3     3   710 use Parse::Readelf::Debug::Line;
  3         5  
  3         9120  
55              
56             #########################################################################
57              
58             =head1 EXPORT
59              
60             Nothing is exported by default as it's normally not needed to modify
61             any of the variables declared in the following export groups:
62              
63             =head2 :all
64              
65             all of the following groups
66              
67             =cut
68              
69             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
70              
71             require Exporter;
72              
73             our @ISA = qw(Exporter);
74             our @EXPORT = qw();
75              
76             our %EXPORT_TAGS =
77             (command => [ qw($command) ],
78             config => [ qw($display_nested_items $re_substructure_filter) ],
79             constants => [ qw($LEVEL $NAME $TYPE $SIZE $LOCATION $OFFSET
80             $BITSIZE $BITOFFSET) ],
81             fixed_regexps => [ qw($re_section_start
82             $re_section_stop
83             $re_unit_offset
84             $re_dwarf_version
85             $re_unit_signature
86             $re_type_offset) ],
87             versioned_regexps => [ qw(@re_item_start
88             @re_bit_offset
89             @re_bit_size
90             @re_byte_size
91             @re_comp_dir
92             @re_const_value
93             @re_containing_type
94             @re_decl_file
95             @re_decl_line
96             @re_declaration
97             @re_encoding
98             @re_external
99             @re_language
100             @re_linkage_name_tag
101             @re_location
102             @re_member_location
103             @re_name_tag
104             @re_producer
105             @re_signature_tag
106             @re_specification
107             @re_type
108             @re_upper_bound
109             @re_ignored_attributes
110             @tag_needs_attributes
111             @ignored_tags) ]
112             );
113             $EXPORT_TAGS{all} = [ map { @$_ } values(%EXPORT_TAGS) ];
114              
115             our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
116              
117             #########################################################################
118              
119             =head2 :command
120              
121             =over
122              
123             =item I<$command>
124              
125             is the variable holding the command to run C to get the
126             information relevant for this module, normally C
127             --debug-dump=line>.
128              
129             =back
130              
131             =cut
132              
133             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
134              
135             our $command = 'readelf --debug-dump=info';
136              
137             #########################################################################
138              
139             =head2 :config
140              
141             =over
142              
143             =item I<$display_nested_items>
144              
145             is a variable which controls if nested items (e.g. sub-structures) are
146             not displayed unless actually used (e.g. as data type of members of
147             their parent) or if they are always displayed - which might confuse
148             the reader. The default is 0, any other value switches on the
149             unconditional display.
150              
151             =item I<$re_substructure_filter>
152              
153             is a regular expression that allows you to cut away the details of all
154             substructures whose type names match the filter. This is useful if
155             you have a bunch of types that you consider so basic that you like to
156             blend out their details, e.g. the internal representation of a complex
157             number datatype. The filter has the value C<^string$> for C++
158             standard strings as default.
159              
160             =back
161              
162             =cut
163              
164             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
165              
166             our $display_nested_items = 0;
167              
168             our $re_substructure_filter = '^string$';
169              
170             #########################################################################
171              
172             =head2 :constants
173              
174             The following constants can be used to access the elements of the
175             result of the method L (see below).
176              
177             =over
178              
179             =item I<$LEVEL>
180              
181             =item I<$NAME>
182              
183             =item I<$TYPE>
184              
185             =item I<$SIZE>
186              
187             =item I<$LOCATION>
188              
189             =item I<$OFFSET>
190              
191             =item I<$BITSIZE>
192              
193             =item I<$BITOFFSET>
194              
195             =back
196              
197             =cut
198              
199             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
200              
201             our $LEVEL = 0;
202             our $NAME = 1;
203             our $TYPE = 2;
204             our $SIZE = 3;
205             our $LOCATION = 4;
206             our $OFFSET = 5;
207             our $BITSIZE = 6;
208             our $BITOFFSET = 7;
209              
210             #########################################################################
211              
212             =head2 :fixed_regexps
213              
214             =over
215              
216             =item I<$re_section_start>
217              
218             is the regular expression that recognises the start of the info debug
219             output of C.
220              
221             =item I<$re_section_stop>
222              
223             is the regular expression that recognises the start of another debug
224             output of C.
225              
226             =item I<$re_unit_offset>
227              
228             is the regular expression that recognises the first line of a
229             compilation unit in an info debug output of C. This line
230             states the offset of the compilation unit itself. So this offset must
231             be a hexadecimal string which will (must) be stored in C<$1> without
232             any leading C<0x>. Usually it's 0 for the first unit.
233              
234             =item I<$re_dwarf_version>
235              
236             is the regular expression that recognises the Dwarf version line in an
237             info debug output of C. The version number must be an
238             integer number which will (must) be stored in C<$1>.
239              
240             =item I<$re_unit_signature>
241              
242             is the regular expression that recognises the hexadecimal signature
243             line at the start of a compilation unit in an info debug output of
244             C. The signature ID must be a string which will (must) be
245             stored in C<$1>.
246              
247             =item I<$re_type_offset>
248              
249             is the regular expression that recognises the type offset line at the
250             start of a compilation unit in an info debug output of C.
251             The offset must be a string which will (must) be stored in C<$1>
252             without any leading C<0x>.
253              
254             =back
255              
256             =cut
257              
258             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
259              
260             our $re_section_start =
261             qr(^The section \.debug_info contains:|^Contents of the \.debug_(?:info|types) section:);
262              
263             our $re_section_stop =
264             qr(^The section \.debug_.* contains:|^Contents of the \.debug_.* section:);
265              
266             our $re_unit_offset = qr(^\s*Compilation Unit\s.*\soffset\s+(?:0x)?([0-9a-f]+));
267              
268             our $re_dwarf_version = qr(^\s*Version:\s+(\d+)\s*$);
269              
270             our $re_unit_signature = qr(^\s*Signature:\s+([0-9a-f]+)\s*$);
271              
272             our $re_type_offset = qr(^\s*Type Offset:\s+(?:0x)?([0-9a-f]+)\s*$);
273              
274             #########################################################################
275              
276             =head2 :versioned_regexps
277              
278             These regular expressions are those that recognise the (yet) supported
279             tags of the item nodes of a readelf debug info output. Each of them
280             is actually a list using the Dwarf version as index:
281              
282             =over
283              
284             =item I<@re_item_start>
285              
286             recognises the start of a new item in the debug info list. C<$1> is
287             the level, C<$2> the internal (unique) item ID, C<$3> the numeric type
288             ID and C<$4> the type tag.
289              
290             =item I<@re_bit_offset>
291              
292             recognises the bit offset tag of an item. C<$1> will contain the offset.
293              
294             =item I<@re_bit_size>
295              
296             recognises the bit size tag of an item. C<$1> will contain the size.
297              
298             =item I<@re_byte_size>
299              
300             recognises the byte size tag of an item. C<$1> will contain the size.
301              
302             =item I<@re_comp_dir>
303              
304             recognises the compilation directory tag of an item. C<$1> will
305             contain the compilation directory as string.
306              
307             =item I<@re_const_value>
308              
309             recognises the const value tag of an item. C<$1> will contain the value.
310              
311             =item I<@re_containing_type>
312              
313             recognises the containing type tag of an item. Either C<$1> will
314             contain the normal internal item ID or C will contain the Dwarf-4
315             signature of the containing type.
316              
317             =item I<@re_decl_file>
318              
319             recognises the declaration file tag of an item. C<$1> will contain
320             the number of the file name (see L).
321              
322             =item I<@re_decl_line>
323              
324             recognises the declaration line tag of an item. C<$1> will contain
325             the line number.
326              
327             =item I<@re_declaration>
328              
329             recognises the declaration tag of an item. C<$1> will usually contain a
330             1 indicating that it is set.
331              
332             =item I<@re_encoding>
333              
334             recognises the encoding tag of an item. C<$1> will contain the
335             encoding as text.
336              
337             =item I<@re_external>
338              
339             recognises the external tag of an item. C<$1> will usually contain a
340             1 indicating that it is set.
341              
342             =item I<@re_language>
343              
344             recognises the language tag of an item. C<$1> will contain the
345             language as text.
346              
347             =item I<@re_linkage_name_tag>
348              
349             recognises the linkage name tag of an item. C<$1> will contain the
350             name.
351              
352             =item I<@re_location>
353              
354             recognises the data member location tag of an item. C<$1> will
355             contain the offset.
356              
357             =item I<@re_member_location>
358              
359             recognises the data location tag of an item. C<$1> will contain the
360             hex value (with spaces between each byte).
361              
362             =item I<@re_name_tag>
363              
364             recognises the name tag of an item. C<$1> will contain the name.
365              
366             =item I<@re_producer>
367              
368             recognises the producer tag of an item. C<$1> will contain the
369             producer as string.
370              
371             =item I<@re_signature_tag>
372              
373             recognises the signature tag of an item. C<$1> will contain the
374             leading C<<0x> in case of a signature refering to the same compilation
375             unit, C<$2> will contain the hexadecimal signature.
376              
377             =item I<@re_specification>
378              
379             recognises the specification tag of an item. C<$1> will contain the
380             internal item ID of the specification.
381              
382             =item I<@re_type>
383              
384             recognises the type tag of an item. Either C<$1> will contain the
385             normal internal item ID or C will contain the Dwarf-4 signature of
386             the type.
387              
388             =item I<@re_upper_bound>
389              
390             recognises the upper bound tag of a subrange item. C<$1> will contain
391             the upper bound.
392              
393             =item I<@re_ignored_attributes>
394              
395             recognises all attributes that are simply ignored (yet).
396              
397             =back
398              
399             The last two lists are a bit different, they control what is parsed by
400             this module. They are also arrays using the Dwarf version as index.
401             What is inside each of this arrays is described below:
402              
403             =over
404              
405             =item I<@tag_needs_attributes>
406              
407             holds hashes of the type tags that are processed. Each element points
408             to a list of the absolutely needed attributes for that type of item.
409              
410             =item I<@ignored_tags>
411              
412             is a list of the type tags (see C<@re_item_start> above) that are
413             currently ignored.
414              
415             =back
416              
417             =cut
418              
419             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
420              
421             our @re_item_start =
422             ( undef, undef,
423             qr'^\s*<(\d+)><([0-9A-F]+)>:\s+abbrev\s+number:\s+(\d+)\s+\((.*)\)'i,
424             undef,
425             qr'^\s*<(\d+)><([0-9A-F]+)>:\s+abbrev\s+number:\s+(\d+)\s+\((.*)\)'i
426             );
427              
428             our @re_abstract_origin =
429             ( undef, undef,
430             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_abstract_origin\s*:\s+<(?:0x)?([0-9A-F]+)>)i,
431             undef,
432             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_abstract_origin\s*:\s+<(?:0x)?([0-9A-F]+)>)i
433             );
434              
435             our @re_bit_offset =
436             ( undef, undef,
437             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_bit_offset\s*:\s+(\d+))i,
438             undef,
439             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_bit_offset\s*:\s+(\d+))i
440             );
441              
442             our @re_bit_size =
443             ( undef, undef,
444             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_bit_size\s*:\s+(\d+))i,
445             undef,
446             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_bit_size\s*:\s+(\d+))i
447             );
448              
449             our @re_byte_size =
450             ( undef, undef,
451             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_byte_size\s*:\s+(\d+))i,
452             undef,
453             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_byte_size\s*:\s+(\d+))i
454             );
455              
456             our @re_comp_dir =
457             ( undef, undef,
458             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_comp_dir\s*:(?:.+:)?\s+(.+))i,
459             undef,
460             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_comp_dir\s*:(?:.+:)?\s+(.+))i
461             );
462              
463             our @re_const_value =
464             ( undef, undef,
465             qr{^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_const_value\s*:\s+([-\d]+|\*|ALL|\(indirect string, .*|\w{1,4})}i,
466             undef,
467             qr{^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_const_value\s*:\s+([-\d]+|\*|ALL|\(indirect string, .*|\w{1,4})}i
468             );
469              
470             our @re_containing_type =
471             ( undef, undef,
472             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_containing_type\s*:\s+<(?:0x)?([0-9A-F]+)>)i,
473             undef,
474             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_containing_type\s*:\s+(?:<(?:0x)?([0-9A-F]+)>|signature\s*:\s+([0-9A-F]+)))i
475             );
476              
477             our @re_decl_file =
478             ( undef, undef,
479             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_decl_file\s*:\s+(\d+))i,
480             undef,
481             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_decl_file\s*:\s+(\d+))i
482             );
483              
484             our @re_decl_line =
485             ( undef, undef,
486             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_decl_line\s*:\s+(\d+))i,
487             undef,
488             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_decl_line\s*:\s+(\d+))i
489             );
490              
491             our @re_declaration =
492             ( undef, undef,
493             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_declaration\s*:\s+(\d+))i,
494             undef,
495             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_declaration\s*:\s+(\d+))i
496             );
497              
498             our @re_encoding =
499             ( undef, undef,
500             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_encoding\s*:\s+\d+\s+\(([a-z ]+)\)'i,
501             undef,
502             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_encoding\s*:\s+\d+\s+\(([a-z ]+)\)'i
503             );
504              
505             our @re_external =
506             ( undef, undef,
507             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_external\s*:\s+(\d+))i,
508             undef,
509             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_external\s*:\s+(\d+))i
510             );
511              
512             our @re_language =
513             ( undef, undef,
514             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_language\s*:\s+\d+\s+\((.+)\)'i,
515             undef,
516             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_language\s*:\s+\d+\s+\((.+)\)'i
517             );
518              
519             our @re_linkage_name_tag =
520             ( undef, undef,
521             undef, # new in Dwarf-4?
522             undef,
523             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_linkage_name\b.*:\s+(.*[\w>]))i
524             );
525              
526             our @re_location =
527             ( undef, undef,
528             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_location\s*:\s*\d+ byte block:\s+([[:xdigit:]]{1,2}(?: [[:xdigit:]]{1,2})*)\s+\W)i,
529             undef,
530             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_location\s*:\s*\d+ byte block:\s+([[:xdigit:]]{1,2}(?: [[:xdigit:]]{1,2})*)\s+\W)i
531             );
532              
533             our @re_member_location =
534             ( undef, undef,
535             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_data_member_location:.*DW_OP_(?:(?:plus_uconst|const1u):\s+(\d+))?)i,
536             undef,
537             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_data_member_location:\s+(\d+))i
538             );
539              
540             our @re_name_tag =
541             ( undef, undef,
542             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_name\b.*:\s+(.*[\w>]))i,
543             undef,
544             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_name\b.*:\s+(.*[\w>]))i
545             );
546              
547             our @re_producer =
548             ( undef, undef,
549             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_producer\s*:(?:\s+\(.+\):)?\s+(.+)'i,
550             undef,
551             qr'^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_producer\s*:(?:\s+\(.+\):)?\s+(.+)'i
552             );
553              
554             our @re_signature_tag =
555             ( undef, undef,
556             undef, # new in Dwarf-4?
557             undef,
558             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_signature\b.*:\s+(<0x)?([0-9A-F]+)>?)i
559             );
560              
561             our @re_specification =
562             ( undef, undef,
563             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_specification\s*:\s+<(?:0x)?([0-9A-F]+)>)i,
564             undef,
565             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_specification\s*:\s+<(?:0x)?([0-9A-F]+)>)i
566             );
567              
568             our @re_type =
569             ( undef, undef,
570             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_type\s*:\s+<(?:0x)?([0-9A-F]+)>)i,
571             undef,
572             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_type\s*:\s+(?:<(?:0x)?([0-9A-F]+)>|signature\s*:\s+([0-9A-F]+)))i
573             );
574              
575             our @re_upper_bound =
576             ( undef, undef,
577             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_upper_bound\s*:\s+(\d+))i,
578             undef,
579             qr(^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_upper_bound\s*:\s+(\d+))i
580             );
581              
582 3         1269 use constant IGNORED_ATTRIBUTES => qw(GNU_macros
583             accessibility
584             artificial
585             encoding
586             entry_pc
587             high_pc
588             low_pc
589             macro_info
590             MIPS_linkage_name
591             producer
592             ranges
593             sibling
594             stmt_list
595 3     3   24 virtuality);
  3         4  
596             our @re_ignored_attributes =
597             ( undef, undef,
598             '^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_(?:(?:'.
599             join('|', IGNORED_ATTRIBUTES).
600             ')\b|location\s*:\s*0x)',
601             undef,
602             '^\s*(?:<[0-9A-F ]+>)?\s*DW_AT_(?:(?:'.
603             join('|', IGNORED_ATTRIBUTES).
604             ')\b|location\s*:\s*0x)'
605             );
606              
607             our @tag_needs_attributes =
608             (
609             undef,
610             undef,
611             {
612             # Note that in combination with a C typedef the name is often missing!
613             DW_TAG_array_type => [ qw(type) ],
614             DW_TAG_base_type => [ qw(name) ],
615             DW_TAG_class_type => [],
616             DW_TAG_const_type => [ qw(type) ],
617             DW_TAG_compile_unit => [ qw(name) ],
618             DW_TAG_enumerator => [ qw(name) ],
619             DW_TAG_enumeration_type => [ qw(byte_size) ],
620             DW_TAG_formal_parameter => [ qw(type) ],
621             DW_TAG_inheritance => [qw(type member_location)],
622             DW_TAG_member => [ qw(name type member_location) ],
623             DW_TAG_pointer_type => [ qw(byte_size) ],
624             DW_TAG_ptr_to_member_type => [ qw(containing_type) ],
625             DW_TAG_reference_type => [ qw(type byte_size) ],
626             DW_TAG_structure_type => [],
627             DW_TAG_subrange_type => [ qw(upper_bound) ],
628             DW_TAG_template_type_param => [ qw(name byte_size) ],
629             DW_TAG_template_value_param => [ qw(name type) ],
630             DW_TAG_typedef => [ qw(name type) ],
631             DW_TAG_union_type => [ qw(byte_size) ],
632             DW_TAG_variable => [ qw(name type) ],
633             DW_TAG_volatile_type => [ qw(type) ]
634             },
635             undef,
636             {
637             # Note that in combination with a C typedef the name is often missing!
638             DW_TAG_array_type => [ qw(type) ],
639             DW_TAG_base_type => [ qw(name) ],
640             DW_TAG_class_type => [],
641             DW_TAG_const_type => [ qw(type) ],
642             DW_TAG_compile_unit => [ qw(name) ],
643             DW_TAG_enumerator => [ qw(name) ],
644             DW_TAG_enumeration_type => [ qw(byte_size) ],
645             DW_TAG_formal_parameter => [ qw(type) ],
646             DW_TAG_inheritance => [qw(type member_location)],
647             DW_TAG_member => [ qw(name type member_location) ],
648             DW_TAG_pointer_type => [ qw(byte_size) ],
649             DW_TAG_ptr_to_member_type => [ qw(containing_type) ],
650             DW_TAG_reference_type => [ qw(type byte_size) ],
651             DW_TAG_structure_type => [],
652             DW_TAG_subrange_type => [ qw(upper_bound) ],
653             DW_TAG_template_type_param => [ qw(name byte_size) ],
654             DW_TAG_template_value_param => [ qw(name type) ],
655             DW_TAG_typedef => [ qw(name type) ],
656             DW_TAG_union_type => [ qw(byte_size) ],
657             DW_TAG_variable => [ qw(name type) ],
658             DW_TAG_volatile_type => [ qw(type) ]
659             }
660             );
661              
662             our @ignored_tags =
663             (
664             undef,
665             undef,
666             [
667             qw(
668             DW_TAG_GNU_call_site
669             DW_TAG_GNU_call_site_parameter
670             DW_TAG_inlined_subroutine
671             DW_TAG_imported_declaration
672             DW_TAG_imported_module
673             DW_TAG_label
674             DW_TAG_lexical_block
675             DW_TAG_namespace
676             DW_TAG_subprogram
677             DW_TAG_subroutine_type
678             DW_TAG_unspecified_parameters
679             ),
680             'Unknown TAG value: 4109',
681             'Unknown TAG value: 410a'
682             ],
683             undef,
684             [
685             qw(
686             DW_TAG_GNU_call_site
687             DW_TAG_GNU_call_site_parameter
688             DW_TAG_inlined_subroutine
689             DW_TAG_imported_declaration
690             DW_TAG_imported_module
691             DW_TAG_inheritance
692             DW_TAG_label
693             DW_TAG_lexical_block
694             DW_TAG_namespace
695             DW_TAG_subprogram
696             DW_TAG_subroutine_type
697             DW_TAG_type_unit
698             DW_TAG_unspecified_parameters
699             ),
700             'Unknown TAG value: 4109',
701             'Unknown TAG value: 410a'
702             ]
703             );
704              
705             # list of attributes holding readelf hexadecimal IDs that must be
706             # remapped in Dwarf-4 compilation units with signatures:
707 3     3   17 use constant ID_ATTRIBUTES => qw(sibling specification type);
  3         4  
  3         188  
708              
709             # list of attributes that may hold a signature instead of an ID in
710             # Dwarf-4:
711 3     3   14 use constant SIGNATURE_ATTRIBUTES => qw(signature type);
  3         4  
  3         13913  
712              
713             #########################################################################
714              
715             =head2 new - get readelf's debug info section into an object
716              
717             $debug_info = new Parse::Readelf::Debug::Info($file_name,
718             [$line_info]);
719              
720             =head3 example:
721              
722             $debug_info1 = new Parse::Readelf::Debug::Info('program');
723             $line_info = new Parse::Readelf::Debug::Line('module.o');
724             $debug_info2 = new Parse::Readelf::Debug::Info('module.o',
725             $line_info);
726              
727             =head3 parameters:
728              
729             $file_name name of executable or object file
730             $line_info a L object
731              
732             =head3 description:
733              
734             This method parses the output of C and
735             stores its interesting details internally to be accessed later by
736             getter methods described below.
737              
738             If no L object is passed as second
739             parameter the method creates one internally at it is needed to
740             locate the source files.
741              
742             =head3 global variables used:
743              
744             The method uses all of the variables described above in the
745             L section.
746              
747             =head3 returns:
748              
749             The method returns the blessed Parse::Readelf::Debug::Info object
750             or an exception in case of an error.
751              
752             =cut
753              
754             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
755             sub new($$;$)
756             {
757 20     20 1 31534 my $this = shift;
758 20   100     153 my $class = ref($this) || $this;
759 20         40 my ($file_name, $line_info) = @_;
760 20         141 my %self = (line_info => $line_info,
761             items => [],
762             item_map => {},
763             name_map => {});
764 20         44 local $_;
765              
766             # checks:
767 20 100       66 if (! $file_name)
768 1         198 { croak 'bad call to new of ', __PACKAGE__ }
769 19 100       53 if (ref($this))
770 1         346 { carp 'cloning of a ', __PACKAGE__, ' object is not supported' }
771 19 100       660 if (! -f $file_name)
772 1         175 { croak __PACKAGE__, " can't find ", $file_name }
773 18 100 100     100 if (defined $line_info and
774             ref($line_info) ne 'Parse::Readelf::Debug::Line')
775 1         146 { croak 'bad Parse::Readelf::Debug::Line object passed to ', __PACKAGE__ }
776              
777             # first get debug line section parsed:
778 17 100       132 $self{line_info} = new Parse::Readelf::Debug::Line($file_name)
779             unless defined $line_info;
780              
781             # call readelf and prepare parsing output:
782 17 100       33523 open READELF, '-|', $command.' '.$file_name or
783             croak "can't parse ", $file_name, ' with "', $command, '" in ',
784             __PACKAGE__, ': ', $!;
785              
786             # find start of section:
787 16         12312 while ()
788 130 100       853 { last if m/$re_section_start/; }
789              
790             # parse section:
791 16         56 my $version = -1;
792 16         30 my $unit_offset = 0;
793 16         57 my $signature = '';
794 16         32 my $type_offset = '';
795 16         86 my @level_stack = (undef);
796 16         91 my $item = undef;
797 16         29 my $needed_attributes = undef;
798 16         64 my %is_ignored = ();
799 16         32 my $tag_needs_attributes = undef;
800 16         41 my $compilation_unit = -1;
801 16         34 my %compilation_unit_list = ();
802 16         134 while ()
803             {
804 76656 100       406067 if (m/$re_dwarf_version/)
    100          
    100          
    100          
805             {
806 108         246 $version = $1;
807 108 100       947 confess 'DWARF version ', $version, ' not supported in ',
808             __PACKAGE__
809             unless defined $re_item_start[$version];
810 107         149 %is_ignored = map { $_ => 1 } @{$ignored_tags[$version]};
  1565         3826  
  107         378  
811 107         370 $tag_needs_attributes = $tag_needs_attributes[$version];
812 107         148 $compilation_unit++;
813 107         187 $signature = $type_offset = '';
814             }
815             elsif (m/$re_unit_offset/)
816             {
817 108         367 $unit_offset = hex($1);
818             }
819             elsif (m/$re_unit_signature/)
820             {
821 84         418 $signature = $1;
822             }
823             elsif (m/$re_type_offset/)
824             {
825 84 50       236 $signature
826             or confess 'internal error: type offset without previous ',
827             'signature at input line ', $., ' in ', __PACKAGE__;
828 84         534 $type_offset = sprintf("%x", $unit_offset + hex($1));
829             }
830 76655 100       107394 next unless $version >= 0;
831              
832             # stop at end of section:
833 76613 100 100     343812 if (m/$re_section_stop/ and not m/$re_section_start/)
834             {
835 3         5265 my $dummy = grep /nothing/, ; # avoid SIGPIPE in close
836 3         365 last;
837             }
838              
839             # handle the beginning (and therefore the change) of an item:
840 76610 100 100     1709565 if (m/$re_item_start[$version]/i)
    100 100        
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
841             {
842             # check if item is complete and store it:
843 16663 100       25353 if (defined $item)
844             {
845             # fix IDs in compilation units with signature:
846 12312 100       17553 if ($signature)
847             {
848 2748         5892 foreach (ID_ATTRIBUTES)
849             {
850 8244 100 100     28346 $item->{$_} = $compilation_unit.'_'.$item->{$_}
851             if defined $item->{$_} and $item->{$_} !~ m/^S/;
852             }
853             # TODO: remove when Dwarf-4 is no longer experimental:
854 2748         8436 foreach (keys %$item)
855             {
856 16857 50       31622 confess 'internal error: attribute ', $_,
857             ' needs remapping in compilation unit ',
858             '(add to ID_ATTRIBUTES in ', __PACKAGE__, ')'
859             if m/^[0-9a-f]{1,7}$/;
860             }
861 2748 100       7769 if ($item->{id} eq $compilation_unit.'_'.$type_offset)
862             {
863 84         262 $compilation_unit_list{$signature} = $item->{id};
864             }
865             }
866             # special handling of indirect variables of
867             # non-optimised inline functions:
868 12312 50 66     25280 if (defined $item->{abstract_origin} and
869             (defined $item->{type_tag} eq 'DW_TAG_variable' ))
870             {
871             # TODO: This needs a test case!
872 0         0 warn "abstract variable";
873 0         0 $item = undef;
874 0         0 next;
875             }
876             # normal handling:
877 12312         17124 foreach (@$needed_attributes)
878             {
879 15620 100       36893 next if defined $item->{$_};
880             # special handling of items that contain
881             # additional info needed by other items:
882 484 100 100     1712 if ($item->{type_tag} eq 'DW_TAG_member' &&
      66        
      100        
      66        
883             defined $item->{member_location} &&
884             defined $item->{type} &&
885             defined $self{item_map}->{$item->{type}} &&
886             ! defined
887             $self{item_map}->{$item->{type}}->{member_location})
888             {
889 5         18 $self{item_map}->{$item->{type}}->{member_location} =
890             $item->{member_location};
891             }
892             #TODO: activate check again later or in case of problems (missing info):
893             # carp('necessary attribute tag ', $_, ' is missing in ',
894             # $item->{type_tag},
895             # (defined $item->{name} ? ' for '.$item->{name} : ''),
896             # ' at position ', $item->{id});
897 484         507 $item = undef;
898 484         1469 last;
899             }
900             }
901 16663 100       28305 if (defined $item)
902             {
903 11828 50       19306 confess 'item ', $item, ' has no type tag in ', __PACKAGE__
904             unless $item->{type_tag};
905 11828         8960 push @{$self{items}}, $item;
  11828         19748  
906 11828         29241 $self{item_map}->{$item->{id}} = $item;
907             # handle stack of item levels:
908 11828 100       26018 if ($item->{level} >= 1)
909             {
910 11807 100       19417 push @{$level_stack[$item->{level} - 1]->{sub_items}},
  9133         20211  
911             $item
912             if $item->{level} > 1;
913 11807         32427 pop @level_stack while ($#level_stack >= $item->{level});
914 11807         13027 $level_stack[$item->{level}] = $item;
915             # inheritance entries (almost) never have file/line:
916 11807 50 66     23759 if ($item->{type_tag} eq 'DW_TAG_inheritance' and
      66        
917             not defined $item->{decl_file} and
918             defined $level_stack[$item->{level} - 1]->{decl_file})
919             {
920 30         102 $item->{decl_file} =
921             $level_stack[$item->{level} - 1]->{decl_file};
922 30         105 $item->{decl_line} =
923             $level_stack[$item->{level} - 1]->{decl_line};
924             }
925             }
926             # Take special care of structure names that are stored
927             # in another node:
928 11828         12119 my $name = $item->{name};
929 11828 100 100     50270 if (not defined $name and
      100        
      100        
930             $item->{type_tag} =~ m/^DW_TAG_(?:class|structure|union)_type$/
931             and
932             defined $item->{specification} and
933             defined $self{item_map}->{$item->{specification}})
934             {
935 100         276 $name = $self{item_map}->{$item->{specification}}->{name};
936             }
937             # the name map can store items with unique names
938             # (simple reference) and identical names (array of
939             # references):
940 11828 100       17885 if (defined $name)
941             {
942 3776 100       9581 if (not defined $self{name_map}->{$name})
    100          
    50          
943 2761         6158 { $self{name_map}->{$name} = $item }
944             elsif (ref($self{name_map}->{$name}) eq 'HASH')
945             {
946 462         1221 $self{name_map}->{$name} =
947             [ $self{name_map}->{$name}, $item ]
948             }
949             elsif (ref($self{name_map}->{$name}) eq 'ARRAY')
950 553         550 { push @{$self{name_map}->{$name}}, $item }
  553         1188  
951             else
952             {
953 0         0 confess 'internal error: invalid reference type ',
954             ref($self{name_map}->{$name}),
955             ' in name_map in ', __PACKAGE__
956             }
957             }
958             # for items with known location add object id:
959 11828 100       18398 if (defined $item->{decl_file})
960 2716         3432 { $item->{compilation_unit} = $compilation_unit }
961             # brush up stored item with a few item tag specific fixes:
962 11828 100 66     26528 $item->{name} = 'void'
      100        
963             if ($item->{type_tag} eq 'DW_TAG_pointer_type' and
964             not defined $item->{name} and
965             not defined $item->{type});
966             # save a bit of memory (strings):
967             }
968             # prepare node for next item (we ignore the type ID in $3
969             # except for the carp below as the ID uses a new sequence
970             # for every compilation unit and is therefore pretty much
971             # worthless for us):
972 16663 100       89791 $item = { level => $1,
973             id => $signature ? $compilation_unit.'_'.$2 : $2,
974             type_tag => $4,
975             sub_items => [] };
976 16663 100       38737 if (defined $tag_needs_attributes->{$4})
    100          
977             {
978 12325         48480 $needed_attributes = $tag_needs_attributes->{$4};
979             }
980             elsif ($is_ignored{$4})
981             {
982 4337         16415 pop @level_stack while ($#level_stack >= $item->{level});
983 4337         19363 $item = undef;
984             }
985             else
986             {
987 1         123 carp 'unknown item type ', $4, ' (', $3,
988             ') found at position ', $2;
989 1         10 $item = undef;
990             }
991             }
992             elsif (not defined $item)
993 26461         56273 { next }
994             elsif (m/$re_abstract_origin[$version]/)
995 114         394 { $item->{abstract_origin} = $1 }
996             elsif (m/$re_bit_offset[$version]/)
997 92         443 { $item->{bit_offset} = $1 }
998             elsif (m/$re_bit_size[$version]/)
999 92         458 { $item->{bit_size} = $1 }
1000             elsif (m/$re_byte_size[$version]/)
1001 1589         7219 { $item->{byte_size} = $1 }
1002             elsif (m/$re_comp_dir[$version]/)
1003 23         280 { $item->{comp_dir} = $1 }
1004             elsif (m/$re_const_value[$version]/)
1005 693         3250 { $item->{const_value} = $1 }
1006             elsif (m/$re_containing_type[$version]/)
1007 0 0       0 { $item->{containing_type} = defined $2 ? 'S'.$2 : $1 }
1008             elsif (m/$re_decl_file[$version]/)
1009 2844         12597 { $item->{decl_file} = $1 }
1010             elsif (m/$re_decl_line[$version]/)
1011 2844         12361 { $item->{decl_line} = $1 }
1012             elsif (m/$re_declaration[$version]/)
1013 1221         6236 { $item->{declaration} = $1 }
1014             elsif (m/$re_encoding[$version]/)
1015 533         2732 { $item->{encoding} = $1 }
1016             elsif (m/$re_external[$version]/)
1017 905         4076 { $item->{external} = $1 }
1018             elsif (m/$re_language[$version]/)
1019 23         413 { $item->{language} = $1 }
1020             elsif (defined $re_linkage_name_tag[$version] and
1021             m/$re_linkage_name_tag[$version]/)
1022 33         152 { $item->{linkage_name} = $1 }
1023             elsif (m/$re_location[$version]/)
1024 156         700 { $item->{location} = $1 }
1025             elsif (m/$re_member_location[$version]/)
1026 1050 50       6320 { $item->{member_location} = $1 if defined $1; }
1027             elsif (m/$re_name_tag[$version]/)
1028 3917         20291 { $item->{name} = $1 }
1029             elsif (m/$re_producer[$version]/)
1030 23         184 { $item->{producer} = $1 }
1031             elsif (defined $re_signature_tag[$version] and
1032             m/$re_signature_tag[$version]/)
1033 21 50       156 { $item->{signature} = defined $1 ? $2 : 'S'.$2 }
1034             elsif (m/$re_specification[$version]/)
1035 155         870 { $item->{specification} = $1 }
1036             elsif (m/$re_type[$version]/)
1037 10677 100       61812 { $item->{type} = defined $2 ? 'S'.$2 : $1 }
1038             elsif (m/$re_upper_bound[$version]/)
1039 62         428 { $item->{upper_bound} = $1 }
1040             elsif (m/$re_ignored_attributes[$version]/i)
1041             {}
1042             elsif (m/^\s*(?:<[0-9A-F ]+>)?\s*(DW_AT_\w+)\s*:/i)
1043             {
1044 1         8 chomp;
1045 1         291 carp('unknown attribute type ', $1, ' found at position ',
1046             $item->{id}, ' : ', $_);
1047             }
1048             }
1049              
1050             # remap Ss:
1051 15         34 foreach $item (values %{$self{item_map}})
  15         1857  
1052             {
1053 11828         11561 foreach (SIGNATURE_ATTRIBUTES)
1054             {
1055 23656 100 100     71477 if (defined $item->{$_} and $item->{$_} =~ m/^S([0-9A-F]+)/i)
1056 144         392 { $item->{$_} = $compilation_unit_list{$1}; }
1057             }
1058             }
1059              
1060             # now we're finished:
1061 15 100       1265 close READELF or
1062             croak 'error while attempting to parse ', $file_name,
1063             ' (maybe not an object file?)';
1064 14 100       32 @{$self{items}} > 0 or
  14         414  
1065             croak 'aborting: debug info section seems empty in ', __PACKAGE__;
1066              
1067 13         519 bless \%self, $class;
1068             }
1069              
1070             #########################################################################
1071              
1072             =head2 item_ids - get object ID(s) of (named) item
1073              
1074             @item_ids = $debug_info->item_ids($identifier);
1075              
1076             =head3 example:
1077              
1078             @item_ids = $debug_info->item_ids('my_variable');
1079              
1080             =head3 parameters:
1081              
1082             $identifier name of item (e.g. variable name)
1083              
1084             =head3 description:
1085              
1086             This method returns the internal item ID of all identifiers with
1087             the given name as array.
1088              
1089             =head3 returns:
1090              
1091             If a name is unique, the method returns an array with exactly one
1092             element, if a name does not exist it returns an empty array and
1093             otherwise an array containing the IDs of all matching itmes is
1094             returned.
1095              
1096             =cut
1097              
1098             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
1099             sub item_ids($$)
1100             {
1101 33     33 1 37048 my $this = shift;
1102 33         98 my ($identifier) = @_;
1103 33         54 local $_;
1104              
1105 33         104 my $id = $this->{name_map}{$identifier};
1106             return
1107 38         213 map { $_->{id} }
  8         21  
1108             (! defined $id ? ()
1109             : ref($id) eq 'HASH' ? ($id)
1110 33 100       154 : @{$id});
    100          
1111             }
1112              
1113             #########################################################################
1114              
1115             =head2 item_ids_matching - get object IDs of items matching constraints
1116              
1117             @item_ids = $debug_info->item_ids_matching($re_name, [$re_type_tag]);
1118              
1119             =head3 example:
1120              
1121             @some_item_ids = $debug_info->item_ids_matching('^var', 'variable');
1122             @all_item_ids = $debug_info->item_ids_matching('');
1123             @all_structure_ids = $debug_info->item_ids_matching('', '.*structure.*');
1124              
1125             =head3 parameters:
1126              
1127             $re_name regular expression matching name of items
1128             $re_type_tag regular expression matching type tag of items
1129              
1130             =head3 description:
1131              
1132             This method returns an array containing the internal item ID of
1133             all identifiers that match both the regular expression for their
1134             name and their type tags. Note that an empty string will match
1135             any name or type tag, even missing ones. Also note that type tags
1136             in Dwarf 2 always begin with C.
1137              
1138             =head3 returns:
1139              
1140             If a name is unique, the method returns an array with exactly one
1141             element, if a name does not exist it returns an empty array and
1142             otherwise an array containing the IDs of all matching itmes is
1143             returned. The IDs are sorted alphabetically according to their
1144             names.
1145              
1146             =cut
1147              
1148             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
1149             sub item_ids_matching($$;$)
1150             {
1151 44     44 1 16597 my $this = shift;
1152 44         102 my ($re_name, $re_type_tag) = (@_, '.');
1153 44 100       148 $re_name = '.' if $re_name eq '';
1154 44         56 local $_;
1155              
1156 44         74 my @ids = ();
1157 44 100       54 foreach (map { ref($_) eq 'HASH' ? $_ : @$_ }
  10791         15554  
  44         1100  
1158             values %{$this->{name_map}})
1159             {
1160 14154 100 100     52779 next if defined $_->{name} and $_->{name} !~ m/$re_name/;
1161 2841 100 66     8734 next if (not defined $_->{name} and
      66        
      100        
1162             $re_name ne '' and
1163             not ($_->{type_tag} =~ m/^DW_TAG_(?:class|structure|union)_type$/
1164             and
1165             defined $_->{specification} and
1166             $this->{item_map}->{$_->{specification}}->{name}
1167             =~ m/$re_name/));
1168 2549 100 66     10339 next if defined $_->{type_tag} and $_->{type_tag} !~ m/$re_type_tag/;
1169 911 50 33     1559 next if not defined $_->{type_tag} and $re_type_tag ne '';
1170 911 100       2814 push @ids, [ $_->{id}, ( defined $_->{name} ? $_->{name} : '' ) ];
1171             }
1172             return
1173 911         1644 map { $_->[0] }
  4110         3402  
1174 44         741 sort { $a->[1] cmp $b->[1] }
1175             @ids;
1176             }
1177              
1178             #########################################################################
1179              
1180             =head2 structure_layout - get structure layout of variable or data type
1181              
1182             @structure_layout =
1183             $debug_info->structure_layout($id, [$initial_offset]);
1184              
1185             =head3 example:
1186              
1187             @structure_layout1 =
1188             $debug_info->structure_layout('1a8');
1189             @structure_layout2 =
1190             $debug_info->structure_layout('2f0', 4);
1191              
1192             =head3 parameters:
1193              
1194             $id internal ID of item
1195             $initial_offset offset to be used for the beginning of the layout
1196              
1197             =head3 description:
1198              
1199             This method returns the structure layout of a variable or data
1200             type with the given item ID (which can be found with the method
1201             L<"item_ids"> or L<"item_ids_matching">). For each element of a
1202             structure it returns a sextuple containing (in that order)
1203             I, I, I, I, I
1204             source file> and I allthough some of the information might
1205             be missing (which is indicated by an empty string). For bit
1206             fields two additional fields are added: I and
1207             I (either both are defined or none at all).
1208              
1209             I is a triplet. The first two elements
1210             (object ID of module and source number) are needed to get the file
1211             name from
1212             L.
1213             The third is the line number within the source. If in Dwarf 4 the
1214             last two elements are not provided, they will be replaced by the
1215             fixed string C and the signature ID of the compilation
1216             unit instead.
1217              
1218             Note that named indices for the result are defined in the
1219             L export (see above).
1220              
1221             =head3 returns:
1222              
1223             The method returns an array of the sextuples described above.
1224              
1225             =cut
1226              
1227             # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
1228             sub structure_layout($$;$)
1229             {
1230 689     689 1 7841 my $this = shift;
1231 689         774 my ($id, $initial_offset) = @_;
1232 689 100       1114 $initial_offset = 0 unless defined $initial_offset;
1233 689         577 local $_;
1234              
1235 689         987 my $item = $this->{item_map}->{$id};
1236             # ignore undefined items or standard items (as standard data types):
1237 689 100 66     2727 return () unless defined $item and defined $item->{decl_file};
1238              
1239             # handle relative level - 1:
1240 407 100       663 if (defined $this->{sl_level})
1241 358         354 { $this->{sl_level}++ }
1242             else
1243             {
1244 49         98 $this->{sl_level} = 0;
1245 49         103 $this->{tag_stack} = [];
1246             }
1247 407         413 my $level = $this->{sl_level};
1248              
1249             # maintain a stack of the item tags:
1250 407         601 $this->{tag_stack}->[$level] = $item->{type_tag};
1251              
1252             # check for nested structures (if applicable) and don't process
1253             # anything if we found one:
1254 407         489 my @result = ();
1255 407 100 100     1626 if ($display_nested_items or
      100        
      100        
1256             $item->{type_tag} ne 'DW_TAG_structure_type' or
1257             $level < 1 or
1258             $item->{type_tag} ne $this->{tag_stack}->[$level - 1])
1259             {
1260             # get name:
1261 400         469 my $name = $item->{name};
1262 400 50 100     855 if (not defined $name and
      66        
      66        
      33        
1263             $level < 1 and
1264             $item->{type_tag} =~ m/^DW_TAG_(?:class|structure|union)_type$/ and
1265             defined $item->{specification} and
1266             defined $this->{item_map}->{$item->{specification}})
1267             {
1268 2         7 $name = $this->{item_map}->{$item->{specification}}->{name};
1269             }
1270 400 100       608 $name = '' unless defined $name;
1271              
1272             # handle offset:
1273 400 100       710 my $offset =
1274             defined $item->{member_location} ? $item->{member_location} : 0;
1275 400         542 $offset += $initial_offset;
1276              
1277             # handle size - 1:
1278 400 100       725 my $size = defined $item->{byte_size} ? $item->{byte_size} : 0;
1279              
1280             # handle bit size and offset:
1281 400         381 my @bit_data = ();
1282 400 100 66     1372 if (defined $item->{bit_size} or defined $item->{bit_offset})
1283             {
1284 77 50       177 $bit_data[0] =
1285             defined $item->{bit_size} ? $item->{bit_size} : 0;
1286 77 50       152 $bit_data[1] =
1287             defined $item->{bit_offset} ? $item->{bit_offset} : 0;
1288             }
1289              
1290             # handle types:
1291 400         461 my $type_name = '';
1292 400         419 my @sub_layout = ();
1293 400 100       758 if (defined $item->{type})
1294             {
1295 329         576 my $type = $this->{item_map}->{$item->{type}};
1296 329         286 my $prefix = '';
1297 329         290 my $postfix = '';
1298             # for special types use shortcut to their sub-types:
1299 329         643 while ($type->{type_tag})
1300             {
1301             # const:
1302 382 100       1470 if ($type->{type_tag} eq 'DW_TAG_const_type')
    100          
    100          
    100          
    100          
1303             {
1304 22 100       80 $prefix .= 'const ' unless $prefix =~ m/const/;
1305 22         56 $type = $this->{item_map}->{$type->{type}};
1306 22         57 next;
1307             }
1308             # volatile:
1309             elsif ($type->{type_tag} eq 'DW_TAG_volatile_type')
1310             {
1311 6 50       24 $prefix .= 'volatile ' unless $prefix =~ m/volatile/;
1312 6         18 $type = $this->{item_map}->{$type->{type}};
1313 6         15 next;
1314             }
1315             # reference:
1316             elsif ($type->{type_tag} eq 'DW_TAG_reference_type')
1317             {
1318 8         14 $postfix .= '&';
1319 8         25 $type = $this->{item_map}->{$type->{type}};
1320 8         21 next;
1321             }
1322             # pointer:
1323             elsif ($type->{type_tag} eq 'DW_TAG_pointer_type')
1324             {
1325 16         25 $postfix .= '*';
1326 16 100 66     77 if (defined $type->{type} and
1327             defined $this->{item_map}->{$type->{type}})
1328             {
1329 4         10 $type = $this->{item_map}->{$type->{type}};
1330 4         13 next;
1331             }
1332             }
1333             # arrays:
1334             elsif ($type->{type_tag} eq 'DW_TAG_array_type')
1335             {
1336 13         17 foreach (0..$#{$type->{sub_items}})
  13         61  
1337             {
1338 13         27 $name .= '[';
1339 13 50       65 $name .= $type->{sub_items}->[$_]->{upper_bound} + 1
1340             if defined $type->{sub_items}->[$_]->{upper_bound};
1341 13         28 $name .= ']';
1342             }
1343 13         35 $type = $this->{item_map}->{$type->{type}};
1344 13         27 next;
1345             }
1346 329         374 last;
1347             }
1348              
1349             # handle size - 2:
1350 329 100 100     1617 $size = $type->{byte_size}
      66        
1351             if ($size == 0 and
1352             defined $type->{byte_size} and
1353             $type->{byte_size} > 0);
1354              
1355             # handle details of types in recursion:
1356 329         701 @sub_layout = $this->structure_layout($item->{type}, $offset);
1357              
1358             # for templates use shortcut to their specification:
1359 329 100 100     1113 if ($type->{type_tag} =~ m/^DW_TAG_(?:class|structure|union)_type$/
1360             and
1361             defined $type->{specification})
1362 6         14 { $type = $this->{item_map}->{$type->{specification}} }
1363              
1364             # set type name:
1365 329 100       664 $type_name = $type->{name} if defined $type->{name};
1366             # TODO: all shold be known in later version:
1367 329 50 33     541 $type_name = ''
      66        
1368             if $type_name eq '' and ($prefix or $postfix);
1369 329 100       488 $type_name = $prefix.$type_name if $prefix;
1370 329 100       488 $type_name .= $postfix if $postfix;
1371              
1372             # apply structure filter, if applicable:
1373 329 100 66     1468 @sub_layout = ()
1374             if defined $re_substructure_filter and
1375             $type_name =~ m/$re_substructure_filter/;
1376              
1377             # handle size - 3:
1378 329   66     828 while ($size == 0 and
      66        
1379             defined $type->{type} and
1380             $type = $this->{item_map}->{$type->{type}})
1381             {
1382 6 50 33     36 $size = $type->{byte_size}
1383             if (defined $type->{byte_size} and
1384             $type->{byte_size} > 0);
1385             }
1386             }
1387              
1388             # handle size - 4:
1389 400   66     1131 while ($name =~ m/\[(\d+)\]/g and $1 > 0)
1390 13         87 { $size *= $1 }
1391              
1392             # for structured items continue recursion (but ignore
1393             # declarations not declaring real members!):
1394 400         365 foreach (@{$item->{sub_items}})
  400         829  
1395             {
1396 309 50       1119 push @sub_layout, $this->structure_layout($_->{id}, $offset)
1397             unless $_->{type_tag} eq 'DW_TAG_typedef';
1398             }
1399              
1400             # sort sub-structure:
1401 400 100       771 if (@sub_layout)
1402             {
1403 889 100 66     2159 @sub_layout =
    100          
    100          
    50          
1404             sort {
1405 117         301 ($a->[$OFFSET] <=> $b->[$OFFSET]
1406             ||
1407             (defined $a->[$BITOFFSET]
1408             ? (defined $b->[$BITOFFSET]
1409             ? $a->[$BITOFFSET] <=> $b->[$BITOFFSET] : 1)
1410             : (defined $b->[$BITOFFSET] ? -1 : 0)
1411             )
1412             ||
1413             $a->[$LEVEL] <=> $b->[$LEVEL]
1414             )
1415             }
1416             @sub_layout;
1417             }
1418              
1419             # handle location of definition:
1420 400         523 my $location = [];
1421 400 50 33     2140 if (defined $item->{compilation_unit} and
      33        
1422             defined $item->{decl_file} and
1423             defined $item->{decl_line})
1424             {
1425 400         1083 $location = [$item->{compilation_unit},
1426             $item->{decl_file},
1427             $item->{decl_line} ];
1428             }
1429              
1430             # for unnamed singular substructures eliminate singular level:
1431 400 100 100     1512 if ($item->{type_tag} =~ m/^DW_TAG_(?:class|structure|union)_type$/ and
      66        
      66        
1432             not $name and
1433             not $type_name and
1434             0 == @bit_data)
1435             {
1436 7         23 @result = @sub_layout;
1437             }
1438             else
1439             {
1440 393         1356 @result = ([$level, $name, $type_name, $size, $location,
1441             $offset, @bit_data],
1442             @sub_layout);
1443             }
1444             }
1445              
1446             # handle relative level - 2:
1447 407 100       679 if ($this->{sl_level} > 0)
1448 358         402 { $this->{sl_level}-- }
1449             else
1450             {
1451 49         123 delete $this->{tag_stack};
1452 49         93 delete $this->{sl_level};
1453             }
1454              
1455             # put everything together and return:
1456 407         1199 return @result;
1457             }
1458              
1459             1;
1460              
1461             #########################################################################
1462              
1463             __END__