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
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)
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
+import copy
+
from ..common.utils import struct_parse
from .constants import *
self.epilogue_begin = False
self.isa = 0
+ def __repr__(self):
+ a = ['<LineState %x:' % id(self)]
+ a.append(' address = 0x%x' % self.address)
+ for attr in ('file', 'line', 'column', 'is_stmt', 'basic_block',
+ 'end_sequence', 'prologue_end', 'epilogue_begin', 'isa'):
+ a.append(' %s = %s' % (attr, getattr(self, attr)))
+ return '\n'.join(a) + '>\n'
class LineProgram(object):
""" Builds a "line table", which is essentially the matrix described
# 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
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)
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
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