s += ' %s: %s\n' % (name, instr.args[0])
elif name == 'DW_CFA_def_cfa_expression':
expr_dumper = ExprDumper(entry.structs)
- expr_dumper.process_expr(instr.args[0])
# readelf output is missing a colon for DW_CFA_def_cfa_expression
- s += ' %s (%s)\n' % (name, expr_dumper.get_str())
+ s += ' %s (%s)\n' % (name, expr_dumper.dump_expr(instr.args[0]))
elif name == 'DW_CFA_expression':
expr_dumper = ExprDumper(entry.structs)
- expr_dumper.process_expr(instr.args[1])
s += ' %s: %s (%s)\n' % (
- name, _full_reg_name(instr.args[0]), expr_dumper.get_str())
+ name, _full_reg_name(instr.args[0]),
+ expr_dumper.dump_expr(instr.args[1]))
else:
s += ' %s: <??>\n' % name
_DWARF_EXPR_DUMPER_CACHE[cache_key] = \
ExprDumper(structs)
dwarf_expr_dumper = _DWARF_EXPR_DUMPER_CACHE[cache_key]
- dwarf_expr_dumper.clear()
- dwarf_expr_dumper.process_expr(expr)
- return '(' + dwarf_expr_dumper.get_str() + ')'
+ return '(' + dwarf_expr_dumper.dump_expr(expr) + ')'
def describe_reg_name(regnum, machine_arch=None, default=True):
""" A dumper for DWARF expressions that dumps a textual
representation of the complete expression.
- Usage: after creation, call process_expr, and then get_str for a
- semicolon-delimited string representation of the decoded expression.
+ Usage: after creation, call dump_expr repeatedly - it's stateless.
"""
def __init__(self, structs):
self.structs = structs
self._init_lookups()
self._str_parts = []
- def process_expr(self, expr):
- """ Parse and process a DWARF expression. expr should be a list of
+ def dump_expr(self, expr):
+ """ Parse and dump a DWARF expression. expr should be a list of
(integer) byte values.
+
+ Returns a string representing the expression.
"""
parsed = self.expr_parser.parse_expr(expr)
+ s = []
for deo in parsed:
- self._str_parts.append(self._dump_to_string(deo.op, deo.op_name, deo.args))
-
- def clear(self):
- self._str_parts = []
-
- def get_str(self):
- return '; '.join(self._str_parts)
+ s.append(self._dump_to_string(deo.op, deo.op_name, deo.args))
+ return '; '.join(s)
def _init_lookups(self):
self._ops_with_decimal_arg = set([
set_global_machine_arch('x64')
def test_basic_single(self):
- self.visitor.process_expr([0x1b])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x1b]),
'DW_OP_div')
- self.setUp()
- self.visitor.process_expr([0x74, 0x82, 0x01])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x74, 0x82, 0x01]),
'DW_OP_breg4 (rsi): 130')
- self.setUp()
- self.visitor.process_expr([0x91, 0x82, 0x01])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x91, 0x82, 0x01]),
'DW_OP_fbreg: 130')
- self.setUp()
- self.visitor.process_expr([0x51])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x51]),
'DW_OP_reg1 (rdx)')
- self.setUp()
- self.visitor.process_expr([0x90, 16])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x90, 16]),
'DW_OP_regx: 16 (rip)')
- self.setUp()
- self.visitor.process_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]),
'DW_OP_bit_piece: 1295 144')
def test_basic_sequence(self):
- self.visitor.process_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]),
'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref')
- self.setUp()
- self.visitor.process_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]),
'DW_OP_pick: 255; DW_OP_const2s: -15')
- self.setUp()
- self.visitor.process_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e])
- self.assertEqual(self.visitor.get_str(),
+ self.assertEqual(self.visitor.dump_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]),
'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul')