CU will now parse all its DIEs (lazily, when any specific DIE is requested)
authoreliben <devnull@localhost>
Mon, 26 Sep 2011 08:17:03 +0000 (11:17 +0300)
committereliben <devnull@localhost>
Mon, 26 Sep 2011 08:17:03 +0000 (11:17 +0300)
elftools/dwarf/compileunit.py
elftools/dwarf/die.py
elftools/dwarf/dwarfinfo.py
elftools/dwarf/structs.py
z.py

index ec04f7de941c67e5ace7c8b9d87770b8221b2df4..daee885faba4e7e4e933909891dcc1ac3a0c7837 100644 (file)
@@ -27,7 +27,7 @@ class CompileUnit(object):
         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 @@ class CompileUnit(object):
             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 @@ class CompileUnit(object):
         """ 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
+
index 26e9dbaf986f05fded44b9aae8a8406958d6c8bb..b92c31a79441cc515c23af7664d8f1a44757deb7 100644 (file)
@@ -44,6 +44,9 @@ class DIE(object):
             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
index 7a4bbc03b324b613ce3df5a02d22fb513a2bb306..051ea9f59d8e96f75d7d5995571733a08136bf47 100644 (file)
@@ -174,13 +174,14 @@ class DWARFInfo(object):
                 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):
index 0f3094c302699c319545467b2320654ee43b0a23..a2c0da34f47ac272658ee9b3fd9861854f1b8b04 100644 (file)
@@ -72,7 +72,7 @@ class DWARFStructs(object):
         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 5e5e775ce209b57c0efcc79c2a2277f835ce9ab7..c8cdbce377759b52fb423e88c271bae5b596d04c 100644 (file)
--- a/z.py
+++ b/z.py
@@ -10,7 +10,7 @@ from elftools.elf.sections import *
 # 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 @@ print efile.has_dwarf_info()
 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')