def bregN(self, regnum): '''The single operand of the DW_OP_bregn operations provides a signed LEB128 offset from the specified register.''' offset = SLEB.decode(self.expression) if offset > 0: self.push('(char *) get_reg(%i) + %#x' % (regnum, offset)) elif offset < 0: self.push('(char *) get_reg(%i) - %#x' % (regnum, abs(offset))) else: self.push('(char *) get_reg(%i)' % (regnum))
def fbreg(self): '''The DW_OP_fbreg operation provides a signed LEB128 offset from the address specified by the location description in the DW_AT_frame_base attribute of the current function. (This is typically a "stack pointer" register plus or minus some offset. On more sophisticated systems it might be a location list that adjusts the offset according to changes in the stack pointer as the PC changes.)''' offset = SLEB.decode(self.expression) if offset > 0: self.push('__adbi_frame__ + %#x' % offset) elif offset < 0: self.push('__adbi_frame__ - %#x' % abs(offset)) else: self.push('__adbi_frame__') self.uses_frame = True
def iter_entries(): if not self.debug_info.dwarf.has_CFI(): logging.warn('ELF has no call frame information.') return for fde in self.debug_info.dwarf.CFI_entries(): if not isinstance(fde, FDE): continue low = fde.header.initial_location high = low + fde.header.address_range invalid = False decoded = fde.get_decoded().table for n, each in enumerate(decoded, 0): try: entry_low = debug_info.addr2fo(each['pc']) entry_high = debug_info.addr2fo( high if n >= len(decoded) - 1 else decoded[n + 1]['pc']) except ValueError: invalid = True continue cfa_rule = each['cfa'] if cfa_rule.expr is not None: # CFA is a regular DWARF expressions expr = cfa_rule.expr else: assert cfa_rule.reg is not None # CFA is a register + offset -- convert it to a DWARF expression expr = bytearray([0x92]) # DW_OP_bregx expr += LEB.encode(cfa_rule.reg) # Register index expr += SLEB.encode( cfa_rule.offset) # Offset from register yield CallFrameInfoEntry(entry_low, entry_high, b64encode(expr)) if invalid: logging.warn( 'Invalid call frame information entry encountered in FDE at %#x.', fde.offset)
def iter_entries(): if not self.debug_info.dwarf.has_CFI(): logging.warn('ELF has no call frame information.') return for fde in self.debug_info.dwarf.CFI_entries(): if not isinstance(fde, FDE): continue low = fde.header.initial_location high = low + fde.header.address_range invalid = False decoded = fde.get_decoded().table for n, each in enumerate(decoded, 0): try: entry_low = debug_info.addr2fo(each['pc']) entry_high = debug_info.addr2fo(high if n >= len(decoded) - 1 else decoded[n + 1]['pc']) except ValueError: invalid = True continue cfa_rule = each['cfa'] if cfa_rule.expr is not None: # CFA is a regular DWARF expressions expr = cfa_rule.expr else: assert cfa_rule.reg is not None # CFA is a register + offset -- convert it to a DWARF expression expr = bytearray([0x92]) # DW_OP_bregx expr += LEB.encode(cfa_rule.reg) # Register index expr += SLEB.encode(cfa_rule.offset) # Offset from register yield CallFrameInfoEntry(entry_low, entry_high, b64encode(expr)) if invalid: logging.warn('Invalid call frame information entry encountered in FDE at %#x.', fde.offset)
def consts(self): '''The single operand of the DW_OP_consts operation provides a signed LEB128 integer constant.''' val = SLEB.decode(self.expression) self.push('%#x' % val)