@@ -139,7 +139,7 @@ def __init__(self,
139
139
self ._cu_cache = []
140
140
self ._cu_offsets_map = []
141
141
142
- # DWARF v4 type units by sig8 - OrderedDict created on Reference
142
+ # DWARF v4 type units by sig8 - OrderedDict created when needed
143
143
self ._type_units_by_sig = None
144
144
145
145
@property
@@ -179,6 +179,32 @@ def get_DIE_from_refaddr(self, refaddr, cu=None):
179
179
if cu is None :
180
180
cu = self .get_CU_containing (refaddr )
181
181
return cu .get_DIE_from_refaddr (refaddr )
182
+
183
+ def get_DIE_by_sig8 (self , sig8 ):
184
+ """ Find and return a DIE referenced by its type signature.
185
+ sig8:
186
+ The 8 byte signature (as a 64-bit unsigned integer)
187
+ Returns the DIE with the given type signature by searching
188
+ for the Type Unit with the matching signature then finding
189
+ the DIE at the offset given by the type_die field in the
190
+ Type Unit header.
191
+ Signatures are an 64-bit unsigned integers computed by the
192
+ DWARF producer as specified in the DWARF standard. Each
193
+ Type Unit contains one signature and the offset to the
194
+ corresponding DW_AT_type DIE in its unit header.
195
+ Describing a type can generate several DIEs. By moving
196
+ a DIE and its related DIEs to a Type Unit and generating
197
+ a hash of the DIEs and attributes in a flattened form
198
+ multiple Compile Units in a linked object can reference
199
+ the same DIE in the overall DWARF structure.
200
+ In DWARF v4 type units are identified by their appearance in the
201
+ .debug_types section.
202
+ """
203
+ self ._parse_debug_types ()
204
+ tu = self ._type_units_by_sig .get (sig8 )
205
+ if tu is None :
206
+ raise KeyError ("Signature %016x not found in .debug_types" % sig8 )
207
+ return tu ._get_cached_DIE (tu .tu_offset + tu ['type_offset' ])
182
208
183
209
def get_CU_containing (self , refaddr ):
184
210
""" Find the CU that includes the given reference address in the
@@ -478,8 +504,8 @@ def _parse_TUs_iter(self, offset=0):
478
504
479
505
def _parse_debug_types (self ):
480
506
""" Check if the .debug_types section is previously parsed. If not,
481
- parse all TUs and store them in an OrderedDict using their unique
482
- 64-bit signature as the key.
507
+ parse all TUs and store them in an OrderedDict using their unique
508
+ 64-bit signature as the key.
483
509
484
510
See .get_TU_by_sig8().
485
511
"""
@@ -490,9 +516,16 @@ def _parse_debug_types(self):
490
516
if self .debug_types_sec is None :
491
517
return
492
518
493
- # Collect all Type Units in the .debug_types section for access using
494
- # their 8-byte unique signature
495
- for tu in self ._parse_TUs_iter ():
519
+ # Parse all the Type Units in the types section for access by sig8
520
+ offset = 0
521
+ while offset < self .debug_types_sec .size :
522
+ tu = self ._parse_TU_at_offset (offset )
523
+ # Compute the offset of the next TU in the section. The unit_length
524
+ # field of the TU header contains its size not including the length
525
+ # field itself.
526
+ offset = (offset +
527
+ tu ['unit_length' ] +
528
+ tu .structs .initial_length_field_size ())
496
529
self ._type_units_by_sig [tu ['signature' ]] = tu
497
530
498
531
def _cached_CU_at_offset (self , offset ):
@@ -583,7 +616,8 @@ def _parse_TU_at_offset(self, offset):
583
616
dwarf_format = 64 if initial_length == 0xFFFFFFFF else 32
584
617
585
618
# Temporary structs for parsing the header
586
- # The structs for the rest of the TUs depend on the header data.
619
+ # The structs for the rest of the TU depend on the header data.
620
+ #
587
621
tu_structs = DWARFStructs (
588
622
little_endian = self .config .little_endian ,
589
623
dwarf_format = dwarf_format ,
0 commit comments