class CompileUnit(object):
+ """ A DWARF compilation unit (CU).
+
+ A normal compilation unit typically represents the text and data
+ contributed to an executable by a single relocatable object file.
+ It may be derived from several source files,
+ including pre-processed "include files"
+
+ Serves as a container and context to DIEs that describe objects and code
+ belonging to a compilation unit.
+
+ CU header entries can be accessed as dict keys from this object, i.e.
+ cu = CompileUnit(...)
+ cu['version'] # version field of the CU header
+
+ To get the top-level DIE describing the compilation unit, call the
+ get_top_DIE method.
+ """
def __init__(self, header, dwarfinfo, structs, cu_die_offset):
""" header:
CU header for this compile unit
# Raw value as parsed from the section - used for debugging and presentation
# (e.g. for a DW_FORM_strp it's the raw string offset into the table)
#
-AttributeValue = namedtuple('AttributeValue', 'form value raw_value')
+# offset:
+# Offset of this attribute's value in the stream
+#
+AttributeValue = namedtuple(
+ 'AttributeValue', 'form value raw_value offset')
class DIE(object):
"""
return self.tag is None
+ #------ PRIVATE ------#
+
def _parse_DIE(self):
""" Parses the DIE info from the section, based on the abbreviation
table of the CU
# values from the stream.
#
for name, form in abbrev_decl.iter_attr_specs():
- print '**', self.stream.tell()
+ attr_offset = self.stream.tell()
raw_value = struct_parse(structs.Dwarf_dw_form[form], self.stream)
value = self._translate_attr_value(form, raw_value)
- self.attributes[name] = AttributeValue(form, value, raw_value)
+ self.attributes[name] = AttributeValue(
+ form=form,
+ value=value,
+ raw_value=raw_value,
+ offset=attr_offset)
self.size = self.stream.tell() - self.offset
self.little_endian = little_endian
# This is the DWARFStructs the context uses, so it doesn't depend on
- # DWARF format and address_size (these are determined per CU) - so we
- # set them to default values.
+ # DWARF format and address_size (these are determined per CU) - set them
+ # to default values.
self.structs = DWARFStructs(
little_endian=self.little_endian,
dwarf_format=32,
address_size=4)
- # Populate the list with CUs found in debug_info
+ # Populate the list with CUs found in debug_info. For each CU only its
+ # header is parsed immediately (the abbrev table isn't loaded before
+ # it's being referenced by one of the CU's DIEs).
+ # Since there usually aren't many CUs in a single object, this
+ # shouldn't present a performance problem.
+ #
self._CU = self._parse_CUs()
# Cache for abbrev tables: a dict keyed by offset
self.stream,
stream_pos=self.debug_str_loc.offset + offset)
+ #------ PRIVATE ------#
+
def _parse_CUs(self):
""" Parse CU entries from debug_info.
"""
cu_structs = DWARFStructs(
little_endian=self.little_endian,
dwarf_format=dwarf_format,
- address_size=8)
+ address_size=8)
cu_die_offset = self.stream.tell()
dwarf_assert(
dwarfinfo = efile.get_dwarf_info()
tt = dwarfinfo.structs.Dwarf_dw_form['DW_FORM_block1'].parse('\x03\x12\x34\x46')
-cu = dwarfinfo.get_CU(1)
+cu = dwarfinfo.get_CU(0)
print 'CU header', cu.header
topdie = cu.get_top_DIE()
print topdie.size, topdie.tag
-print topdie.attributes
+for attrname, val in topdie.attributes.iteritems():
+ print attrname, val
#~ print dwarfinfo.structs.Dwarf_abbrev_entry.parse('\x13\x01\x01\x03\x50\x04\x00\x00')