class CIE(object):
""" CIE - Common Information Entry.
Contains a header and a list of instructions (CallFrameInstruction).
+ offset: the offset of this entry from the beginning of the section
"""
- def __init__(self, header, instructions):
+ def __init__(self, header, instructions, offset):
self.header = header
self.instructions = instructions
+ self.offset = offset
def __getitem__(self, name):
""" Implement dict-like access to header entries
""" FDE - Frame Description Entry.
Contains a header, a list of instructions (CallFrameInstruction) and a
reference to the CIE object associated with this FDE.
+ offset: the offset of this entry from the beginning of the section
"""
- def __init__(self, header, instructions, cie):
+ def __init__(self, header, instructions, offset, cie):
self.header = header
self.instructions = instructions
+ self.offset = offset
self.cie = cie
def __getitem__(self, name):
if is_CIE:
self._entry_cache[offset] = CIE(
- header=header, instructions=instructions)
+ header=header, instructions=instructions, offset=offset)
else: # FDE
with preserve_stream_pos(self.stream):
cie = self._parse_entry_at(header['CIE_pointer'])
self._entry_cache[offset] = FDE(
- header=header, instructions=instructions, cie=cie)
+ header=header, instructions=instructions, offset=offset,
+ cie=cie)
return self._entry_cache[offset]
def _parse_instructions(self, structs, offset, end_offset):
\r
# Call frame instructions\r
#\r
+# Note that the first 3 instructions have the so-called "primary opcode"\r
+# (as described in DWARFv3 7.23), so only their highest 2 bits take part\r
+# in the opcode decoding. They are kept as constants with the low bits masked\r
+# out, and the callframe module knows how to handle this.\r
+# The other instructions use an "extended opcode" encoded just in the low 6\r
+# bits, with the high 2 bits, so these constants are exactly as they would\r
+# appear in an actual file.\r
+#\r
DW_CFA_advance_loc = 0b01000000\r
DW_CFA_offset = 0b10000000\r
DW_CFA_restore = 0b11000000\r
return str(val_description) + '\t' + extra_info
+def describe_CFI_instruction(instruction, entry, context):
+ # ZZZ: just get a list of instructions and keep the context internally!!
+ """ Given a CFI instruction, return its textual description. Also needs the
+ entry that contains this instruction.
+ context is a
+ """
+ return ''
+
+
def describe_reg_name(regnum, machine_arch):
""" Provide a textual description for a register name, given its serial
number. The number is expected to be valid.
)
from elftools.dwarf.dwarfinfo import DWARFInfo
from elftools.dwarf.descriptions import (
- describe_attr_value, set_global_machine_arch)
+ describe_attr_value, set_global_machine_arch, describe_CFI_instruction)
from elftools.dwarf.constants import (
DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file)
+from elftools.dwarf.callframe import CIE, FDE
class ReadElf(object):
self._dump_debug_info()
elif dump_what == 'decodedline':
self._dump_debug_line_programs()
+ elif dump_what == 'frames':
+ self._dump_debug_frames()
else:
self._emitline('debug dump not yet supported for "%s"' % dump_what)
# Another readelf oddity...
self._emitline()
+ def _dump_debug_frames(self):
+ """ Dump the raw frame information from .debug_frame
+ """
+ self._emitline('Contents of the .debug_frame section:')
+
+ for entry in self._dwarfinfo.CFI_entries():
+ if isinstance(entry, CIE):
+ self._emitline('\n%08x %08x %08x CIE' % (
+ entry.offset, entry['length'], entry['CIE_id']))
+ self._emitline(' Version: %d' % entry['version'])
+ self._emitline(' Augmentation: "%s"' % entry['augmentation'])
+ self._emitline(' Code alignment factor: %u' % entry['code_alignment_factor'])
+ self._emitline(' Data alignment factor: %d' % entry['data_alignment_factor'])
+ self._emitline(' Return address column: %d' % entry['return_address_register'])
+ else: # FDE
+ self._emitline('\n%08x %08x %08x FDE cie=%08x pc=%08x..%08x' % (
+ entry.offset,
+ entry['length'],
+ entry['CIE_pointer'],
+ entry.cie.offset,
+ entry['initial_location'],
+ entry['initial_location'] + entry['address_range']))
+
+ if len(entry.instructions) > 0:
+ self._emitline('')
+ for instr in entry.instructions:
+ self._emitline(describe_CFI_instruction(instr, entry))
+
def _emit(self, s=''):
""" Emit an object to output
"""