1#-------------------------------------------------------------------------------
2# elftools tests
3#
4# Eli Bendersky (eliben@gmail.com)
5# This code is in the public domain
6#-------------------------------------------------------------------------------
7import unittest
8
9from elftools.dwarf.descriptions import ExprDumper, set_global_machine_arch
10from elftools.dwarf.dwarf_expr import DWARFExprParser, DWARFExprOp
11from elftools.dwarf.structs import DWARFStructs
12
13
14class TestExprDumper(unittest.TestCase):
15    structs32 = DWARFStructs(
16            little_endian=True,
17            dwarf_format=32,
18            address_size=4)
19
20    def setUp(self):
21        self.visitor = ExprDumper(self.structs32)
22        set_global_machine_arch('x64')
23
24    def test_basic_single(self):
25        self.assertEqual(self.visitor.dump_expr([0x1b]),
26            'DW_OP_div')
27
28        self.assertEqual(self.visitor.dump_expr([0x74, 0x82, 0x01]),
29            'DW_OP_breg4 (rsi): 130')
30
31        self.assertEqual(self.visitor.dump_expr([0x91, 0x82, 0x01]),
32            'DW_OP_fbreg: 130')
33
34        self.assertEqual(self.visitor.dump_expr([0x51]),
35            'DW_OP_reg1 (rdx)')
36
37        self.assertEqual(self.visitor.dump_expr([0x90, 16]),
38            'DW_OP_regx: 16 (rip)')
39
40        self.assertEqual(self.visitor.dump_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]),
41            'DW_OP_bit_piece: 1295 144')
42
43        self.assertEqual(self.visitor.dump_expr([0x0e, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00]),
44            'DW_OP_const8u: 71777214294589695')
45
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')
49
50        self.assertEqual(self.visitor.dump_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]),
51            'DW_OP_pick: 255; DW_OP_const2s: -15')
52
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')
55
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'))
61
62
63class TestParseExpr(unittest.TestCase):
64    structs32 = DWARFStructs(
65            little_endian=True,
66            dwarf_format=32,
67            address_size=4)
68
69    def setUp(self):
70        set_global_machine_arch('x64')
71
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=[])])
76
77        lst = p.parse_expr([0x90, 16])
78        self.assertEqual(lst, [DWARFExprOp(op=0x90, op_name='DW_OP_regx', args=[16])])
79
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=[]),
86            DWARFExprOp(op=0xe0, op_name='DW_OP_lo_user', args=[])])
87
88
89if __name__ == '__main__':
90    unittest.main()
91