From 7f13df2b3717777ee9f92bb63dc1b193af628204 Mon Sep 17 00:00:00 2001 From: eliben Date: Mon, 26 Sep 2011 11:17:03 +0300 Subject: [PATCH] CU will now parse all its DIEs (lazily, when any specific DIE is requested) --- elftools/dwarf/compileunit.py | 35 +++++++++++++++++++++++++++++------ elftools/dwarf/die.py | 3 +++ elftools/dwarf/dwarfinfo.py | 3 ++- elftools/dwarf/structs.py | 2 +- z.py | 17 ++++++++++++----- 5 files changed, 47 insertions(+), 13 deletions(-) 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 @@ 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 + 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 @@ 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 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 @@ 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): 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 @@ 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 5e5e775..c8cdbce 100644 --- 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') -- 2.30.2