From: eliben Date: Tue, 20 Sep 2011 07:20:32 +0000 (+0300) Subject: * DWARFInfo now doesn't receive a "dwarf class" argument, since it must infer it... X-Git-Tag: v0.10~105 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ce5ec71a8995cef723e1460e5bd2014d664828a8;p=pyelftools.git * DWARFInfo now doesn't receive a "dwarf class" argument, since it must infer it on its own from the info section * Parsing of CU headers was fixed and now appears to be working --- diff --git a/elftools/dwarf/compileunit.py b/elftools/dwarf/compileunit.py index 5e133b0..a22b761 100644 --- a/elftools/dwarf/compileunit.py +++ b/elftools/dwarf/compileunit.py @@ -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] + + + + diff --git a/elftools/dwarf/dwarfinfo.py b/elftools/dwarf/dwarfinfo.py index 5216bac..af9c7ad 100644 --- a/elftools/dwarf/dwarfinfo.py +++ b/elftools/dwarf/dwarfinfo.py @@ -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 - - - diff --git a/elftools/dwarf/structs.py b/elftools/dwarf/structs.py index 104cee9..7001b7a 100644 --- a/elftools/dwarf/structs.py +++ b/elftools/dwarf/structs.py @@ -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() diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index b1c2d81..872d2d5 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -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 6fc8ff6..b16ef69 100644 --- 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 44e6dbf..54af0f7 100644 --- a/zd.py +++ b/zd.py @@ -6,8 +6,7 @@ from elftools.dwarf.structs import DWARFStructs from elftools.dwarf.dwarfinfo import DWARFInfo -ds = DWARFStructs( - little_endian=True, +ds = DWARFStructs(little_endian=True, dwarfclass=32) print ds.Dwarf_xword('x').parse('\x04\x01\x00\x00')