CU will now parse all its DIEs (lazily, when any specific DIE is requested)
diff --git a/elftools/dwarf/compileunit.py b/elftools/dwarf/compileunit.py
index ec04f7d..daee885 100644
--- a/elftools/dwarf/compileunit.py
+++ b/elftools/dwarf/compileunit.py
@@ -27,7 +27,7 @@
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):
+ def __init__(self, header, dwarfinfo, structs, cu_offset, cu_die_offset):
""" header:
CU header for this compile unit
@@ -37,18 +37,25 @@
structs:
A DWARFStructs instance suitable for this compile unit
+ cu_offset:
+ Offset in the stream to the beginning of this CU (its header)
+
cu_die_offset:
Offset in the stream of the top DIE of this CU
"""
self.dwarfinfo = dwarfinfo
self.header = header
self.structs = structs
+ self.cu_offset = cu_offset
self.cu_die_offset = cu_die_offset
# The abbreviation table for this CU. Filled lazily when DIEs are
# requested.
self._abbrev_table = None
+ # A list of DIEs belonging to this CU. Lazily parsed.
+ self._dielist = []
+
def get_abbrev_table(self):
""" Get the abbreviation table (AbbrevTable object) for this CU
"""
@@ -61,14 +68,30 @@
""" Get the top DIE (which is either a DW_TAG_compile_unit or
DW_TAG_partial_unit) of this CU
"""
- return DIE(
- cu=self,
- stream=self.dwarfinfo.stream,
- offset=self.cu_die_offset)
+ return self._get_DIE(0)
def __getitem__(self, name):
""" Implement dict-like access to header entries
"""
return self.header[name]
-
\ No newline at end of file
+ def _get_DIE(self, index):
+ """ Get the DIE at the given index
+ """
+ if len(self._dielist) == 0:
+ self._parse_DIEs()
+ return self._dielist[index]
+
+ def _parse_DIEs(self):
+ # Compute the boundary (one byte past the bounds) of this CU in the
+ # stream
+ cu_boundary = ( self.cu_offset +
+ self['unit_length'] +
+ self.structs.initial_length_field_size())
+
+ die_offset = self.cu_die_offset
+ while die_offset < cu_boundary:
+ die = DIE(cu=self, stream=self.dwarfinfo.stream, offset=die_offset)
+ self._dielist.append(die)
+ die_offset += die.size
+
diff --git a/elftools/dwarf/die.py b/elftools/dwarf/die.py
index 26e9dba..b92c31a 100644
--- a/elftools/dwarf/die.py
+++ b/elftools/dwarf/die.py
@@ -44,6 +44,9 @@
size:
The size this DIE occupies in the section
+ offset:
+ The offset of this DIE in the stream
+
attributes:
An ordered dictionary mapping attribute names to values. It's
ordered to enable both efficient name->value mapping and
diff --git a/elftools/dwarf/dwarfinfo.py b/elftools/dwarf/dwarfinfo.py
index 7a4bbc0..051ea9f 100644
--- a/elftools/dwarf/dwarfinfo.py
+++ b/elftools/dwarf/dwarfinfo.py
@@ -174,13 +174,14 @@
header=cu_header,
dwarfinfo=self,
structs=cu_structs,
+ cu_offset=offset,
cu_die_offset=cu_die_offset))
# Compute the offset of the next CU in the section. The unit_length
# field of the CU header contains its size not including the length
# field itself.
offset = ( offset +
cu_header['unit_length'] +
- cu_structs.initial_lenght_field_size())
+ cu_structs.initial_length_field_size())
return CUlist
def _is_supported_version(self, version):
diff --git a/elftools/dwarf/structs.py b/elftools/dwarf/structs.py
index 0f3094c..a2c0da3 100644
--- a/elftools/dwarf/structs.py
+++ b/elftools/dwarf/structs.py
@@ -72,7 +72,7 @@
self.address_size = address_size
self._create_structs()
- def initial_lenght_field_size(self):
+ def initial_length_field_size(self):
""" Size of an initial length field.
"""
return 4 if self.dwarf_format == 32 else 12
diff --git a/z.py b/z.py
index 5e5e775..c8cdbce 100644
--- a/z.py
+++ b/z.py
@@ -10,7 +10,7 @@
# read a little-endian, 64-bit file
es = ELFStructs(True, 64)
-stream = open('tests/testfiles/z.elf', 'rb')
+stream = open('tests/testfiles/exe_simple64.elf', 'rb')
#stream = open('binfiles/z32.elf', 'rb')
efile = ELFFile(stream)
@@ -22,13 +22,20 @@
dwarfinfo = efile.get_dwarf_info()
tt = dwarfinfo.structs.Dwarf_dw_form['DW_FORM_block1'].parse('\x03\x12\x34\x46')
-cu = dwarfinfo.get_CU(0)
+cu = dwarfinfo.get_CU(1)
print 'CU header', cu.header
topdie = cu.get_top_DIE()
-print topdie.size, topdie.tag
-for attrname, val in topdie.attributes.iteritems():
- print attrname, val
+for die in cu._dielist:
+ print 'DIE %s, size=%s' % (die.tag, die.size)
+ for attrname, val in die.attributes.iteritems():
+ print ' ', attrname, val
+
+#~ topdie = cu.get_top_DIE()
+
+#~ print topdie.size, topdie.tag
+
+#~ print len(cu._dielist)
#~ print dwarfinfo.structs.Dwarf_abbrev_entry.parse('\x13\x01\x01\x03\x50\x04\x00\x00')