* DWARFInfo now doesn't receive a "dwarf class" argument, since it must infer it...
authoreliben <devnull@localhost>
Tue, 20 Sep 2011 07:20:32 +0000 (10:20 +0300)
committereliben <devnull@localhost>
Tue, 20 Sep 2011 07:20:32 +0000 (10:20 +0300)
* Parsing of CU headers was fixed and now appears to be working

elftools/dwarf/compileunit.py
elftools/dwarf/dwarfinfo.py
elftools/dwarf/structs.py
elftools/elf/elffile.py
z.py
zd.py

index 5e133b0a507a526ca40fb04262a25e363ae390c1..a22b761ab25c368a3cc2c4da0ecbca3a3f4d444c 100644 (file)
@@ -9,12 +9,28 @@
 
 
 class CompileUnit(object):
-    def __init__(self, header, format_bits, cu_die):
+    def __init__(self, dwarfinfo, header, structs):
+        """ Arguments:
+            
+            dwarfinfo:
+                The DWARFInfo context object which created this one
+            
+            header:
+                CU header for this compile unit
+            
+            structs:
+                A DWARFStructs instance suitable for this compile unit
+        """
+        self.dwarfinfo = dwarfinfo
         self.header = header
-        self.format_bits = format_bits
+        self.structs = structs
         self.cu_die = cu_die
     
     def __getitem__(self, name):
         """ Implement dict-like access to header entries
         """
         return self.header[name]
+
+
+
+
index 5216bac2c4327feddaa1a1f847ea8467656ffd18..af9c7add031f001c2f5730e7e6435dfaf36d0e7c 100644 (file)
@@ -23,13 +23,11 @@ class DWARFInfo(object):
     """ Creation: the constructor accepts a stream (file-like object) that
         contains debug sections, along with locators (DebugSectionLocator)
         of the required sections. In addition, little_endian is a boolean
-        parameter specifying endianity, and dwarfclass is 32 or 64, depending
-        on the type of file the DWARF info was read from.
+        parameter specifying endianity.
     """
     def __init__(self, 
             stream,
             little_endian,
-            dwarfclass,
             debug_info_loc,
             debug_abbrev_loc,
             debug_str_loc,
@@ -41,40 +39,49 @@ class DWARFInfo(object):
         self.debug_line_loc = debug_line_loc
         
         self.little_endian = little_endian
-        self.dwarfclass = dwarfclass
+        self.dwarf_format = 32
         self.structs = DWARFStructs(
             little_endian=self.little_endian,
-            dwarfclass=self.dwarfclass)
+            dwarf_format=self.dwarf_format)
         
+        # Populate the list with CUs found in debug_info
         self._CU = self._parse_CUs()
     
-    def initial_lenght_field_size(self):
-        """ Size of an initial length field.
-        """
-        return 4 if self.dwarfclass == 32 else 12
-
     def _parse_CUs(self):
-        """ Parse CU entries from debug_info and return them as a list of
-            containers.
+        """ Parse CU entries from debug_info.
         """
         offset = self.debug_info_loc.offset
-        print 'loc', self.debug_info_loc
         section_boundary = self.debug_info_loc.offset + self.debug_info_loc.size
         CUlist = []
         while offset < section_boundary:
+            # Section 7.4 (32-bit and 64-bit DWARF Formats) of the DWARF spec v3
+            # states that the first 32-bit word of the CU header determines 
+            # whether the CU is represented with 32-bit or 64-bit DWARF format.
+            # 
+            # So we peek at the first byte in the CU header to determine its
+            # dwarf format. Based on it, we then create a new DWARFStructs
+            # instance suitable for this CU and use it to parse the rest.
+            #
+            initial_length = struct_parse(
+                self.structs.Dwarf_uint32(''), self.stream, offset)
+            if initial_length == 0xFFFFFFFF:
+                self.dwarf_format = 64
+            cu_structs = DWARFStructs(
+                little_endian=self.little_endian,
+                dwarf_format=self.dwarf_format)
+            
             cu_header = struct_parse(
                 self.structs.Dwarf_CU_header, self.stream, offset)
-            print offset, cu_header
             dwarf_assert(
                 self._is_supported_version(cu_header['version']),
                 "Expected supported DWARF version. Got '%s'" % cu_header['version'])
-            CUlist.append(CompileUnit(cu_header, None))
+            CUlist.append(CompileUnit(cu_header, cu_structs, None))
             # 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'] + 
-                        self.initial_lenght_field_size())
+                        cu_structs.initial_lenght_field_size())
         return CUlist
         
     def _is_supported_version(self, version):
@@ -82,6 +89,3 @@ class DWARFInfo(object):
         """
         return 2 <= version <= 3
 
-
-
-
index 104cee96a7dc23bae247684a2c7f5f9c7c86a117..7001b7a7de81676a29f8ba3f80226e6ef0a1e6fc 100644 (file)
@@ -15,15 +15,17 @@ from ..construct import (
 
 
 class DWARFStructs(object):
-    """ Accessible attributes (mostly described by in chapter 7 of the DWARF
+    """ Exposes Construct structs suitable for parsing information from DWARF 
+        sections. Configurable with endianity and format (32 or 64-bit)
+    
+        Accessible attributes (mostly described by in chapter 7 of the DWARF
         spec v3):
     
             Dwarf_uint{8,16,32,64):
                 Data chunks of the common sizes
             
-            Dwarf_xword, Dwarf_offset:
-                32-bit or 64-bit word, depending on dwarfclass (xword and offset
-                are synonyms here).
+            Dwarf_offset:
+                32-bit or 64-bit word, depending on dwarf_format
             
             Dwarf_initial_length:
                 "Initial length field" encoding
@@ -34,27 +36,33 @@ class DWARFStructs(object):
             
             Dwarf_CU_header:
                 Compilation unit header
+        
+        See also the documentation of public methods.
     """
-    def __init__(self, little_endian=True, dwarfclass=32):
-        assert dwarfclass == 32 or dwarfclass == 64
+    def __init__(self, little_endian=True, dwarf_format=32):
+        assert dwarf_format == 32 or dwarf_format == 64
         self.little_endian = little_endian
-        self.dwarfclass = dwarfclass        
+        self.dwarf_format = dwarf_format        
         self._create_structs()
 
+    def initial_lenght_field_size(self):
+        """ Size of an initial length field.
+        """
+        return 4 if self.dwarf_format == 32 else 12
+
     def _create_structs(self):
         if self.little_endian:
             self.Dwarf_uint8 = ULInt8
             self.Dwarf_uint16 = ULInt16
             self.Dwarf_uint32 = ULInt32
             self.Dwarf_uint64 = ULInt64
-            self.Dwarf_xword = ULInt32 if self.dwarfclass == 32 else ULInt64
+            self.Dwarf_offset = ULInt32 if self.dwarf_format == 32 else ULInt64
         else:
             self.Dwarf_uint8 = UBInt8
             self.Dwarf_uint16 = UBInt16
             self.Dwarf_uint32 = UBInt32
             self.Dwarf_uint64 = UBInt64
-            self.Dwarf_xword = UBInt32 if self.dwarfclass == 32 else UBInt64
-        self.Dwarf_offset = self.Dwarf_xword
+            self.Dwarf_offest = UBInt32 if self.dwarf_format == 32 else UBInt64
 
         self._create_initial_length()
         self._create_leb128()
index b1c2d81e7aaed9c4e65258a14cdd0f551ea74e6f..872d2d516409ad79eed9801463ffb8f4c7fe65b4 100644 (file)
@@ -125,7 +125,6 @@ class ELFFile(object):
         return DWARFInfo(
                 stream=self.stream,
                 little_endian=self.little_endian,
-                dwarfclass=self.elfclass,
                 debug_info_loc=debug_sections['.debug_info'],
                 debug_abbrev_loc=debug_sections['.debug_abbrev'],
                 debug_str_loc=debug_sections['.debug_str'],
diff --git a/z.py b/z.py
index 6fc8ff6d739a1ad3c3db6d82bd98389f93b27868..b16ef690e7232b9723a2a95fc88515b5b2bc1eec 100644 (file)
--- a/z.py
+++ b/z.py
@@ -19,7 +19,10 @@ print '===> %s sections!' % efile.num_sections()
 
 print efile.has_dwarf_info()
 
-print efile.get_dwarf_info()
+dwarfinfo = efile.get_dwarf_info()
+print dwarfinfo
+for cu in dwarfinfo._CU:
+    print cu, cu.header
 
 
 #~ print efile.get_section_by_name('.debug_info').name
diff --git a/zd.py b/zd.py
index 44e6dbfadc80c272f6b14af78df6ab46b08c855b..54af0f79d4cd36af3c2fbe58ec53a3cc57ffb110 100644 (file)
--- a/zd.py
+++ b/zd.py
@@ -6,8 +6,7 @@ from elftools.dwarf.structs import DWARFStructs
 from elftools.dwarf.dwarfinfo import DWARFInfo\r
 \r
 \r
-ds = DWARFStructs(\r
-    little_endian=True,\r
+ds = DWARFStructs(little_endian=True,\r
     dwarfclass=32)\r
 \r
 print ds.Dwarf_xword('x').parse('\x04\x01\x00\x00')\r