1 #-------------------------------------------------------------------------------
4 # Eli Bendersky (eliben@gmail.com)
5 # This code is in the public domain
6 #-------------------------------------------------------------------------------
9 from elftools
.dwarf
.descriptions
import ExprDumper
, set_global_machine_arch
10 from elftools
.dwarf
.dwarf_expr
import DWARFExprParser
, DWARFExprOp
11 from elftools
.dwarf
.structs
import DWARFStructs
14 class TestExprDumper(unittest
.TestCase
):
15 structs32
= DWARFStructs(
21 self
.visitor
= ExprDumper(self
.structs32
)
22 set_global_machine_arch('x64')
24 def test_basic_single(self
):
25 self
.assertEqual(self
.visitor
.dump_expr([0x1b]),
28 self
.assertEqual(self
.visitor
.dump_expr([0x74, 0x82, 0x01]),
29 'DW_OP_breg4 (rsi): 130')
31 self
.assertEqual(self
.visitor
.dump_expr([0x91, 0x82, 0x01]),
34 self
.assertEqual(self
.visitor
.dump_expr([0x51]),
37 self
.assertEqual(self
.visitor
.dump_expr([0x90, 16]),
38 'DW_OP_regx: 16 (rip)')
40 self
.assertEqual(self
.visitor
.dump_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]),
41 'DW_OP_bit_piece: 1295 144')
43 self
.assertEqual(self
.visitor
.dump_expr([0x0e, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00]),
44 'DW_OP_const8u: 71777214294589695')
46 def test_basic_sequence(self
):
47 self
.assertEqual(self
.visitor
.dump_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]),
48 'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref')
50 self
.assertEqual(self
.visitor
.dump_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]),
51 'DW_OP_pick: 255; DW_OP_const2s: -15')
53 self
.assertEqual(self
.visitor
.dump_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]),
54 'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul')
56 # 0xe0 maps to both DW_OP_GNU_push_tls_address and DW_OP_lo_user, so
57 # check for both to prevent non-determinism.
58 self
.assertIn(self
.visitor
.dump_expr([0x08, 0x0f, 0xe0]),
59 ('DW_OP_const1u: 15; DW_OP_GNU_push_tls_address',
60 'DW_OP_const1u: 15; DW_OP_lo_user'))
63 class TestParseExpr(unittest
.TestCase
):
64 structs32
= DWARFStructs(
70 set_global_machine_arch('x64')
72 def test_single(self
):
73 p
= DWARFExprParser(self
.structs32
)
74 lst
= p
.parse_expr([0x1b])
75 self
.assertEqual(lst
, [DWARFExprOp(op
=0x1B, op_name
='DW_OP_div', args
=[], offset
=0)])
77 lst
= p
.parse_expr([0x90, 16])
78 self
.assertEqual(lst
, [DWARFExprOp(op
=0x90, op_name
='DW_OP_regx', args
=[16], offset
=0)])
80 lst
= p
.parse_expr([0xe0])
81 self
.assertEqual(len(lst
), 1)
82 # 0xe0 maps to both DW_OP_GNU_push_tls_address and DW_OP_lo_user, so
83 # check for both to prevent non-determinism.
84 self
.assertIn(lst
[0], [
85 DWARFExprOp(op
=0xe0, op_name
='DW_OP_GNU_push_tls_address', args
=[], offset
=0),
86 DWARFExprOp(op
=0xe0, op_name
='DW_OP_lo_user', args
=[], offset
=0)])
98 lst
= p
.parse_expr([0x97,0x6,0x12,0x28,0x4,0x0,0x30,0x2F,0x3,0x0,0x34,0x1C,0x6])
99 self
.assertEqual(len(lst
), 9)
100 self
.assertEqual(lst
, [
101 DWARFExprOp(op
=0x97, op_name
='DW_OP_push_object_address', args
=[], offset
=0),
102 DWARFExprOp(op
=0x6, op_name
='DW_OP_deref', args
=[], offset
=1),
103 DWARFExprOp(op
=0x12, op_name
='DW_OP_dup', args
=[], offset
=2),
104 DWARFExprOp(op
=0x28, op_name
='DW_OP_bra', args
=[4], offset
=3),
105 DWARFExprOp(op
=0x30, op_name
='DW_OP_lit0', args
=[], offset
=6),
106 DWARFExprOp(op
=0x2f, op_name
='DW_OP_skip', args
=[3], offset
=7),
107 DWARFExprOp(op
=0x34, op_name
='DW_OP_lit4', args
=[], offset
=10),
108 DWARFExprOp(op
=0x1c, op_name
='DW_OP_minus', args
=[], offset
=11),
109 DWARFExprOp(op
=0x6, op_name
='DW_OP_deref', args
=[], offset
=12)])
112 if __name__
== '__main__':