xref: /llvm-project/lldb/packages/Python/lldbsuite/test/lldbdwarf.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1""" This module implement Dwarf expression opcode parser. """
2
3import lldb
4
5# DWARF Expression operators.
6DW_OP_addr = 0x03
7DW_OP_deref = 0x06
8DW_OP_const1u = 0x08
9DW_OP_const1s = 0x09
10DW_OP_const2u = 0x0A
11DW_OP_const2s = 0x0B
12DW_OP_const4u = 0x0C
13DW_OP_const4s = 0x0D
14DW_OP_const8u = 0x0E
15DW_OP_const8s = 0x0F
16DW_OP_constu = 0x10
17DW_OP_consts = 0x11
18DW_OP_dup = 0x12
19DW_OP_drop = 0x13
20DW_OP_over = 0x14
21DW_OP_pick = 0x15
22DW_OP_swap = 0x16
23DW_OP_rot = 0x17
24DW_OP_xderef = 0x18
25DW_OP_abs = 0x19
26DW_OP_and = 0x1A
27DW_OP_div = 0x1B
28DW_OP_minus = 0x1C
29DW_OP_mod = 0x1D
30DW_OP_mul = 0x1E
31DW_OP_neg = 0x1F
32DW_OP_not = 0x20
33DW_OP_or = 0x21
34DW_OP_plus = 0x22
35DW_OP_plus_uconst = 0x23
36DW_OP_shl = 0x24
37DW_OP_shr = 0x25
38DW_OP_shra = 0x26
39DW_OP_xor = 0x27
40DW_OP_skip = 0x2F
41DW_OP_bra = 0x28
42DW_OP_eq = 0x29
43DW_OP_ge = 0x2A
44DW_OP_gt = 0x2B
45DW_OP_le = 0x2C
46DW_OP_lt = 0x2D
47DW_OP_ne = 0x2E
48DW_OP_lit0 = 0x30
49DW_OP_lit1 = 0x31
50DW_OP_lit2 = 0x32
51DW_OP_lit3 = 0x33
52DW_OP_lit4 = 0x34
53DW_OP_lit5 = 0x35
54DW_OP_lit6 = 0x36
55DW_OP_lit7 = 0x37
56DW_OP_lit8 = 0x38
57DW_OP_lit9 = 0x39
58DW_OP_lit10 = 0x3A
59DW_OP_lit11 = 0x3B
60DW_OP_lit12 = 0x3C
61DW_OP_lit13 = 0x3D
62DW_OP_lit14 = 0x3E
63DW_OP_lit15 = 0x3F
64DW_OP_lit16 = 0x40
65DW_OP_lit17 = 0x41
66DW_OP_lit18 = 0x42
67DW_OP_lit19 = 0x43
68DW_OP_lit20 = 0x44
69DW_OP_lit21 = 0x45
70DW_OP_lit22 = 0x46
71DW_OP_lit23 = 0x47
72DW_OP_lit24 = 0x48
73DW_OP_lit25 = 0x49
74DW_OP_lit26 = 0x4A
75DW_OP_lit27 = 0x4B
76DW_OP_lit28 = 0x4C
77DW_OP_lit29 = 0x4D
78DW_OP_lit30 = 0x4E
79DW_OP_lit31 = 0x4F
80DW_OP_reg0 = 0x50
81DW_OP_reg1 = 0x51
82DW_OP_reg2 = 0x52
83DW_OP_reg3 = 0x53
84DW_OP_reg4 = 0x54
85DW_OP_reg5 = 0x55
86DW_OP_reg6 = 0x56
87DW_OP_reg7 = 0x57
88DW_OP_reg8 = 0x58
89DW_OP_reg9 = 0x59
90DW_OP_reg10 = 0x5A
91DW_OP_reg11 = 0x5B
92DW_OP_reg12 = 0x5C
93DW_OP_reg13 = 0x5D
94DW_OP_reg14 = 0x5E
95DW_OP_reg15 = 0x5F
96DW_OP_reg16 = 0x60
97DW_OP_reg17 = 0x61
98DW_OP_reg18 = 0x62
99DW_OP_reg19 = 0x63
100DW_OP_reg20 = 0x64
101DW_OP_reg21 = 0x65
102DW_OP_reg22 = 0x66
103DW_OP_reg23 = 0x67
104DW_OP_reg24 = 0x68
105DW_OP_reg25 = 0x69
106DW_OP_reg26 = 0x6A
107DW_OP_reg27 = 0x6B
108DW_OP_reg28 = 0x6C
109DW_OP_reg29 = 0x6D
110DW_OP_reg30 = 0x6E
111DW_OP_reg31 = 0x6F
112DW_OP_breg0 = 0x70
113DW_OP_breg1 = 0x71
114DW_OP_breg2 = 0x72
115DW_OP_breg3 = 0x73
116DW_OP_breg4 = 0x74
117DW_OP_breg5 = 0x75
118DW_OP_breg6 = 0x76
119DW_OP_breg7 = 0x77
120DW_OP_breg8 = 0x78
121DW_OP_breg9 = 0x79
122DW_OP_breg10 = 0x7A
123DW_OP_breg11 = 0x7B
124DW_OP_breg12 = 0x7C
125DW_OP_breg13 = 0x7D
126DW_OP_breg14 = 0x7E
127DW_OP_breg15 = 0x7F
128DW_OP_breg16 = 0x80
129DW_OP_breg17 = 0x81
130DW_OP_breg18 = 0x82
131DW_OP_breg19 = 0x83
132DW_OP_breg20 = 0x84
133DW_OP_breg21 = 0x85
134DW_OP_breg22 = 0x86
135DW_OP_breg23 = 0x87
136DW_OP_breg24 = 0x88
137DW_OP_breg25 = 0x89
138DW_OP_breg26 = 0x8A
139DW_OP_breg27 = 0x8B
140DW_OP_breg28 = 0x8C
141DW_OP_breg29 = 0x8D
142DW_OP_breg30 = 0x8E
143DW_OP_breg31 = 0x8F
144DW_OP_regx = 0x90
145DW_OP_fbreg = 0x91
146DW_OP_bregx = 0x92
147DW_OP_piece = 0x93
148DW_OP_deref_size = 0x94
149DW_OP_xderef_size = 0x95
150DW_OP_nop = 0x96
151DW_OP_push_object_address = 0x97
152DW_OP_call2 = 0x98
153DW_OP_call4 = 0x99
154DW_OP_call_ref = 0x9A
155DW_OP_form_tls_address = 0x9B
156DW_OP_call_frame_cfa = 0x9C
157DW_OP_bit_piece = 0x9D
158DW_OP_implicit_value = 0x9E
159DW_OP_stack_value = 0x9F
160DW_OP_lo_user = 0xE0
161DW_OP_GNU_push_tls_address = 0xE0
162DW_OP_hi_user = 0xFF
163
164
165class DwarfOpcodeParser(object):
166    def updateRegInfoBitsize(self, reg_info, byte_order):
167        """Update the regInfo bit size."""
168
169        # Evaluate Dwarf Expression
170        expr_result = self.evaluateDwarfExpression(
171            reg_info["dynamic_size_dwarf_expr_bytes"], byte_order
172        )
173
174        if expr_result == 0:
175            reg_info["bitsize"] = 32
176        elif expr_result == 1:
177            reg_info["bitsize"] = 64
178
179    def evaluateDwarfExpression(self, dwarf_opcode, byte_order):
180        """Evaluate Dwarf Expression."""
181
182        dwarf_opcode = [dwarf_opcode[i : i + 2] for i in range(0, len(dwarf_opcode), 2)]
183        dwarf_data = []
184        for index in range(len(dwarf_opcode)):
185            if index < len(dwarf_opcode):
186                val = int(dwarf_opcode[index], 16)
187            else:
188                break
189
190            if val == DW_OP_regx:
191                # Read register number
192                self.assertTrue(len(dwarf_opcode) > (index + 1))
193                reg_no = int(dwarf_opcode.pop(index + 1), 16)
194
195                self.reset_test_sequence()
196                # Read register value
197                self.test_sequence.add_log_lines(
198                    [
199                        "read packet: $p{0:x}#00".format(reg_no),
200                        {
201                            "direction": "send",
202                            "regex": r"^\$([0-9a-fA-F]+)#",
203                            "capture": {1: "p_response"},
204                        },
205                    ],
206                    True,
207                )
208
209                Context = self.expect_gdbremote_sequence()
210                self.assertIsNotNone(Context)
211                p_response = Context.get("p_response")
212                self.assertIsNotNone(p_response)
213
214                if byte_order == lldb.eByteOrderLittle:
215                    # In case of little endian
216                    # first decode the HEX ASCII bytes and then reverse it
217                    # to get actual value of SR register
218                    p_response = "".join(
219                        reversed(
220                            [
221                                p_response[i : i + 2]
222                                for i in range(0, len(p_response), 2)
223                            ]
224                        )
225                    )
226                # Push register value
227                dwarf_data.append(int(p_response, 16))
228
229            elif val == DW_OP_lit1:
230                # Push literal 1
231                dwarf_data.append(1)
232
233            elif val == DW_OP_lit26:
234                # Push literal 26
235                dwarf_data.append(26)
236
237            elif val == DW_OP_shl:
238                # left shift and push the result back
239                self.assertTrue(len(dwarf_data) > 1)
240                shift_amount = dwarf_data.pop()
241                val_to_shift = dwarf_data.pop()
242                result = val_to_shift << shift_amount
243                dwarf_data.append(result)
244
245            elif val == DW_OP_shr:
246                # Right shift and push the result back
247                self.assertTrue(len(dwarf_data) > 1)
248                shift_amount = dwarf_data.pop()
249                val_to_shift = dwarf_data.pop()
250                result = val_to_shift >> shift_amount
251                dwarf_data.append(result)
252
253            elif val == DW_OP_and:
254                # And of topmost 2 elements and push the result back
255                first_ele = dwarf_data.pop()
256                second_ele = dwarf_data.pop()
257                result = first_ele & second_ele
258                dwarf_data.append(result)
259
260            else:
261                self.assertTrue(False and "Unprocess Dwarf Opcode")
262
263        self.assertTrue(len(dwarf_data) == 1)
264        expr_result = dwarf_data.pop()
265        return expr_result
266