From 2e85c84982c85630d16ea351d4b570f5b8d612b0 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sat, 3 Dec 2011 16:33:54 +0200 Subject: [PATCH] after cleanup and fixing, it actually shows signs of life --- elftools/dwarf/dwarfinfo.py | 10 +++---- elftools/dwarf/lineprogram.py | 53 ++++++++++++++++++++++++----------- z.py | 6 ++++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/elftools/dwarf/dwarfinfo.py b/elftools/dwarf/dwarfinfo.py index 8ebb47d..bb073e0 100644 --- a/elftools/dwarf/dwarfinfo.py +++ b/elftools/dwarf/dwarfinfo.py @@ -114,7 +114,7 @@ class DWARFInfo(object): top_DIE = CU.get_top_DIE() if 'DW_AT_stmt_list' in top_DIE.attributes: return self._parse_line_program_at_offset( - top_DIE.attributes['DW_AT_stmt_list'], CU.structs) + top_DIE.attributes['DW_AT_stmt_list'].value, CU.structs) else: return None @@ -188,16 +188,16 @@ class DWARFInfo(object): lineprog_header = struct_parse( structs.Dwarf_lineprog_header, self.debug_line_sec.stream, - offset) + debug_line_offset) # Calculate the offset to the next line program (see DWARF 6.2.4) - end_offset = ( offset + lineprog_header['unit_length'] + - lineprog_structs.initial_length_field_size()) + end_offset = ( debug_line_offset + lineprog_header['unit_length'] + + structs.initial_length_field_size()) return LineProgram( header=lineprog_header, dwarfinfo=self, - structs=lineprog_structs, + structs=structs, program_start_offset=self.debug_line_sec.stream.tell(), program_end_offset=end_offset) diff --git a/elftools/dwarf/lineprogram.py b/elftools/dwarf/lineprogram.py index 43d8f90..11cd57f 100644 --- a/elftools/dwarf/lineprogram.py +++ b/elftools/dwarf/lineprogram.py @@ -6,6 +6,8 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- +import copy + from ..common.utils import struct_parse from .constants import * @@ -28,6 +30,13 @@ class LineState(object): self.epilogue_begin = False self.isa = 0 + def __repr__(self): + a = ['\n' class LineProgram(object): """ Builds a "line table", which is essentially the matrix described @@ -85,7 +94,7 @@ class LineProgram(object): # Used by instructions that have to add the current state to the # line table. After adding, some state registers have to be # cleared. - linetable.append(state) + linetable.append(copy.copy(state)) state.basic_block = False state.prologue_end = False state.epilogue_begin = False @@ -93,7 +102,7 @@ class LineProgram(object): offset = self.program_start_offset while offset < self.program_end_offset: opcode = struct_parse( - self.structs.Dwarf_uint8, + self.structs.Dwarf_uint8(''), self.stream, offset) @@ -107,42 +116,50 @@ class LineProgram(object): adjusted_opcode = opcode - self['opcode_base'] state.address += ((adjusted_opcode / self['line_range']) * self['minimum_instruction_length']) - self.line += (self['line_base'] + + state.line += (self['line_base'] + adjusted_opcode % self['line_range']) add_state_to_table() elif opcode == 0: # Extended opcode: start with a zero byte, followed by # instruction size and the instruction itself. - inst_len = struct_parse(self.Dwarf_uleb128, self.stream) - ex_opcode = struct_parse(self.Dwarf_uint8, self.stream) + inst_len = struct_parse(self.structs.Dwarf_uleb128(''), + self.stream) + ex_opcode = struct_parse(self.structs.Dwarf_uint8(''), + self.stream) if ex_opcode == DW_LNE_end_sequence: state.end_sequence = True - add_state_to_table(state) - state = LineState() # reset state + add_state_to_table() + # reset state + state = LineState(self.header['default_is_stmt']) elif ex_opcode == DW_LNE_set_address: - operand = struct_parse(self.Dwarf_target_addr, self.stream) + operand = struct_parse(self.structs.Dwarf_target_addr(''), + self.stream) state.address = operand elif ex_opcode == DW_LNE_define_file: - operand = struct_parse(self.Dwarf_lineprog_file_entry, - self.stream) + operand = struct_parse( + self.structs.Dwarf_lineprog_file_entry, self.stream) self['file_entry'].append(operand) else: # 0 < opcode < opcode_base # Standard opcode if opcode == DW_LNS_copy: add_state_to_table() elif opcode == DW_LNS_advance_pc: - operand = struct_parse(self.Dwarf_uleb128, self.stream) + operand = struct_parse(self.structs.Dwarf_uleb128(''), + self.stream) state.address += ( operand * self.header['minimum_instruction_length']) elif opcode == DW_LNS_advance_line: - operand = struct_parse(self.Dwarf_sleb128, self.stream) + operand = struct_parse(self.structs.Dwarf_sleb128(''), + self.stream) state.line += operand elif opcode == DW_LNS_set_file: - operand = struct_parse(self.Dwarf_sleb128, self.stream) + operand = struct_parse(self.structs.Dwarf_sleb128(''), + self.stream) state.file = operand elif opcode == DW_LNS_set_column: - operand = struct_parse(self.Dwarf_uleb128, self.stream) + operand = struct_parse(self.structs.Dwarf_uleb128(''), + self.stream) state.column = operand elif opcode == DW_LNS_negate_stmt: state.is_stmt = not state.is_stmt @@ -153,16 +170,20 @@ class LineProgram(object): state.address += ((adjusted_opcode / self['line_range']) * self['minimum_instruction_length']) elif opcode == DW_LNS_fixed_advance_pc: - operand = struct_parse(self.Dwarf_uint16, self.stream) + operand = struct_parse(self.structs.Dwarf_uint16, + self.stream) state.address += operand elif opcode == DW_LNS_set_prologue_end: state.prologue_end = True elif opcode == DW_LNS_set_epilogue_begin: state.epilogue_begin = True elif opcode == DW_LNS_set_isa: - operand = struct_parse(self.Dwarf_uleb128, self.stream) + operand = struct_parse(self.structs.Dwarf_uleb128(''), + self.stream) state.isa = operand else: dwarf_assert(False, 'Invalid standard line program opcode: %s' % ( opcode,)) + offset = self.stream.tell() + return linetable diff --git a/z.py b/z.py index f603948..fed0ab7 100644 --- a/z.py +++ b/z.py @@ -22,7 +22,13 @@ print '===> %s sections!' % efile.num_sections() #~ print efile.has_dwarf_info() dwarfinfo = efile.get_dwarf_info() +CUs = list(dwarfinfo.iter_CUs()) +print 'num CUs:', len(CUs) +print 'first CU:', CUs[0] +lp = dwarfinfo.line_program_for_CU(CUs[0]) +print 'lp:', lp, lp.header +print 'linetable:', lp.get_line_table() #for lp in dwarfinfo.iter_line_programs(): #print lp #print lp.header -- 2.30.2