File: | tools/lldb/source/Expression/DWARFExpression.cpp |
Warning: | line 1472, column 51 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- DWARFExpression.cpp -------------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "lldb/Expression/DWARFExpression.h" | |||
11 | ||||
12 | // C Includes | |||
13 | #include <inttypes.h> | |||
14 | ||||
15 | // C++ Includes | |||
16 | #include <vector> | |||
17 | ||||
18 | #include "lldb/Core/Module.h" | |||
19 | #include "lldb/Core/Value.h" | |||
20 | #include "lldb/Core/dwarf.h" | |||
21 | #include "lldb/Utility/DataEncoder.h" | |||
22 | #include "lldb/Utility/Log.h" | |||
23 | #include "lldb/Utility/RegisterValue.h" | |||
24 | #include "lldb/Utility/Scalar.h" | |||
25 | #include "lldb/Utility/StreamString.h" | |||
26 | #include "lldb/Utility/VMRange.h" | |||
27 | ||||
28 | #include "lldb/Host/Host.h" | |||
29 | #include "lldb/Utility/Endian.h" | |||
30 | ||||
31 | #include "lldb/Symbol/Function.h" | |||
32 | ||||
33 | #include "lldb/Target/ABI.h" | |||
34 | #include "lldb/Target/ExecutionContext.h" | |||
35 | #include "lldb/Target/Process.h" | |||
36 | #include "lldb/Target/RegisterContext.h" | |||
37 | #include "lldb/Target/StackFrame.h" | |||
38 | #include "lldb/Target/StackID.h" | |||
39 | #include "lldb/Target/Thread.h" | |||
40 | ||||
41 | #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" | |||
42 | ||||
43 | using namespace lldb; | |||
44 | using namespace lldb_private; | |||
45 | ||||
46 | static lldb::addr_t | |||
47 | ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu, | |||
48 | uint32_t index) { | |||
49 | uint32_t index_size = dwarf_cu->GetAddressByteSize(); | |||
50 | dw_offset_t addr_base = dwarf_cu->GetAddrBase(); | |||
51 | lldb::offset_t offset = addr_base + index * index_size; | |||
52 | return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64( | |||
53 | &offset, index_size); | |||
54 | } | |||
55 | ||||
56 | //---------------------------------------------------------------------- | |||
57 | // DWARFExpression constructor | |||
58 | //---------------------------------------------------------------------- | |||
59 | DWARFExpression::DWARFExpression(DWARFUnit *dwarf_cu) | |||
60 | : m_module_wp(), m_data(), m_dwarf_cu(dwarf_cu), | |||
61 | m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS(18446744073709551615UL)) {} | |||
62 | ||||
63 | DWARFExpression::DWARFExpression(const DWARFExpression &rhs) | |||
64 | : m_module_wp(rhs.m_module_wp), m_data(rhs.m_data), | |||
65 | m_dwarf_cu(rhs.m_dwarf_cu), m_reg_kind(rhs.m_reg_kind), | |||
66 | m_loclist_slide(rhs.m_loclist_slide) {} | |||
67 | ||||
68 | DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, | |||
69 | const DataExtractor &data, | |||
70 | DWARFUnit *dwarf_cu, | |||
71 | lldb::offset_t data_offset, | |||
72 | lldb::offset_t data_length) | |||
73 | : m_module_wp(), m_data(data, data_offset, data_length), | |||
74 | m_dwarf_cu(dwarf_cu), m_reg_kind(eRegisterKindDWARF), | |||
75 | m_loclist_slide(LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
76 | if (module_sp) | |||
77 | m_module_wp = module_sp; | |||
78 | } | |||
79 | ||||
80 | //---------------------------------------------------------------------- | |||
81 | // Destructor | |||
82 | //---------------------------------------------------------------------- | |||
83 | DWARFExpression::~DWARFExpression() {} | |||
84 | ||||
85 | bool DWARFExpression::IsValid() const { return m_data.GetByteSize() > 0; } | |||
86 | ||||
87 | void DWARFExpression::SetOpcodeData(const DataExtractor &data) { | |||
88 | m_data = data; | |||
89 | } | |||
90 | ||||
91 | void DWARFExpression::CopyOpcodeData(lldb::ModuleSP module_sp, | |||
92 | const DataExtractor &data, | |||
93 | lldb::offset_t data_offset, | |||
94 | lldb::offset_t data_length) { | |||
95 | const uint8_t *bytes = data.PeekData(data_offset, data_length); | |||
96 | if (bytes) { | |||
97 | m_module_wp = module_sp; | |||
98 | m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length))); | |||
99 | m_data.SetByteOrder(data.GetByteOrder()); | |||
100 | m_data.SetAddressByteSize(data.GetAddressByteSize()); | |||
101 | } | |||
102 | } | |||
103 | ||||
104 | void DWARFExpression::CopyOpcodeData(const void *data, | |||
105 | lldb::offset_t data_length, | |||
106 | ByteOrder byte_order, | |||
107 | uint8_t addr_byte_size) { | |||
108 | if (data && data_length) { | |||
109 | m_data.SetData(DataBufferSP(new DataBufferHeap(data, data_length))); | |||
110 | m_data.SetByteOrder(byte_order); | |||
111 | m_data.SetAddressByteSize(addr_byte_size); | |||
112 | } | |||
113 | } | |||
114 | ||||
115 | void DWARFExpression::CopyOpcodeData(uint64_t const_value, | |||
116 | lldb::offset_t const_value_byte_size, | |||
117 | uint8_t addr_byte_size) { | |||
118 | if (const_value_byte_size) { | |||
119 | m_data.SetData( | |||
120 | DataBufferSP(new DataBufferHeap(&const_value, const_value_byte_size))); | |||
121 | m_data.SetByteOrder(endian::InlHostByteOrder()); | |||
122 | m_data.SetAddressByteSize(addr_byte_size); | |||
123 | } | |||
124 | } | |||
125 | ||||
126 | void DWARFExpression::SetOpcodeData(lldb::ModuleSP module_sp, | |||
127 | const DataExtractor &data, | |||
128 | lldb::offset_t data_offset, | |||
129 | lldb::offset_t data_length) { | |||
130 | m_module_wp = module_sp; | |||
131 | m_data.SetData(data, data_offset, data_length); | |||
132 | } | |||
133 | ||||
134 | void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset, | |||
135 | lldb::offset_t length, | |||
136 | lldb::DescriptionLevel level, | |||
137 | ABI *abi) const { | |||
138 | if (!m_data.ValidOffsetForDataOfSize(offset, length)) | |||
139 | return; | |||
140 | const lldb::offset_t start_offset = offset; | |||
141 | const lldb::offset_t end_offset = offset + length; | |||
142 | while (m_data.ValidOffset(offset) && offset < end_offset) { | |||
143 | const lldb::offset_t op_offset = offset; | |||
144 | const uint8_t op = m_data.GetU8(&offset); | |||
145 | ||||
146 | switch (level) { | |||
147 | default: | |||
148 | break; | |||
149 | ||||
150 | case lldb::eDescriptionLevelBrief: | |||
151 | if (op_offset > start_offset) | |||
152 | s->PutChar(' '); | |||
153 | break; | |||
154 | ||||
155 | case lldb::eDescriptionLevelFull: | |||
156 | case lldb::eDescriptionLevelVerbose: | |||
157 | if (op_offset > start_offset) | |||
158 | s->EOL(); | |||
159 | s->Indent(); | |||
160 | if (level == lldb::eDescriptionLevelFull) | |||
161 | break; | |||
162 | // Fall through for verbose and print offset and DW_OP prefix.. | |||
163 | s->Printf("0x%8.8" PRIx64"l" "x" ": %s", op_offset, | |||
164 | op >= DW_OP_APPLE_uninit0xF0 ? "DW_OP_APPLE_" : "DW_OP_"); | |||
165 | break; | |||
166 | } | |||
167 | ||||
168 | switch (op) { | |||
169 | case DW_OP_addr: | |||
170 | *s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") "; | |||
171 | break; // 0x03 1 address | |||
172 | case DW_OP_deref: | |||
173 | *s << "DW_OP_deref"; | |||
174 | break; // 0x06 | |||
175 | case DW_OP_const1u: | |||
176 | s->Printf("DW_OP_const1u(0x%2.2x)", m_data.GetU8(&offset)); | |||
177 | break; // 0x08 1 1-byte constant | |||
178 | case DW_OP_const1s: | |||
179 | s->Printf("DW_OP_const1s(0x%2.2x)", m_data.GetU8(&offset)); | |||
180 | break; // 0x09 1 1-byte constant | |||
181 | case DW_OP_const2u: | |||
182 | s->Printf("DW_OP_const2u(0x%4.4x)", m_data.GetU16(&offset)); | |||
183 | break; // 0x0a 1 2-byte constant | |||
184 | case DW_OP_const2s: | |||
185 | s->Printf("DW_OP_const2s(0x%4.4x)", m_data.GetU16(&offset)); | |||
186 | break; // 0x0b 1 2-byte constant | |||
187 | case DW_OP_const4u: | |||
188 | s->Printf("DW_OP_const4u(0x%8.8x)", m_data.GetU32(&offset)); | |||
189 | break; // 0x0c 1 4-byte constant | |||
190 | case DW_OP_const4s: | |||
191 | s->Printf("DW_OP_const4s(0x%8.8x)", m_data.GetU32(&offset)); | |||
192 | break; // 0x0d 1 4-byte constant | |||
193 | case DW_OP_const8u: | |||
194 | s->Printf("DW_OP_const8u(0x%16.16" PRIx64"l" "x" ")", m_data.GetU64(&offset)); | |||
195 | break; // 0x0e 1 8-byte constant | |||
196 | case DW_OP_const8s: | |||
197 | s->Printf("DW_OP_const8s(0x%16.16" PRIx64"l" "x" ")", m_data.GetU64(&offset)); | |||
198 | break; // 0x0f 1 8-byte constant | |||
199 | case DW_OP_constu: | |||
200 | s->Printf("DW_OP_constu(0x%" PRIx64"l" "x" ")", m_data.GetULEB128(&offset)); | |||
201 | break; // 0x10 1 ULEB128 constant | |||
202 | case DW_OP_consts: | |||
203 | s->Printf("DW_OP_consts(0x%" PRId64"l" "d" ")", m_data.GetSLEB128(&offset)); | |||
204 | break; // 0x11 1 SLEB128 constant | |||
205 | case DW_OP_dup: | |||
206 | s->PutCString("DW_OP_dup"); | |||
207 | break; // 0x12 | |||
208 | case DW_OP_drop: | |||
209 | s->PutCString("DW_OP_drop"); | |||
210 | break; // 0x13 | |||
211 | case DW_OP_over: | |||
212 | s->PutCString("DW_OP_over"); | |||
213 | break; // 0x14 | |||
214 | case DW_OP_pick: | |||
215 | s->Printf("DW_OP_pick(0x%2.2x)", m_data.GetU8(&offset)); | |||
216 | break; // 0x15 1 1-byte stack index | |||
217 | case DW_OP_swap: | |||
218 | s->PutCString("DW_OP_swap"); | |||
219 | break; // 0x16 | |||
220 | case DW_OP_rot: | |||
221 | s->PutCString("DW_OP_rot"); | |||
222 | break; // 0x17 | |||
223 | case DW_OP_xderef: | |||
224 | s->PutCString("DW_OP_xderef"); | |||
225 | break; // 0x18 | |||
226 | case DW_OP_abs: | |||
227 | s->PutCString("DW_OP_abs"); | |||
228 | break; // 0x19 | |||
229 | case DW_OP_and: | |||
230 | s->PutCString("DW_OP_and"); | |||
231 | break; // 0x1a | |||
232 | case DW_OP_div: | |||
233 | s->PutCString("DW_OP_div"); | |||
234 | break; // 0x1b | |||
235 | case DW_OP_minus: | |||
236 | s->PutCString("DW_OP_minus"); | |||
237 | break; // 0x1c | |||
238 | case DW_OP_mod: | |||
239 | s->PutCString("DW_OP_mod"); | |||
240 | break; // 0x1d | |||
241 | case DW_OP_mul: | |||
242 | s->PutCString("DW_OP_mul"); | |||
243 | break; // 0x1e | |||
244 | case DW_OP_neg: | |||
245 | s->PutCString("DW_OP_neg"); | |||
246 | break; // 0x1f | |||
247 | case DW_OP_not: | |||
248 | s->PutCString("DW_OP_not"); | |||
249 | break; // 0x20 | |||
250 | case DW_OP_or: | |||
251 | s->PutCString("DW_OP_or"); | |||
252 | break; // 0x21 | |||
253 | case DW_OP_plus: | |||
254 | s->PutCString("DW_OP_plus"); | |||
255 | break; // 0x22 | |||
256 | case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend | |||
257 | s->Printf("DW_OP_plus_uconst(0x%" PRIx64"l" "x" ")", | |||
258 | m_data.GetULEB128(&offset)); | |||
259 | break; | |||
260 | ||||
261 | case DW_OP_shl: | |||
262 | s->PutCString("DW_OP_shl"); | |||
263 | break; // 0x24 | |||
264 | case DW_OP_shr: | |||
265 | s->PutCString("DW_OP_shr"); | |||
266 | break; // 0x25 | |||
267 | case DW_OP_shra: | |||
268 | s->PutCString("DW_OP_shra"); | |||
269 | break; // 0x26 | |||
270 | case DW_OP_xor: | |||
271 | s->PutCString("DW_OP_xor"); | |||
272 | break; // 0x27 | |||
273 | case DW_OP_skip: | |||
274 | s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset)); | |||
275 | break; // 0x2f 1 signed 2-byte constant | |||
276 | case DW_OP_bra: | |||
277 | s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset)); | |||
278 | break; // 0x28 1 signed 2-byte constant | |||
279 | case DW_OP_eq: | |||
280 | s->PutCString("DW_OP_eq"); | |||
281 | break; // 0x29 | |||
282 | case DW_OP_ge: | |||
283 | s->PutCString("DW_OP_ge"); | |||
284 | break; // 0x2a | |||
285 | case DW_OP_gt: | |||
286 | s->PutCString("DW_OP_gt"); | |||
287 | break; // 0x2b | |||
288 | case DW_OP_le: | |||
289 | s->PutCString("DW_OP_le"); | |||
290 | break; // 0x2c | |||
291 | case DW_OP_lt: | |||
292 | s->PutCString("DW_OP_lt"); | |||
293 | break; // 0x2d | |||
294 | case DW_OP_ne: | |||
295 | s->PutCString("DW_OP_ne"); | |||
296 | break; // 0x2e | |||
297 | ||||
298 | case DW_OP_lit0: // 0x30 | |||
299 | case DW_OP_lit1: // 0x31 | |||
300 | case DW_OP_lit2: // 0x32 | |||
301 | case DW_OP_lit3: // 0x33 | |||
302 | case DW_OP_lit4: // 0x34 | |||
303 | case DW_OP_lit5: // 0x35 | |||
304 | case DW_OP_lit6: // 0x36 | |||
305 | case DW_OP_lit7: // 0x37 | |||
306 | case DW_OP_lit8: // 0x38 | |||
307 | case DW_OP_lit9: // 0x39 | |||
308 | case DW_OP_lit10: // 0x3A | |||
309 | case DW_OP_lit11: // 0x3B | |||
310 | case DW_OP_lit12: // 0x3C | |||
311 | case DW_OP_lit13: // 0x3D | |||
312 | case DW_OP_lit14: // 0x3E | |||
313 | case DW_OP_lit15: // 0x3F | |||
314 | case DW_OP_lit16: // 0x40 | |||
315 | case DW_OP_lit17: // 0x41 | |||
316 | case DW_OP_lit18: // 0x42 | |||
317 | case DW_OP_lit19: // 0x43 | |||
318 | case DW_OP_lit20: // 0x44 | |||
319 | case DW_OP_lit21: // 0x45 | |||
320 | case DW_OP_lit22: // 0x46 | |||
321 | case DW_OP_lit23: // 0x47 | |||
322 | case DW_OP_lit24: // 0x48 | |||
323 | case DW_OP_lit25: // 0x49 | |||
324 | case DW_OP_lit26: // 0x4A | |||
325 | case DW_OP_lit27: // 0x4B | |||
326 | case DW_OP_lit28: // 0x4C | |||
327 | case DW_OP_lit29: // 0x4D | |||
328 | case DW_OP_lit30: // 0x4E | |||
329 | case DW_OP_lit31: | |||
330 | s->Printf("DW_OP_lit%i", op - DW_OP_lit0); | |||
331 | break; // 0x4f | |||
332 | ||||
333 | case DW_OP_reg0: // 0x50 | |||
334 | case DW_OP_reg1: // 0x51 | |||
335 | case DW_OP_reg2: // 0x52 | |||
336 | case DW_OP_reg3: // 0x53 | |||
337 | case DW_OP_reg4: // 0x54 | |||
338 | case DW_OP_reg5: // 0x55 | |||
339 | case DW_OP_reg6: // 0x56 | |||
340 | case DW_OP_reg7: // 0x57 | |||
341 | case DW_OP_reg8: // 0x58 | |||
342 | case DW_OP_reg9: // 0x59 | |||
343 | case DW_OP_reg10: // 0x5A | |||
344 | case DW_OP_reg11: // 0x5B | |||
345 | case DW_OP_reg12: // 0x5C | |||
346 | case DW_OP_reg13: // 0x5D | |||
347 | case DW_OP_reg14: // 0x5E | |||
348 | case DW_OP_reg15: // 0x5F | |||
349 | case DW_OP_reg16: // 0x60 | |||
350 | case DW_OP_reg17: // 0x61 | |||
351 | case DW_OP_reg18: // 0x62 | |||
352 | case DW_OP_reg19: // 0x63 | |||
353 | case DW_OP_reg20: // 0x64 | |||
354 | case DW_OP_reg21: // 0x65 | |||
355 | case DW_OP_reg22: // 0x66 | |||
356 | case DW_OP_reg23: // 0x67 | |||
357 | case DW_OP_reg24: // 0x68 | |||
358 | case DW_OP_reg25: // 0x69 | |||
359 | case DW_OP_reg26: // 0x6A | |||
360 | case DW_OP_reg27: // 0x6B | |||
361 | case DW_OP_reg28: // 0x6C | |||
362 | case DW_OP_reg29: // 0x6D | |||
363 | case DW_OP_reg30: // 0x6E | |||
364 | case DW_OP_reg31: // 0x6F | |||
365 | { | |||
366 | uint32_t reg_num = op - DW_OP_reg0; | |||
367 | if (abi) { | |||
368 | RegisterInfo reg_info; | |||
369 | if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { | |||
370 | if (reg_info.name) { | |||
371 | s->PutCString(reg_info.name); | |||
372 | break; | |||
373 | } else if (reg_info.alt_name) { | |||
374 | s->PutCString(reg_info.alt_name); | |||
375 | break; | |||
376 | } | |||
377 | } | |||
378 | } | |||
379 | s->Printf("DW_OP_reg%u", reg_num); | |||
380 | break; | |||
381 | } break; | |||
382 | ||||
383 | case DW_OP_breg0: | |||
384 | case DW_OP_breg1: | |||
385 | case DW_OP_breg2: | |||
386 | case DW_OP_breg3: | |||
387 | case DW_OP_breg4: | |||
388 | case DW_OP_breg5: | |||
389 | case DW_OP_breg6: | |||
390 | case DW_OP_breg7: | |||
391 | case DW_OP_breg8: | |||
392 | case DW_OP_breg9: | |||
393 | case DW_OP_breg10: | |||
394 | case DW_OP_breg11: | |||
395 | case DW_OP_breg12: | |||
396 | case DW_OP_breg13: | |||
397 | case DW_OP_breg14: | |||
398 | case DW_OP_breg15: | |||
399 | case DW_OP_breg16: | |||
400 | case DW_OP_breg17: | |||
401 | case DW_OP_breg18: | |||
402 | case DW_OP_breg19: | |||
403 | case DW_OP_breg20: | |||
404 | case DW_OP_breg21: | |||
405 | case DW_OP_breg22: | |||
406 | case DW_OP_breg23: | |||
407 | case DW_OP_breg24: | |||
408 | case DW_OP_breg25: | |||
409 | case DW_OP_breg26: | |||
410 | case DW_OP_breg27: | |||
411 | case DW_OP_breg28: | |||
412 | case DW_OP_breg29: | |||
413 | case DW_OP_breg30: | |||
414 | case DW_OP_breg31: { | |||
415 | uint32_t reg_num = op - DW_OP_breg0; | |||
416 | int64_t reg_offset = m_data.GetSLEB128(&offset); | |||
417 | if (abi) { | |||
418 | RegisterInfo reg_info; | |||
419 | if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { | |||
420 | if (reg_info.name) { | |||
421 | s->Printf("[%s%+" PRIi64"l" "i" "]", reg_info.name, reg_offset); | |||
422 | break; | |||
423 | } else if (reg_info.alt_name) { | |||
424 | s->Printf("[%s%+" PRIi64"l" "i" "]", reg_info.alt_name, reg_offset); | |||
425 | break; | |||
426 | } | |||
427 | } | |||
428 | } | |||
429 | s->Printf("DW_OP_breg%i(0x%" PRIx64"l" "x" ")", reg_num, reg_offset); | |||
430 | } break; | |||
431 | ||||
432 | case DW_OP_regx: // 0x90 1 ULEB128 register | |||
433 | { | |||
434 | uint32_t reg_num = m_data.GetULEB128(&offset); | |||
435 | if (abi) { | |||
436 | RegisterInfo reg_info; | |||
437 | if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { | |||
438 | if (reg_info.name) { | |||
439 | s->PutCString(reg_info.name); | |||
440 | break; | |||
441 | } else if (reg_info.alt_name) { | |||
442 | s->PutCString(reg_info.alt_name); | |||
443 | break; | |||
444 | } | |||
445 | } | |||
446 | } | |||
447 | s->Printf("DW_OP_regx(%" PRIu32"u" ")", reg_num); | |||
448 | break; | |||
449 | } break; | |||
450 | case DW_OP_fbreg: // 0x91 1 SLEB128 offset | |||
451 | s->Printf("DW_OP_fbreg(%" PRIi64"l" "i" ")", m_data.GetSLEB128(&offset)); | |||
452 | break; | |||
453 | case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset | |||
454 | { | |||
455 | uint32_t reg_num = m_data.GetULEB128(&offset); | |||
456 | int64_t reg_offset = m_data.GetSLEB128(&offset); | |||
457 | if (abi) { | |||
458 | RegisterInfo reg_info; | |||
459 | if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { | |||
460 | if (reg_info.name) { | |||
461 | s->Printf("[%s%+" PRIi64"l" "i" "]", reg_info.name, reg_offset); | |||
462 | break; | |||
463 | } else if (reg_info.alt_name) { | |||
464 | s->Printf("[%s%+" PRIi64"l" "i" "]", reg_info.alt_name, reg_offset); | |||
465 | break; | |||
466 | } | |||
467 | } | |||
468 | } | |||
469 | s->Printf("DW_OP_bregx(reg=%" PRIu32"u" ",offset=%" PRIi64"l" "i" ")", reg_num, | |||
470 | reg_offset); | |||
471 | } break; | |||
472 | case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed | |||
473 | s->Printf("DW_OP_piece(0x%" PRIx64"l" "x" ")", m_data.GetULEB128(&offset)); | |||
474 | break; | |||
475 | case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved | |||
476 | s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset)); | |||
477 | break; | |||
478 | case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved | |||
479 | s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset)); | |||
480 | break; | |||
481 | case DW_OP_nop: | |||
482 | s->PutCString("DW_OP_nop"); | |||
483 | break; // 0x96 | |||
484 | case DW_OP_push_object_address: | |||
485 | s->PutCString("DW_OP_push_object_address"); | |||
486 | break; // 0x97 DWARF3 | |||
487 | case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE | |||
488 | s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset)); | |||
489 | break; | |||
490 | case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE | |||
491 | s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset)); | |||
492 | break; | |||
493 | case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE | |||
494 | s->Printf("DW_OP_call_ref(0x%8.8" PRIx64"l" "x" ")", m_data.GetAddress(&offset)); | |||
495 | break; | |||
496 | // case DW_OP_call_frame_cfa: s << "call_frame_cfa"; break; | |||
497 | // // 0x9c DWARF3 | |||
498 | // case DW_OP_bit_piece: // 0x9d DWARF3 2 | |||
499 | // s->Printf("DW_OP_bit_piece(0x%x, 0x%x)", | |||
500 | // m_data.GetULEB128(&offset), m_data.GetULEB128(&offset)); | |||
501 | // break; | |||
502 | // case DW_OP_lo_user: s->PutCString("DW_OP_lo_user"); break; | |||
503 | // // 0xe0 | |||
504 | // case DW_OP_hi_user: s->PutCString("DW_OP_hi_user"); break; | |||
505 | // // 0xff | |||
506 | // case DW_OP_APPLE_extern: | |||
507 | // s->Printf("DW_OP_APPLE_extern(%" PRIu64 ")", | |||
508 | // m_data.GetULEB128(&offset)); | |||
509 | // break; | |||
510 | // case DW_OP_APPLE_array_ref: | |||
511 | // s->PutCString("DW_OP_APPLE_array_ref"); | |||
512 | // break; | |||
513 | case DW_OP_form_tls_address: | |||
514 | s->PutCString("DW_OP_form_tls_address"); // 0x9b | |||
515 | break; | |||
516 | case DW_OP_GNU_addr_index: // 0xfb | |||
517 | s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64"l" "x" ")", | |||
518 | m_data.GetULEB128(&offset)); | |||
519 | break; | |||
520 | case DW_OP_GNU_const_index: // 0xfc | |||
521 | s->Printf("DW_OP_GNU_const_index(0x%" PRIx64"l" "x" ")", | |||
522 | m_data.GetULEB128(&offset)); | |||
523 | break; | |||
524 | case DW_OP_GNU_push_tls_address: | |||
525 | s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0 | |||
526 | break; | |||
527 | case DW_OP_APPLE_uninit0xF0: | |||
528 | s->PutCString("DW_OP_APPLE_uninit"); // 0xF0 | |||
529 | break; | |||
530 | // case DW_OP_APPLE_assign: // 0xF1 - pops value off and | |||
531 | // assigns it to second item on stack (2nd item must have | |||
532 | // assignable context) | |||
533 | // s->PutCString("DW_OP_APPLE_assign"); | |||
534 | // break; | |||
535 | // case DW_OP_APPLE_address_of: // 0xF2 - gets the address of | |||
536 | // the top stack item (top item must be a variable, or have | |||
537 | // value_type that is an address already) | |||
538 | // s->PutCString("DW_OP_APPLE_address_of"); | |||
539 | // break; | |||
540 | // case DW_OP_APPLE_value_of: // 0xF3 - pops the value off the | |||
541 | // stack and pushes the value of that object (top item must be a | |||
542 | // variable, or expression local) | |||
543 | // s->PutCString("DW_OP_APPLE_value_of"); | |||
544 | // break; | |||
545 | // case DW_OP_APPLE_deref_type: // 0xF4 - gets the address of | |||
546 | // the top stack item (top item must be a variable, or a clang | |||
547 | // type) | |||
548 | // s->PutCString("DW_OP_APPLE_deref_type"); | |||
549 | // break; | |||
550 | // case DW_OP_APPLE_expr_local: // 0xF5 - ULEB128 expression | |||
551 | // local index | |||
552 | // s->Printf("DW_OP_APPLE_expr_local(%" PRIu64 ")", | |||
553 | // m_data.GetULEB128(&offset)); | |||
554 | // break; | |||
555 | // case DW_OP_APPLE_constf: // 0xF6 - 1 byte float size, | |||
556 | // followed by constant float data | |||
557 | // { | |||
558 | // uint8_t float_length = m_data.GetU8(&offset); | |||
559 | // s->Printf("DW_OP_APPLE_constf(<%u> ", float_length); | |||
560 | // m_data.Dump(s, offset, eFormatHex, float_length, 1, | |||
561 | // UINT32_MAX, DW_INVALID_ADDRESS, 0, 0); | |||
562 | // s->PutChar(')'); | |||
563 | // // Consume the float data | |||
564 | // m_data.GetData(&offset, float_length); | |||
565 | // } | |||
566 | // break; | |||
567 | // case DW_OP_APPLE_scalar_cast: | |||
568 | // s->Printf("DW_OP_APPLE_scalar_cast(%s)", | |||
569 | // Scalar::GetValueTypeAsCString | |||
570 | // ((Scalar::Type)m_data.GetU8(&offset))); | |||
571 | // break; | |||
572 | // case DW_OP_APPLE_clang_cast: | |||
573 | // { | |||
574 | // clang::Type *clang_type = (clang::Type | |||
575 | // *)m_data.GetMaxU64(&offset, sizeof(void*)); | |||
576 | // s->Printf("DW_OP_APPLE_clang_cast(%p)", clang_type); | |||
577 | // } | |||
578 | // break; | |||
579 | // case DW_OP_APPLE_clear: | |||
580 | // s->PutCString("DW_OP_APPLE_clear"); | |||
581 | // break; | |||
582 | // case DW_OP_APPLE_error: // 0xFF - Stops expression | |||
583 | // evaluation and returns an error (no args) | |||
584 | // s->PutCString("DW_OP_APPLE_error"); | |||
585 | // break; | |||
586 | } | |||
587 | } | |||
588 | } | |||
589 | ||||
590 | void DWARFExpression::SetLocationListSlide(addr_t slide) { | |||
591 | m_loclist_slide = slide; | |||
592 | } | |||
593 | ||||
594 | int DWARFExpression::GetRegisterKind() { return m_reg_kind; } | |||
595 | ||||
596 | void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { | |||
597 | m_reg_kind = reg_kind; | |||
598 | } | |||
599 | ||||
600 | bool DWARFExpression::IsLocationList() const { | |||
601 | return m_loclist_slide != LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
602 | } | |||
603 | ||||
604 | void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level, | |||
605 | addr_t location_list_base_addr, | |||
606 | ABI *abi) const { | |||
607 | if (IsLocationList()) { | |||
608 | // We have a location list | |||
609 | lldb::offset_t offset = 0; | |||
610 | uint32_t count = 0; | |||
611 | addr_t curr_base_addr = location_list_base_addr; | |||
612 | while (m_data.ValidOffset(offset)) { | |||
613 | addr_t begin_addr_offset = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
614 | addr_t end_addr_offset = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
615 | if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, | |||
616 | begin_addr_offset, end_addr_offset)) | |||
617 | break; | |||
618 | ||||
619 | if (begin_addr_offset == 0 && end_addr_offset == 0) | |||
620 | break; | |||
621 | ||||
622 | if (begin_addr_offset < end_addr_offset) { | |||
623 | if (count > 0) | |||
624 | s->PutCString(", "); | |||
625 | VMRange addr_range(curr_base_addr + begin_addr_offset, | |||
626 | curr_base_addr + end_addr_offset); | |||
627 | addr_range.Dump(s, 0, 8); | |||
628 | s->PutChar('{'); | |||
629 | lldb::offset_t location_length = m_data.GetU16(&offset); | |||
630 | DumpLocation(s, offset, location_length, level, abi); | |||
631 | s->PutChar('}'); | |||
632 | offset += location_length; | |||
633 | } else { | |||
634 | if ((m_data.GetAddressByteSize() == 4 && | |||
635 | (begin_addr_offset == UINT32_MAX(4294967295U))) || | |||
636 | (m_data.GetAddressByteSize() == 8 && | |||
637 | (begin_addr_offset == UINT64_MAX(18446744073709551615UL)))) { | |||
638 | curr_base_addr = end_addr_offset + location_list_base_addr; | |||
639 | // We have a new base address | |||
640 | if (count > 0) | |||
641 | s->PutCString(", "); | |||
642 | *s << "base_addr = " << end_addr_offset; | |||
643 | } | |||
644 | } | |||
645 | ||||
646 | count++; | |||
647 | } | |||
648 | } else { | |||
649 | // We have a normal location that contains DW_OP location opcodes | |||
650 | DumpLocation(s, 0, m_data.GetByteSize(), level, abi); | |||
651 | } | |||
652 | } | |||
653 | ||||
654 | static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, | |||
655 | lldb::RegisterKind reg_kind, | |||
656 | uint32_t reg_num, Status *error_ptr, | |||
657 | Value &value) { | |||
658 | if (reg_ctx == NULL__null) { | |||
659 | if (error_ptr) | |||
660 | error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); | |||
661 | } else { | |||
662 | uint32_t native_reg = | |||
663 | reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); | |||
664 | if (native_reg == LLDB_INVALID_REGNUM(4294967295U)) { | |||
665 | if (error_ptr) | |||
666 | error_ptr->SetErrorStringWithFormat("Unable to convert register " | |||
667 | "kind=%u reg_num=%u to a native " | |||
668 | "register number.\n", | |||
669 | reg_kind, reg_num); | |||
670 | } else { | |||
671 | const RegisterInfo *reg_info = | |||
672 | reg_ctx->GetRegisterInfoAtIndex(native_reg); | |||
673 | RegisterValue reg_value; | |||
674 | if (reg_ctx->ReadRegister(reg_info, reg_value)) { | |||
675 | if (reg_value.GetScalarValue(value.GetScalar())) { | |||
676 | value.SetValueType(Value::eValueTypeScalar); | |||
677 | value.SetContext(Value::eContextTypeRegisterInfo, | |||
678 | const_cast<RegisterInfo *>(reg_info)); | |||
679 | if (error_ptr) | |||
680 | error_ptr->Clear(); | |||
681 | return true; | |||
682 | } else { | |||
683 | // If we get this error, then we need to implement a value buffer in | |||
684 | // the dwarf expression evaluation function... | |||
685 | if (error_ptr) | |||
686 | error_ptr->SetErrorStringWithFormat( | |||
687 | "register %s can't be converted to a scalar value", | |||
688 | reg_info->name); | |||
689 | } | |||
690 | } else { | |||
691 | if (error_ptr) | |||
692 | error_ptr->SetErrorStringWithFormat("register %s is not available", | |||
693 | reg_info->name); | |||
694 | } | |||
695 | } | |||
696 | } | |||
697 | return false; | |||
698 | } | |||
699 | ||||
700 | // bool | |||
701 | // DWARFExpression::LocationListContainsLoadAddress (Process* process, const | |||
702 | // Address &addr) const | |||
703 | //{ | |||
704 | // return LocationListContainsLoadAddress(process, | |||
705 | // addr.GetLoadAddress(process)); | |||
706 | //} | |||
707 | // | |||
708 | // bool | |||
709 | // DWARFExpression::LocationListContainsLoadAddress (Process* process, addr_t | |||
710 | // load_addr) const | |||
711 | //{ | |||
712 | // if (load_addr == LLDB_INVALID_ADDRESS) | |||
713 | // return false; | |||
714 | // | |||
715 | // if (IsLocationList()) | |||
716 | // { | |||
717 | // lldb::offset_t offset = 0; | |||
718 | // | |||
719 | // addr_t loc_list_base_addr = m_loclist_slide.GetLoadAddress(process); | |||
720 | // | |||
721 | // if (loc_list_base_addr == LLDB_INVALID_ADDRESS) | |||
722 | // return false; | |||
723 | // | |||
724 | // while (m_data.ValidOffset(offset)) | |||
725 | // { | |||
726 | // // We need to figure out what the value is for the location. | |||
727 | // addr_t lo_pc = m_data.GetAddress(&offset); | |||
728 | // addr_t hi_pc = m_data.GetAddress(&offset); | |||
729 | // if (lo_pc == 0 && hi_pc == 0) | |||
730 | // break; | |||
731 | // else | |||
732 | // { | |||
733 | // lo_pc += loc_list_base_addr; | |||
734 | // hi_pc += loc_list_base_addr; | |||
735 | // | |||
736 | // if (lo_pc <= load_addr && load_addr < hi_pc) | |||
737 | // return true; | |||
738 | // | |||
739 | // offset += m_data.GetU16(&offset); | |||
740 | // } | |||
741 | // } | |||
742 | // } | |||
743 | // return false; | |||
744 | //} | |||
745 | ||||
746 | static offset_t GetOpcodeDataSize(const DataExtractor &data, | |||
747 | const lldb::offset_t data_offset, | |||
748 | const uint8_t op) { | |||
749 | lldb::offset_t offset = data_offset; | |||
750 | switch (op) { | |||
751 | case DW_OP_addr: | |||
752 | case DW_OP_call_ref: // 0x9a 1 address sized offset of DIE (DWARF3) | |||
753 | return data.GetAddressByteSize(); | |||
754 | ||||
755 | // Opcodes with no arguments | |||
756 | case DW_OP_deref: // 0x06 | |||
757 | case DW_OP_dup: // 0x12 | |||
758 | case DW_OP_drop: // 0x13 | |||
759 | case DW_OP_over: // 0x14 | |||
760 | case DW_OP_swap: // 0x16 | |||
761 | case DW_OP_rot: // 0x17 | |||
762 | case DW_OP_xderef: // 0x18 | |||
763 | case DW_OP_abs: // 0x19 | |||
764 | case DW_OP_and: // 0x1a | |||
765 | case DW_OP_div: // 0x1b | |||
766 | case DW_OP_minus: // 0x1c | |||
767 | case DW_OP_mod: // 0x1d | |||
768 | case DW_OP_mul: // 0x1e | |||
769 | case DW_OP_neg: // 0x1f | |||
770 | case DW_OP_not: // 0x20 | |||
771 | case DW_OP_or: // 0x21 | |||
772 | case DW_OP_plus: // 0x22 | |||
773 | case DW_OP_shl: // 0x24 | |||
774 | case DW_OP_shr: // 0x25 | |||
775 | case DW_OP_shra: // 0x26 | |||
776 | case DW_OP_xor: // 0x27 | |||
777 | case DW_OP_eq: // 0x29 | |||
778 | case DW_OP_ge: // 0x2a | |||
779 | case DW_OP_gt: // 0x2b | |||
780 | case DW_OP_le: // 0x2c | |||
781 | case DW_OP_lt: // 0x2d | |||
782 | case DW_OP_ne: // 0x2e | |||
783 | case DW_OP_lit0: // 0x30 | |||
784 | case DW_OP_lit1: // 0x31 | |||
785 | case DW_OP_lit2: // 0x32 | |||
786 | case DW_OP_lit3: // 0x33 | |||
787 | case DW_OP_lit4: // 0x34 | |||
788 | case DW_OP_lit5: // 0x35 | |||
789 | case DW_OP_lit6: // 0x36 | |||
790 | case DW_OP_lit7: // 0x37 | |||
791 | case DW_OP_lit8: // 0x38 | |||
792 | case DW_OP_lit9: // 0x39 | |||
793 | case DW_OP_lit10: // 0x3A | |||
794 | case DW_OP_lit11: // 0x3B | |||
795 | case DW_OP_lit12: // 0x3C | |||
796 | case DW_OP_lit13: // 0x3D | |||
797 | case DW_OP_lit14: // 0x3E | |||
798 | case DW_OP_lit15: // 0x3F | |||
799 | case DW_OP_lit16: // 0x40 | |||
800 | case DW_OP_lit17: // 0x41 | |||
801 | case DW_OP_lit18: // 0x42 | |||
802 | case DW_OP_lit19: // 0x43 | |||
803 | case DW_OP_lit20: // 0x44 | |||
804 | case DW_OP_lit21: // 0x45 | |||
805 | case DW_OP_lit22: // 0x46 | |||
806 | case DW_OP_lit23: // 0x47 | |||
807 | case DW_OP_lit24: // 0x48 | |||
808 | case DW_OP_lit25: // 0x49 | |||
809 | case DW_OP_lit26: // 0x4A | |||
810 | case DW_OP_lit27: // 0x4B | |||
811 | case DW_OP_lit28: // 0x4C | |||
812 | case DW_OP_lit29: // 0x4D | |||
813 | case DW_OP_lit30: // 0x4E | |||
814 | case DW_OP_lit31: // 0x4f | |||
815 | case DW_OP_reg0: // 0x50 | |||
816 | case DW_OP_reg1: // 0x51 | |||
817 | case DW_OP_reg2: // 0x52 | |||
818 | case DW_OP_reg3: // 0x53 | |||
819 | case DW_OP_reg4: // 0x54 | |||
820 | case DW_OP_reg5: // 0x55 | |||
821 | case DW_OP_reg6: // 0x56 | |||
822 | case DW_OP_reg7: // 0x57 | |||
823 | case DW_OP_reg8: // 0x58 | |||
824 | case DW_OP_reg9: // 0x59 | |||
825 | case DW_OP_reg10: // 0x5A | |||
826 | case DW_OP_reg11: // 0x5B | |||
827 | case DW_OP_reg12: // 0x5C | |||
828 | case DW_OP_reg13: // 0x5D | |||
829 | case DW_OP_reg14: // 0x5E | |||
830 | case DW_OP_reg15: // 0x5F | |||
831 | case DW_OP_reg16: // 0x60 | |||
832 | case DW_OP_reg17: // 0x61 | |||
833 | case DW_OP_reg18: // 0x62 | |||
834 | case DW_OP_reg19: // 0x63 | |||
835 | case DW_OP_reg20: // 0x64 | |||
836 | case DW_OP_reg21: // 0x65 | |||
837 | case DW_OP_reg22: // 0x66 | |||
838 | case DW_OP_reg23: // 0x67 | |||
839 | case DW_OP_reg24: // 0x68 | |||
840 | case DW_OP_reg25: // 0x69 | |||
841 | case DW_OP_reg26: // 0x6A | |||
842 | case DW_OP_reg27: // 0x6B | |||
843 | case DW_OP_reg28: // 0x6C | |||
844 | case DW_OP_reg29: // 0x6D | |||
845 | case DW_OP_reg30: // 0x6E | |||
846 | case DW_OP_reg31: // 0x6F | |||
847 | case DW_OP_nop: // 0x96 | |||
848 | case DW_OP_push_object_address: // 0x97 DWARF3 | |||
849 | case DW_OP_form_tls_address: // 0x9b DWARF3 | |||
850 | case DW_OP_call_frame_cfa: // 0x9c DWARF3 | |||
851 | case DW_OP_stack_value: // 0x9f DWARF4 | |||
852 | case DW_OP_GNU_push_tls_address: // 0xe0 GNU extension | |||
853 | return 0; | |||
854 | ||||
855 | // Opcodes with a single 1 byte arguments | |||
856 | case DW_OP_const1u: // 0x08 1 1-byte constant | |||
857 | case DW_OP_const1s: // 0x09 1 1-byte constant | |||
858 | case DW_OP_pick: // 0x15 1 1-byte stack index | |||
859 | case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved | |||
860 | case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved | |||
861 | return 1; | |||
862 | ||||
863 | // Opcodes with a single 2 byte arguments | |||
864 | case DW_OP_const2u: // 0x0a 1 2-byte constant | |||
865 | case DW_OP_const2s: // 0x0b 1 2-byte constant | |||
866 | case DW_OP_skip: // 0x2f 1 signed 2-byte constant | |||
867 | case DW_OP_bra: // 0x28 1 signed 2-byte constant | |||
868 | case DW_OP_call2: // 0x98 1 2-byte offset of DIE (DWARF3) | |||
869 | return 2; | |||
870 | ||||
871 | // Opcodes with a single 4 byte arguments | |||
872 | case DW_OP_const4u: // 0x0c 1 4-byte constant | |||
873 | case DW_OP_const4s: // 0x0d 1 4-byte constant | |||
874 | case DW_OP_call4: // 0x99 1 4-byte offset of DIE (DWARF3) | |||
875 | return 4; | |||
876 | ||||
877 | // Opcodes with a single 8 byte arguments | |||
878 | case DW_OP_const8u: // 0x0e 1 8-byte constant | |||
879 | case DW_OP_const8s: // 0x0f 1 8-byte constant | |||
880 | return 8; | |||
881 | ||||
882 | // All opcodes that have a single ULEB (signed or unsigned) argument | |||
883 | case DW_OP_constu: // 0x10 1 ULEB128 constant | |||
884 | case DW_OP_consts: // 0x11 1 SLEB128 constant | |||
885 | case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend | |||
886 | case DW_OP_breg0: // 0x70 1 ULEB128 register | |||
887 | case DW_OP_breg1: // 0x71 1 ULEB128 register | |||
888 | case DW_OP_breg2: // 0x72 1 ULEB128 register | |||
889 | case DW_OP_breg3: // 0x73 1 ULEB128 register | |||
890 | case DW_OP_breg4: // 0x74 1 ULEB128 register | |||
891 | case DW_OP_breg5: // 0x75 1 ULEB128 register | |||
892 | case DW_OP_breg6: // 0x76 1 ULEB128 register | |||
893 | case DW_OP_breg7: // 0x77 1 ULEB128 register | |||
894 | case DW_OP_breg8: // 0x78 1 ULEB128 register | |||
895 | case DW_OP_breg9: // 0x79 1 ULEB128 register | |||
896 | case DW_OP_breg10: // 0x7a 1 ULEB128 register | |||
897 | case DW_OP_breg11: // 0x7b 1 ULEB128 register | |||
898 | case DW_OP_breg12: // 0x7c 1 ULEB128 register | |||
899 | case DW_OP_breg13: // 0x7d 1 ULEB128 register | |||
900 | case DW_OP_breg14: // 0x7e 1 ULEB128 register | |||
901 | case DW_OP_breg15: // 0x7f 1 ULEB128 register | |||
902 | case DW_OP_breg16: // 0x80 1 ULEB128 register | |||
903 | case DW_OP_breg17: // 0x81 1 ULEB128 register | |||
904 | case DW_OP_breg18: // 0x82 1 ULEB128 register | |||
905 | case DW_OP_breg19: // 0x83 1 ULEB128 register | |||
906 | case DW_OP_breg20: // 0x84 1 ULEB128 register | |||
907 | case DW_OP_breg21: // 0x85 1 ULEB128 register | |||
908 | case DW_OP_breg22: // 0x86 1 ULEB128 register | |||
909 | case DW_OP_breg23: // 0x87 1 ULEB128 register | |||
910 | case DW_OP_breg24: // 0x88 1 ULEB128 register | |||
911 | case DW_OP_breg25: // 0x89 1 ULEB128 register | |||
912 | case DW_OP_breg26: // 0x8a 1 ULEB128 register | |||
913 | case DW_OP_breg27: // 0x8b 1 ULEB128 register | |||
914 | case DW_OP_breg28: // 0x8c 1 ULEB128 register | |||
915 | case DW_OP_breg29: // 0x8d 1 ULEB128 register | |||
916 | case DW_OP_breg30: // 0x8e 1 ULEB128 register | |||
917 | case DW_OP_breg31: // 0x8f 1 ULEB128 register | |||
918 | case DW_OP_regx: // 0x90 1 ULEB128 register | |||
919 | case DW_OP_fbreg: // 0x91 1 SLEB128 offset | |||
920 | case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed | |||
921 | case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index | |||
922 | case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index | |||
923 | data.Skip_LEB128(&offset); | |||
924 | return offset - data_offset; | |||
925 | ||||
926 | // All opcodes that have a 2 ULEB (signed or unsigned) arguments | |||
927 | case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset | |||
928 | case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); | |||
929 | data.Skip_LEB128(&offset); | |||
930 | data.Skip_LEB128(&offset); | |||
931 | return offset - data_offset; | |||
932 | ||||
933 | case DW_OP_implicit_value: // 0x9e ULEB128 size followed by block of that size | |||
934 | // (DWARF4) | |||
935 | { | |||
936 | uint64_t block_len = data.Skip_LEB128(&offset); | |||
937 | offset += block_len; | |||
938 | return offset - data_offset; | |||
939 | } | |||
940 | ||||
941 | default: | |||
942 | break; | |||
943 | } | |||
944 | return LLDB_INVALID_OFFSET(18446744073709551615UL); | |||
945 | } | |||
946 | ||||
947 | lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx, | |||
948 | bool &error) const { | |||
949 | error = false; | |||
950 | if (IsLocationList()) | |||
951 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
952 | lldb::offset_t offset = 0; | |||
953 | uint32_t curr_op_addr_idx = 0; | |||
954 | while (m_data.ValidOffset(offset)) { | |||
955 | const uint8_t op = m_data.GetU8(&offset); | |||
956 | ||||
957 | if (op == DW_OP_addr) { | |||
958 | const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); | |||
959 | if (curr_op_addr_idx == op_addr_idx) | |||
960 | return op_file_addr; | |||
961 | else | |||
962 | ++curr_op_addr_idx; | |||
963 | } else if (op == DW_OP_GNU_addr_index) { | |||
964 | uint64_t index = m_data.GetULEB128(&offset); | |||
965 | if (curr_op_addr_idx == op_addr_idx) { | |||
966 | if (!m_dwarf_cu) { | |||
967 | error = true; | |||
968 | break; | |||
969 | } | |||
970 | ||||
971 | return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); | |||
972 | } else | |||
973 | ++curr_op_addr_idx; | |||
974 | } else { | |||
975 | const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); | |||
976 | if (op_arg_size == LLDB_INVALID_OFFSET(18446744073709551615UL)) { | |||
977 | error = true; | |||
978 | break; | |||
979 | } | |||
980 | offset += op_arg_size; | |||
981 | } | |||
982 | } | |||
983 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
984 | } | |||
985 | ||||
986 | bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { | |||
987 | if (IsLocationList()) | |||
988 | return false; | |||
989 | lldb::offset_t offset = 0; | |||
990 | while (m_data.ValidOffset(offset)) { | |||
991 | const uint8_t op = m_data.GetU8(&offset); | |||
992 | ||||
993 | if (op == DW_OP_addr) { | |||
994 | const uint32_t addr_byte_size = m_data.GetAddressByteSize(); | |||
995 | // We have to make a copy of the data as we don't know if this data is | |||
996 | // from a read only memory mapped buffer, so we duplicate all of the data | |||
997 | // first, then modify it, and if all goes well, we then replace the data | |||
998 | // for this expression | |||
999 | ||||
1000 | // So first we copy the data into a heap buffer | |||
1001 | std::unique_ptr<DataBufferHeap> head_data_ap( | |||
1002 | new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); | |||
1003 | ||||
1004 | // Make en encoder so we can write the address into the buffer using the | |||
1005 | // correct byte order (endianness) | |||
1006 | DataEncoder encoder(head_data_ap->GetBytes(), head_data_ap->GetByteSize(), | |||
1007 | m_data.GetByteOrder(), addr_byte_size); | |||
1008 | ||||
1009 | // Replace the address in the new buffer | |||
1010 | if (encoder.PutMaxU64(offset, addr_byte_size, file_addr) == UINT32_MAX(4294967295U)) | |||
1011 | return false; | |||
1012 | ||||
1013 | // All went well, so now we can reset the data using a shared pointer to | |||
1014 | // the heap data so "m_data" will now correctly manage the heap data. | |||
1015 | m_data.SetData(DataBufferSP(head_data_ap.release())); | |||
1016 | return true; | |||
1017 | } else { | |||
1018 | const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); | |||
1019 | if (op_arg_size == LLDB_INVALID_OFFSET(18446744073709551615UL)) | |||
1020 | break; | |||
1021 | offset += op_arg_size; | |||
1022 | } | |||
1023 | } | |||
1024 | return false; | |||
1025 | } | |||
1026 | ||||
1027 | bool DWARFExpression::ContainsThreadLocalStorage() const { | |||
1028 | // We are assuming for now that any thread local variable will not have a | |||
1029 | // location list. This has been true for all thread local variables we have | |||
1030 | // seen so far produced by any compiler. | |||
1031 | if (IsLocationList()) | |||
1032 | return false; | |||
1033 | lldb::offset_t offset = 0; | |||
1034 | while (m_data.ValidOffset(offset)) { | |||
1035 | const uint8_t op = m_data.GetU8(&offset); | |||
1036 | ||||
1037 | if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) | |||
1038 | return true; | |||
1039 | const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); | |||
1040 | if (op_arg_size == LLDB_INVALID_OFFSET(18446744073709551615UL)) | |||
1041 | return false; | |||
1042 | else | |||
1043 | offset += op_arg_size; | |||
1044 | } | |||
1045 | return false; | |||
1046 | } | |||
1047 | bool DWARFExpression::LinkThreadLocalStorage( | |||
1048 | lldb::ModuleSP new_module_sp, | |||
1049 | std::function<lldb::addr_t(lldb::addr_t file_addr)> const | |||
1050 | &link_address_callback) { | |||
1051 | // We are assuming for now that any thread local variable will not have a | |||
1052 | // location list. This has been true for all thread local variables we have | |||
1053 | // seen so far produced by any compiler. | |||
1054 | if (IsLocationList()) | |||
1055 | return false; | |||
1056 | ||||
1057 | const uint32_t addr_byte_size = m_data.GetAddressByteSize(); | |||
1058 | // We have to make a copy of the data as we don't know if this data is from a | |||
1059 | // read only memory mapped buffer, so we duplicate all of the data first, | |||
1060 | // then modify it, and if all goes well, we then replace the data for this | |||
1061 | // expression | |||
1062 | ||||
1063 | // So first we copy the data into a heap buffer | |||
1064 | std::shared_ptr<DataBufferHeap> heap_data_sp( | |||
1065 | new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); | |||
1066 | ||||
1067 | // Make en encoder so we can write the address into the buffer using the | |||
1068 | // correct byte order (endianness) | |||
1069 | DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), | |||
1070 | m_data.GetByteOrder(), addr_byte_size); | |||
1071 | ||||
1072 | lldb::offset_t offset = 0; | |||
1073 | lldb::offset_t const_offset = 0; | |||
1074 | lldb::addr_t const_value = 0; | |||
1075 | size_t const_byte_size = 0; | |||
1076 | while (m_data.ValidOffset(offset)) { | |||
1077 | const uint8_t op = m_data.GetU8(&offset); | |||
1078 | ||||
1079 | bool decoded_data = false; | |||
1080 | switch (op) { | |||
1081 | case DW_OP_const4u: | |||
1082 | // Remember the const offset in case we later have a | |||
1083 | // DW_OP_form_tls_address or DW_OP_GNU_push_tls_address | |||
1084 | const_offset = offset; | |||
1085 | const_value = m_data.GetU32(&offset); | |||
1086 | decoded_data = true; | |||
1087 | const_byte_size = 4; | |||
1088 | break; | |||
1089 | ||||
1090 | case DW_OP_const8u: | |||
1091 | // Remember the const offset in case we later have a | |||
1092 | // DW_OP_form_tls_address or DW_OP_GNU_push_tls_address | |||
1093 | const_offset = offset; | |||
1094 | const_value = m_data.GetU64(&offset); | |||
1095 | decoded_data = true; | |||
1096 | const_byte_size = 8; | |||
1097 | break; | |||
1098 | ||||
1099 | case DW_OP_form_tls_address: | |||
1100 | case DW_OP_GNU_push_tls_address: | |||
1101 | // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded | |||
1102 | // by a file address on the stack. We assume that DW_OP_const4u or | |||
1103 | // DW_OP_const8u is used for these values, and we check that the last | |||
1104 | // opcode we got before either of these was DW_OP_const4u or | |||
1105 | // DW_OP_const8u. If so, then we can link the value accodingly. For | |||
1106 | // Darwin, the value in the DW_OP_const4u or DW_OP_const8u is the file | |||
1107 | // address of a structure that contains a function pointer, the pthread | |||
1108 | // key and the offset into the data pointed to by the pthread key. So we | |||
1109 | // must link this address and also set the module of this expression to | |||
1110 | // the new_module_sp so we can resolve the file address correctly | |||
1111 | if (const_byte_size > 0) { | |||
1112 | lldb::addr_t linked_file_addr = link_address_callback(const_value); | |||
1113 | if (linked_file_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1114 | return false; | |||
1115 | // Replace the address in the new buffer | |||
1116 | if (encoder.PutMaxU64(const_offset, const_byte_size, | |||
1117 | linked_file_addr) == UINT32_MAX(4294967295U)) | |||
1118 | return false; | |||
1119 | } | |||
1120 | break; | |||
1121 | ||||
1122 | default: | |||
1123 | const_offset = 0; | |||
1124 | const_value = 0; | |||
1125 | const_byte_size = 0; | |||
1126 | break; | |||
1127 | } | |||
1128 | ||||
1129 | if (!decoded_data) { | |||
1130 | const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); | |||
1131 | if (op_arg_size == LLDB_INVALID_OFFSET(18446744073709551615UL)) | |||
1132 | return false; | |||
1133 | else | |||
1134 | offset += op_arg_size; | |||
1135 | } | |||
1136 | } | |||
1137 | ||||
1138 | // If we linked the TLS address correctly, update the module so that when the | |||
1139 | // expression is evaluated it can resolve the file address to a load address | |||
1140 | // and read the | |||
1141 | // TLS data | |||
1142 | m_module_wp = new_module_sp; | |||
1143 | m_data.SetData(heap_data_sp); | |||
1144 | return true; | |||
1145 | } | |||
1146 | ||||
1147 | bool DWARFExpression::LocationListContainsAddress( | |||
1148 | lldb::addr_t loclist_base_addr, lldb::addr_t addr) const { | |||
1149 | if (addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1150 | return false; | |||
1151 | ||||
1152 | if (IsLocationList()) { | |||
1153 | lldb::offset_t offset = 0; | |||
1154 | ||||
1155 | if (loclist_base_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1156 | return false; | |||
1157 | ||||
1158 | while (m_data.ValidOffset(offset)) { | |||
1159 | // We need to figure out what the value is for the location. | |||
1160 | addr_t lo_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1161 | addr_t hi_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1162 | if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, | |||
1163 | hi_pc)) | |||
1164 | break; | |||
1165 | ||||
1166 | if (lo_pc == 0 && hi_pc == 0) | |||
1167 | break; | |||
1168 | ||||
1169 | lo_pc += loclist_base_addr - m_loclist_slide; | |||
1170 | hi_pc += loclist_base_addr - m_loclist_slide; | |||
1171 | ||||
1172 | if (lo_pc <= addr && addr < hi_pc) | |||
1173 | return true; | |||
1174 | ||||
1175 | offset += m_data.GetU16(&offset); | |||
1176 | } | |||
1177 | } | |||
1178 | return false; | |||
1179 | } | |||
1180 | ||||
1181 | bool DWARFExpression::GetLocation(addr_t base_addr, addr_t pc, | |||
1182 | lldb::offset_t &offset, | |||
1183 | lldb::offset_t &length) { | |||
1184 | offset = 0; | |||
1185 | if (!IsLocationList()) { | |||
1186 | length = m_data.GetByteSize(); | |||
1187 | return true; | |||
1188 | } | |||
1189 | ||||
1190 | if (base_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL) && pc != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1191 | addr_t curr_base_addr = base_addr; | |||
1192 | ||||
1193 | while (m_data.ValidOffset(offset)) { | |||
1194 | // We need to figure out what the value is for the location. | |||
1195 | addr_t lo_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1196 | addr_t hi_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1197 | if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, | |||
1198 | hi_pc)) | |||
1199 | break; | |||
1200 | ||||
1201 | if (lo_pc == 0 && hi_pc == 0) | |||
1202 | break; | |||
1203 | ||||
1204 | lo_pc += curr_base_addr - m_loclist_slide; | |||
1205 | hi_pc += curr_base_addr - m_loclist_slide; | |||
1206 | ||||
1207 | length = m_data.GetU16(&offset); | |||
1208 | ||||
1209 | if (length > 0 && lo_pc <= pc && pc < hi_pc) | |||
1210 | return true; | |||
1211 | ||||
1212 | offset += length; | |||
1213 | } | |||
1214 | } | |||
1215 | offset = LLDB_INVALID_OFFSET(18446744073709551615UL); | |||
1216 | length = 0; | |||
1217 | return false; | |||
1218 | } | |||
1219 | ||||
1220 | bool DWARFExpression::DumpLocationForAddress(Stream *s, | |||
1221 | lldb::DescriptionLevel level, | |||
1222 | addr_t base_addr, addr_t address, | |||
1223 | ABI *abi) { | |||
1224 | lldb::offset_t offset = 0; | |||
1225 | lldb::offset_t length = 0; | |||
1226 | ||||
1227 | if (GetLocation(base_addr, address, offset, length)) { | |||
1228 | if (length > 0) { | |||
1229 | DumpLocation(s, offset, length, level, abi); | |||
1230 | return true; | |||
1231 | } | |||
1232 | } | |||
1233 | return false; | |||
1234 | } | |||
1235 | ||||
1236 | bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope, | |||
1237 | lldb::addr_t loclist_base_load_addr, | |||
1238 | const Value *initial_value_ptr, | |||
1239 | const Value *object_address_ptr, Value &result, | |||
1240 | Status *error_ptr) const { | |||
1241 | ExecutionContext exe_ctx(exe_scope); | |||
1242 | return Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, initial_value_ptr, | |||
1243 | object_address_ptr, result, error_ptr); | |||
1244 | } | |||
1245 | ||||
1246 | bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, | |||
1247 | RegisterContext *reg_ctx, | |||
1248 | lldb::addr_t loclist_base_load_addr, | |||
1249 | const Value *initial_value_ptr, | |||
1250 | const Value *object_address_ptr, Value &result, | |||
1251 | Status *error_ptr) const { | |||
1252 | ModuleSP module_sp = m_module_wp.lock(); | |||
1253 | ||||
1254 | if (IsLocationList()) { | |||
1255 | lldb::offset_t offset = 0; | |||
1256 | addr_t pc; | |||
1257 | StackFrame *frame = NULL__null; | |||
1258 | if (reg_ctx) | |||
1259 | pc = reg_ctx->GetPC(); | |||
1260 | else { | |||
1261 | frame = exe_ctx->GetFramePtr(); | |||
1262 | if (!frame) | |||
1263 | return false; | |||
1264 | RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); | |||
1265 | if (!reg_ctx_sp) | |||
1266 | return false; | |||
1267 | pc = reg_ctx_sp->GetPC(); | |||
1268 | } | |||
1269 | ||||
1270 | if (loclist_base_load_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1271 | if (pc == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1272 | if (error_ptr) | |||
1273 | error_ptr->SetErrorString("Invalid PC in frame."); | |||
1274 | return false; | |||
1275 | } | |||
1276 | ||||
1277 | addr_t curr_loclist_base_load_addr = loclist_base_load_addr; | |||
1278 | ||||
1279 | while (m_data.ValidOffset(offset)) { | |||
1280 | // We need to figure out what the value is for the location. | |||
1281 | addr_t lo_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1282 | addr_t hi_pc = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1283 | if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, | |||
1284 | lo_pc, hi_pc)) | |||
1285 | break; | |||
1286 | ||||
1287 | if (lo_pc == 0 && hi_pc == 0) | |||
1288 | break; | |||
1289 | ||||
1290 | lo_pc += curr_loclist_base_load_addr - m_loclist_slide; | |||
1291 | hi_pc += curr_loclist_base_load_addr - m_loclist_slide; | |||
1292 | ||||
1293 | uint16_t length = m_data.GetU16(&offset); | |||
1294 | ||||
1295 | if (length > 0 && lo_pc <= pc && pc < hi_pc) { | |||
1296 | return DWARFExpression::Evaluate( | |||
1297 | exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, offset, length, | |||
1298 | m_reg_kind, initial_value_ptr, object_address_ptr, result, | |||
1299 | error_ptr); | |||
1300 | } | |||
1301 | offset += length; | |||
1302 | } | |||
1303 | } | |||
1304 | if (error_ptr) | |||
1305 | error_ptr->SetErrorString("variable not available"); | |||
1306 | return false; | |||
1307 | } | |||
1308 | ||||
1309 | // Not a location list, just a single expression. | |||
1310 | return DWARFExpression::Evaluate( | |||
1311 | exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, m_data.GetByteSize(), | |||
1312 | m_reg_kind, initial_value_ptr, object_address_ptr, result, error_ptr); | |||
1313 | } | |||
1314 | ||||
1315 | bool DWARFExpression::Evaluate( | |||
1316 | ExecutionContext *exe_ctx, RegisterContext *reg_ctx, | |||
1317 | lldb::ModuleSP module_sp, const DataExtractor &opcodes, | |||
1318 | DWARFUnit *dwarf_cu, const lldb::offset_t opcodes_offset, | |||
1319 | const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, | |||
1320 | const Value *initial_value_ptr, const Value *object_address_ptr, | |||
1321 | Value &result, Status *error_ptr) { | |||
1322 | ||||
1323 | if (opcodes_length == 0) { | |||
| ||||
1324 | if (error_ptr) | |||
1325 | error_ptr->SetErrorString( | |||
1326 | "no location, value may have been optimized out"); | |||
1327 | return false; | |||
1328 | } | |||
1329 | std::vector<Value> stack; | |||
1330 | ||||
1331 | Process *process = NULL__null; | |||
1332 | StackFrame *frame = NULL__null; | |||
1333 | ||||
1334 | if (exe_ctx) { | |||
1335 | process = exe_ctx->GetProcessPtr(); | |||
1336 | frame = exe_ctx->GetFramePtr(); | |||
1337 | } | |||
1338 | if (reg_ctx == NULL__null && frame) | |||
1339 | reg_ctx = frame->GetRegisterContext().get(); | |||
1340 | ||||
1341 | if (initial_value_ptr) | |||
1342 | stack.push_back(*initial_value_ptr); | |||
1343 | ||||
1344 | lldb::offset_t offset = opcodes_offset; | |||
1345 | const lldb::offset_t end_offset = opcodes_offset + opcodes_length; | |||
1346 | Value tmp; | |||
1347 | uint32_t reg_num; | |||
1348 | ||||
1349 | /// Insertion point for evaluating multi-piece expression. | |||
1350 | uint64_t op_piece_offset = 0; | |||
1351 | Value pieces; // Used for DW_OP_piece | |||
1352 | ||||
1353 | // Make sure all of the data is available in opcodes. | |||
1354 | if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length)) { | |||
1355 | if (error_ptr) | |||
1356 | error_ptr->SetErrorString( | |||
1357 | "invalid offset and/or length for opcodes buffer."); | |||
1358 | return false; | |||
1359 | } | |||
1360 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
1361 | ||||
1362 | while (opcodes.ValidOffset(offset) && offset < end_offset) { | |||
1363 | const lldb::offset_t op_offset = offset; | |||
1364 | const uint8_t op = opcodes.GetU8(&offset); | |||
1365 | ||||
1366 | if (log && log->GetVerbose()) { | |||
1367 | size_t count = stack.size(); | |||
1368 | log->Printf("Stack before operation has %" PRIu64"l" "u" " values:", | |||
1369 | (uint64_t)count); | |||
1370 | for (size_t i = 0; i < count; ++i) { | |||
1371 | StreamString new_value; | |||
1372 | new_value.Printf("[%" PRIu64"l" "u" "]", (uint64_t)i); | |||
1373 | stack[i].Dump(&new_value); | |||
1374 | log->Printf(" %s", new_value.GetData()); | |||
1375 | } | |||
1376 | log->Printf("0x%8.8" PRIx64"l" "x" ": %s", op_offset, DW_OP_value_to_name(op)); | |||
1377 | } | |||
1378 | ||||
1379 | switch (op) { | |||
1380 | //---------------------------------------------------------------------- | |||
1381 | // The DW_OP_addr operation has a single operand that encodes a machine | |||
1382 | // address and whose size is the size of an address on the target machine. | |||
1383 | //---------------------------------------------------------------------- | |||
1384 | case DW_OP_addr: | |||
1385 | stack.push_back(Scalar(opcodes.GetAddress(&offset))); | |||
1386 | stack.back().SetValueType(Value::eValueTypeFileAddress); | |||
1387 | // Convert the file address to a load address, so subsequent | |||
1388 | // DWARF operators can operate on it. | |||
1389 | if (frame) | |||
1390 | stack.back().ConvertToLoadAddress(module_sp.get(), | |||
1391 | frame->CalculateTarget().get()); | |||
1392 | break; | |||
1393 | ||||
1394 | //---------------------------------------------------------------------- | |||
1395 | // The DW_OP_addr_sect_offset4 is used for any location expressions in | |||
1396 | // shared libraries that have a location like: | |||
1397 | // DW_OP_addr(0x1000) | |||
1398 | // If this address resides in a shared library, then this virtual address | |||
1399 | // won't make sense when it is evaluated in the context of a running | |||
1400 | // process where shared libraries have been slid. To account for this, this | |||
1401 | // new address type where we can store the section pointer and a 4 byte | |||
1402 | // offset. | |||
1403 | //---------------------------------------------------------------------- | |||
1404 | // case DW_OP_addr_sect_offset4: | |||
1405 | // { | |||
1406 | // result_type = eResultTypeFileAddress; | |||
1407 | // lldb::Section *sect = (lldb::Section | |||
1408 | // *)opcodes.GetMaxU64(&offset, sizeof(void *)); | |||
1409 | // lldb::addr_t sect_offset = opcodes.GetU32(&offset); | |||
1410 | // | |||
1411 | // Address so_addr (sect, sect_offset); | |||
1412 | // lldb::addr_t load_addr = so_addr.GetLoadAddress(); | |||
1413 | // if (load_addr != LLDB_INVALID_ADDRESS) | |||
1414 | // { | |||
1415 | // // We successfully resolve a file address to a load | |||
1416 | // // address. | |||
1417 | // stack.push_back(load_addr); | |||
1418 | // break; | |||
1419 | // } | |||
1420 | // else | |||
1421 | // { | |||
1422 | // // We were able | |||
1423 | // if (error_ptr) | |||
1424 | // error_ptr->SetErrorStringWithFormat ("Section %s in | |||
1425 | // %s is not currently loaded.\n", | |||
1426 | // sect->GetName().AsCString(), | |||
1427 | // sect->GetModule()->GetFileSpec().GetFilename().AsCString()); | |||
1428 | // return false; | |||
1429 | // } | |||
1430 | // } | |||
1431 | // break; | |||
1432 | ||||
1433 | //---------------------------------------------------------------------- | |||
1434 | // OPCODE: DW_OP_deref | |||
1435 | // OPERANDS: none | |||
1436 | // DESCRIPTION: Pops the top stack entry and treats it as an address. | |||
1437 | // The value retrieved from that address is pushed. The size of the data | |||
1438 | // retrieved from the dereferenced address is the size of an address on the | |||
1439 | // target machine. | |||
1440 | //---------------------------------------------------------------------- | |||
1441 | case DW_OP_deref: { | |||
1442 | if (stack.empty()) { | |||
1443 | if (error_ptr) | |||
1444 | error_ptr->SetErrorString("Expression stack empty for DW_OP_deref."); | |||
1445 | return false; | |||
1446 | } | |||
1447 | Value::ValueType value_type = stack.back().GetValueType(); | |||
1448 | switch (value_type) { | |||
1449 | case Value::eValueTypeHostAddress: { | |||
1450 | void *src = (void *)stack.back().GetScalar().ULongLong(); | |||
1451 | intptr_t ptr; | |||
1452 | ::memcpy(&ptr, src, sizeof(void *)); | |||
1453 | stack.back().GetScalar() = ptr; | |||
1454 | stack.back().ClearContext(); | |||
1455 | } break; | |||
1456 | case Value::eValueTypeFileAddress: { | |||
1457 | auto file_addr = stack.back().GetScalar().ULongLong( | |||
1458 | LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
1459 | if (!module_sp) { | |||
1460 | if (error_ptr) | |||
1461 | error_ptr->SetErrorStringWithFormat( | |||
1462 | "need module to resolve file address for DW_OP_deref"); | |||
1463 | return false; | |||
1464 | } | |||
1465 | Address so_addr; | |||
1466 | if (!module_sp->ResolveFileAddress(file_addr, so_addr)) { | |||
1467 | if (error_ptr) | |||
1468 | error_ptr->SetErrorStringWithFormat( | |||
1469 | "failed to resolve file address in module"); | |||
1470 | return false; | |||
1471 | } | |||
1472 | addr_t load_Addr = so_addr.GetLoadAddress(exe_ctx->GetTargetPtr()); | |||
| ||||
1473 | if (load_Addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1474 | if (error_ptr) | |||
1475 | error_ptr->SetErrorStringWithFormat( | |||
1476 | "failed to resolve load address"); | |||
1477 | return false; | |||
1478 | } | |||
1479 | stack.back().GetScalar() = load_Addr; | |||
1480 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
1481 | // Fall through to load address code below... | |||
1482 | } LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1483 | case Value::eValueTypeLoadAddress: | |||
1484 | if (exe_ctx) { | |||
1485 | if (process) { | |||
1486 | lldb::addr_t pointer_addr = | |||
1487 | stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
1488 | Status error; | |||
1489 | lldb::addr_t pointer_value = | |||
1490 | process->ReadPointerFromMemory(pointer_addr, error); | |||
1491 | if (pointer_value != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1492 | stack.back().GetScalar() = pointer_value; | |||
1493 | stack.back().ClearContext(); | |||
1494 | } else { | |||
1495 | if (error_ptr) | |||
1496 | error_ptr->SetErrorStringWithFormat( | |||
1497 | "Failed to dereference pointer from 0x%" PRIx64"l" "x" | |||
1498 | " for DW_OP_deref: %s\n", | |||
1499 | pointer_addr, error.AsCString()); | |||
1500 | return false; | |||
1501 | } | |||
1502 | } else { | |||
1503 | if (error_ptr) | |||
1504 | error_ptr->SetErrorStringWithFormat( | |||
1505 | "NULL process for DW_OP_deref.\n"); | |||
1506 | return false; | |||
1507 | } | |||
1508 | } else { | |||
1509 | if (error_ptr) | |||
1510 | error_ptr->SetErrorStringWithFormat( | |||
1511 | "NULL execution context for DW_OP_deref.\n"); | |||
1512 | return false; | |||
1513 | } | |||
1514 | break; | |||
1515 | ||||
1516 | default: | |||
1517 | break; | |||
1518 | } | |||
1519 | ||||
1520 | } break; | |||
1521 | ||||
1522 | //---------------------------------------------------------------------- | |||
1523 | // OPCODE: DW_OP_deref_size | |||
1524 | // OPERANDS: 1 | |||
1525 | // 1 - uint8_t that specifies the size of the data to dereference. | |||
1526 | // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top | |||
1527 | // stack entry and treats it as an address. The value retrieved from that | |||
1528 | // address is pushed. In the DW_OP_deref_size operation, however, the size | |||
1529 | // in bytes of the data retrieved from the dereferenced address is | |||
1530 | // specified by the single operand. This operand is a 1-byte unsigned | |||
1531 | // integral constant whose value may not be larger than the size of an | |||
1532 | // address on the target machine. The data retrieved is zero extended to | |||
1533 | // the size of an address on the target machine before being pushed on the | |||
1534 | // expression stack. | |||
1535 | //---------------------------------------------------------------------- | |||
1536 | case DW_OP_deref_size: { | |||
1537 | if (stack.empty()) { | |||
1538 | if (error_ptr) | |||
1539 | error_ptr->SetErrorString( | |||
1540 | "Expression stack empty for DW_OP_deref_size."); | |||
1541 | return false; | |||
1542 | } | |||
1543 | uint8_t size = opcodes.GetU8(&offset); | |||
1544 | Value::ValueType value_type = stack.back().GetValueType(); | |||
1545 | switch (value_type) { | |||
1546 | case Value::eValueTypeHostAddress: { | |||
1547 | void *src = (void *)stack.back().GetScalar().ULongLong(); | |||
1548 | intptr_t ptr; | |||
1549 | ::memcpy(&ptr, src, sizeof(void *)); | |||
1550 | // I can't decide whether the size operand should apply to the bytes in | |||
1551 | // their | |||
1552 | // lldb-host endianness or the target endianness.. I doubt this'll ever | |||
1553 | // come up but I'll opt for assuming big endian regardless. | |||
1554 | switch (size) { | |||
1555 | case 1: | |||
1556 | ptr = ptr & 0xff; | |||
1557 | break; | |||
1558 | case 2: | |||
1559 | ptr = ptr & 0xffff; | |||
1560 | break; | |||
1561 | case 3: | |||
1562 | ptr = ptr & 0xffffff; | |||
1563 | break; | |||
1564 | case 4: | |||
1565 | ptr = ptr & 0xffffffff; | |||
1566 | break; | |||
1567 | // the casts are added to work around the case where intptr_t is a 32 | |||
1568 | // bit quantity; | |||
1569 | // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this | |||
1570 | // program. | |||
1571 | case 5: | |||
1572 | ptr = (intptr_t)ptr & 0xffffffffffULL; | |||
1573 | break; | |||
1574 | case 6: | |||
1575 | ptr = (intptr_t)ptr & 0xffffffffffffULL; | |||
1576 | break; | |||
1577 | case 7: | |||
1578 | ptr = (intptr_t)ptr & 0xffffffffffffffULL; | |||
1579 | break; | |||
1580 | default: | |||
1581 | break; | |||
1582 | } | |||
1583 | stack.back().GetScalar() = ptr; | |||
1584 | stack.back().ClearContext(); | |||
1585 | } break; | |||
1586 | case Value::eValueTypeLoadAddress: | |||
1587 | if (exe_ctx) { | |||
1588 | if (process) { | |||
1589 | lldb::addr_t pointer_addr = | |||
1590 | stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
1591 | uint8_t addr_bytes[sizeof(lldb::addr_t)]; | |||
1592 | Status error; | |||
1593 | if (process->ReadMemory(pointer_addr, &addr_bytes, size, error) == | |||
1594 | size) { | |||
1595 | DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), | |||
1596 | process->GetByteOrder(), size); | |||
1597 | lldb::offset_t addr_data_offset = 0; | |||
1598 | switch (size) { | |||
1599 | case 1: | |||
1600 | stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); | |||
1601 | break; | |||
1602 | case 2: | |||
1603 | stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); | |||
1604 | break; | |||
1605 | case 4: | |||
1606 | stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); | |||
1607 | break; | |||
1608 | case 8: | |||
1609 | stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); | |||
1610 | break; | |||
1611 | default: | |||
1612 | stack.back().GetScalar() = | |||
1613 | addr_data.GetPointer(&addr_data_offset); | |||
1614 | } | |||
1615 | stack.back().ClearContext(); | |||
1616 | } else { | |||
1617 | if (error_ptr) | |||
1618 | error_ptr->SetErrorStringWithFormat( | |||
1619 | "Failed to dereference pointer from 0x%" PRIx64"l" "x" | |||
1620 | " for DW_OP_deref: %s\n", | |||
1621 | pointer_addr, error.AsCString()); | |||
1622 | return false; | |||
1623 | } | |||
1624 | } else { | |||
1625 | if (error_ptr) | |||
1626 | error_ptr->SetErrorStringWithFormat( | |||
1627 | "NULL process for DW_OP_deref.\n"); | |||
1628 | return false; | |||
1629 | } | |||
1630 | } else { | |||
1631 | if (error_ptr) | |||
1632 | error_ptr->SetErrorStringWithFormat( | |||
1633 | "NULL execution context for DW_OP_deref.\n"); | |||
1634 | return false; | |||
1635 | } | |||
1636 | break; | |||
1637 | ||||
1638 | default: | |||
1639 | break; | |||
1640 | } | |||
1641 | ||||
1642 | } break; | |||
1643 | ||||
1644 | //---------------------------------------------------------------------- | |||
1645 | // OPCODE: DW_OP_xderef_size | |||
1646 | // OPERANDS: 1 | |||
1647 | // 1 - uint8_t that specifies the size of the data to dereference. | |||
1648 | // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at | |||
1649 | // the top of the stack is treated as an address. The second stack entry is | |||
1650 | // treated as an "address space identifier" for those architectures that | |||
1651 | // support multiple address spaces. The top two stack elements are popped, | |||
1652 | // a data item is retrieved through an implementation-defined address | |||
1653 | // calculation and pushed as the new stack top. In the DW_OP_xderef_size | |||
1654 | // operation, however, the size in bytes of the data retrieved from the | |||
1655 | // dereferenced address is specified by the single operand. This operand is | |||
1656 | // a 1-byte unsigned integral constant whose value may not be larger than | |||
1657 | // the size of an address on the target machine. The data retrieved is zero | |||
1658 | // extended to the size of an address on the target machine before being | |||
1659 | // pushed on the expression stack. | |||
1660 | //---------------------------------------------------------------------- | |||
1661 | case DW_OP_xderef_size: | |||
1662 | if (error_ptr) | |||
1663 | error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size."); | |||
1664 | return false; | |||
1665 | //---------------------------------------------------------------------- | |||
1666 | // OPCODE: DW_OP_xderef | |||
1667 | // OPERANDS: none | |||
1668 | // DESCRIPTION: Provides an extended dereference mechanism. The entry at | |||
1669 | // the top of the stack is treated as an address. The second stack entry is | |||
1670 | // treated as an "address space identifier" for those architectures that | |||
1671 | // support multiple address spaces. The top two stack elements are popped, | |||
1672 | // a data item is retrieved through an implementation-defined address | |||
1673 | // calculation and pushed as the new stack top. The size of the data | |||
1674 | // retrieved from the dereferenced address is the size of an address on the | |||
1675 | // target machine. | |||
1676 | //---------------------------------------------------------------------- | |||
1677 | case DW_OP_xderef: | |||
1678 | if (error_ptr) | |||
1679 | error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef."); | |||
1680 | return false; | |||
1681 | ||||
1682 | //---------------------------------------------------------------------- | |||
1683 | // All DW_OP_constXXX opcodes have a single operand as noted below: | |||
1684 | // | |||
1685 | // Opcode Operand 1 | |||
1686 | // --------------- ---------------------------------------------------- | |||
1687 | // DW_OP_const1u 1-byte unsigned integer constant DW_OP_const1s | |||
1688 | // 1-byte signed integer constant DW_OP_const2u 2-byte unsigned integer | |||
1689 | // constant DW_OP_const2s 2-byte signed integer constant DW_OP_const4u | |||
1690 | // 4-byte unsigned integer constant DW_OP_const4s 4-byte signed integer | |||
1691 | // constant DW_OP_const8u 8-byte unsigned integer constant DW_OP_const8s | |||
1692 | // 8-byte signed integer constant DW_OP_constu unsigned LEB128 integer | |||
1693 | // constant DW_OP_consts signed LEB128 integer constant | |||
1694 | //---------------------------------------------------------------------- | |||
1695 | case DW_OP_const1u: | |||
1696 | stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset))); | |||
1697 | break; | |||
1698 | case DW_OP_const1s: | |||
1699 | stack.push_back(Scalar((int8_t)opcodes.GetU8(&offset))); | |||
1700 | break; | |||
1701 | case DW_OP_const2u: | |||
1702 | stack.push_back(Scalar((uint16_t)opcodes.GetU16(&offset))); | |||
1703 | break; | |||
1704 | case DW_OP_const2s: | |||
1705 | stack.push_back(Scalar((int16_t)opcodes.GetU16(&offset))); | |||
1706 | break; | |||
1707 | case DW_OP_const4u: | |||
1708 | stack.push_back(Scalar((uint32_t)opcodes.GetU32(&offset))); | |||
1709 | break; | |||
1710 | case DW_OP_const4s: | |||
1711 | stack.push_back(Scalar((int32_t)opcodes.GetU32(&offset))); | |||
1712 | break; | |||
1713 | case DW_OP_const8u: | |||
1714 | stack.push_back(Scalar((uint64_t)opcodes.GetU64(&offset))); | |||
1715 | break; | |||
1716 | case DW_OP_const8s: | |||
1717 | stack.push_back(Scalar((int64_t)opcodes.GetU64(&offset))); | |||
1718 | break; | |||
1719 | case DW_OP_constu: | |||
1720 | stack.push_back(Scalar(opcodes.GetULEB128(&offset))); | |||
1721 | break; | |||
1722 | case DW_OP_consts: | |||
1723 | stack.push_back(Scalar(opcodes.GetSLEB128(&offset))); | |||
1724 | break; | |||
1725 | ||||
1726 | //---------------------------------------------------------------------- | |||
1727 | // OPCODE: DW_OP_dup | |||
1728 | // OPERANDS: none | |||
1729 | // DESCRIPTION: duplicates the value at the top of the stack | |||
1730 | //---------------------------------------------------------------------- | |||
1731 | case DW_OP_dup: | |||
1732 | if (stack.empty()) { | |||
1733 | if (error_ptr) | |||
1734 | error_ptr->SetErrorString("Expression stack empty for DW_OP_dup."); | |||
1735 | return false; | |||
1736 | } else | |||
1737 | stack.push_back(stack.back()); | |||
1738 | break; | |||
1739 | ||||
1740 | //---------------------------------------------------------------------- | |||
1741 | // OPCODE: DW_OP_drop | |||
1742 | // OPERANDS: none | |||
1743 | // DESCRIPTION: pops the value at the top of the stack | |||
1744 | //---------------------------------------------------------------------- | |||
1745 | case DW_OP_drop: | |||
1746 | if (stack.empty()) { | |||
1747 | if (error_ptr) | |||
1748 | error_ptr->SetErrorString("Expression stack empty for DW_OP_drop."); | |||
1749 | return false; | |||
1750 | } else | |||
1751 | stack.pop_back(); | |||
1752 | break; | |||
1753 | ||||
1754 | //---------------------------------------------------------------------- | |||
1755 | // OPCODE: DW_OP_over | |||
1756 | // OPERANDS: none | |||
1757 | // DESCRIPTION: Duplicates the entry currently second in the stack at | |||
1758 | // the top of the stack. | |||
1759 | //---------------------------------------------------------------------- | |||
1760 | case DW_OP_over: | |||
1761 | if (stack.size() < 2) { | |||
1762 | if (error_ptr) | |||
1763 | error_ptr->SetErrorString( | |||
1764 | "Expression stack needs at least 2 items for DW_OP_over."); | |||
1765 | return false; | |||
1766 | } else | |||
1767 | stack.push_back(stack[stack.size() - 2]); | |||
1768 | break; | |||
1769 | ||||
1770 | //---------------------------------------------------------------------- | |||
1771 | // OPCODE: DW_OP_pick | |||
1772 | // OPERANDS: uint8_t index into the current stack | |||
1773 | // DESCRIPTION: The stack entry with the specified index (0 through 255, | |||
1774 | // inclusive) is pushed on the stack | |||
1775 | //---------------------------------------------------------------------- | |||
1776 | case DW_OP_pick: { | |||
1777 | uint8_t pick_idx = opcodes.GetU8(&offset); | |||
1778 | if (pick_idx < stack.size()) | |||
1779 | stack.push_back(stack[pick_idx]); | |||
1780 | else { | |||
1781 | if (error_ptr) | |||
1782 | error_ptr->SetErrorStringWithFormat( | |||
1783 | "Index %u out of range for DW_OP_pick.\n", pick_idx); | |||
1784 | return false; | |||
1785 | } | |||
1786 | } break; | |||
1787 | ||||
1788 | //---------------------------------------------------------------------- | |||
1789 | // OPCODE: DW_OP_swap | |||
1790 | // OPERANDS: none | |||
1791 | // DESCRIPTION: swaps the top two stack entries. The entry at the top | |||
1792 | // of the stack becomes the second stack entry, and the second entry | |||
1793 | // becomes the top of the stack | |||
1794 | //---------------------------------------------------------------------- | |||
1795 | case DW_OP_swap: | |||
1796 | if (stack.size() < 2) { | |||
1797 | if (error_ptr) | |||
1798 | error_ptr->SetErrorString( | |||
1799 | "Expression stack needs at least 2 items for DW_OP_swap."); | |||
1800 | return false; | |||
1801 | } else { | |||
1802 | tmp = stack.back(); | |||
1803 | stack.back() = stack[stack.size() - 2]; | |||
1804 | stack[stack.size() - 2] = tmp; | |||
1805 | } | |||
1806 | break; | |||
1807 | ||||
1808 | //---------------------------------------------------------------------- | |||
1809 | // OPCODE: DW_OP_rot | |||
1810 | // OPERANDS: none | |||
1811 | // DESCRIPTION: Rotates the first three stack entries. The entry at | |||
1812 | // the top of the stack becomes the third stack entry, the second entry | |||
1813 | // becomes the top of the stack, and the third entry becomes the second | |||
1814 | // entry. | |||
1815 | //---------------------------------------------------------------------- | |||
1816 | case DW_OP_rot: | |||
1817 | if (stack.size() < 3) { | |||
1818 | if (error_ptr) | |||
1819 | error_ptr->SetErrorString( | |||
1820 | "Expression stack needs at least 3 items for DW_OP_rot."); | |||
1821 | return false; | |||
1822 | } else { | |||
1823 | size_t last_idx = stack.size() - 1; | |||
1824 | Value old_top = stack[last_idx]; | |||
1825 | stack[last_idx] = stack[last_idx - 1]; | |||
1826 | stack[last_idx - 1] = stack[last_idx - 2]; | |||
1827 | stack[last_idx - 2] = old_top; | |||
1828 | } | |||
1829 | break; | |||
1830 | ||||
1831 | //---------------------------------------------------------------------- | |||
1832 | // OPCODE: DW_OP_abs | |||
1833 | // OPERANDS: none | |||
1834 | // DESCRIPTION: pops the top stack entry, interprets it as a signed | |||
1835 | // value and pushes its absolute value. If the absolute value can not be | |||
1836 | // represented, the result is undefined. | |||
1837 | //---------------------------------------------------------------------- | |||
1838 | case DW_OP_abs: | |||
1839 | if (stack.empty()) { | |||
1840 | if (error_ptr) | |||
1841 | error_ptr->SetErrorString( | |||
1842 | "Expression stack needs at least 1 item for DW_OP_abs."); | |||
1843 | return false; | |||
1844 | } else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false) { | |||
1845 | if (error_ptr) | |||
1846 | error_ptr->SetErrorString( | |||
1847 | "Failed to take the absolute value of the first stack item."); | |||
1848 | return false; | |||
1849 | } | |||
1850 | break; | |||
1851 | ||||
1852 | //---------------------------------------------------------------------- | |||
1853 | // OPCODE: DW_OP_and | |||
1854 | // OPERANDS: none | |||
1855 | // DESCRIPTION: pops the top two stack values, performs a bitwise and | |||
1856 | // operation on the two, and pushes the result. | |||
1857 | //---------------------------------------------------------------------- | |||
1858 | case DW_OP_and: | |||
1859 | if (stack.size() < 2) { | |||
1860 | if (error_ptr) | |||
1861 | error_ptr->SetErrorString( | |||
1862 | "Expression stack needs at least 2 items for DW_OP_and."); | |||
1863 | return false; | |||
1864 | } else { | |||
1865 | tmp = stack.back(); | |||
1866 | stack.pop_back(); | |||
1867 | stack.back().ResolveValue(exe_ctx) = | |||
1868 | stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx); | |||
1869 | } | |||
1870 | break; | |||
1871 | ||||
1872 | //---------------------------------------------------------------------- | |||
1873 | // OPCODE: DW_OP_div | |||
1874 | // OPERANDS: none | |||
1875 | // DESCRIPTION: pops the top two stack values, divides the former second | |||
1876 | // entry by the former top of the stack using signed division, and pushes | |||
1877 | // the result. | |||
1878 | //---------------------------------------------------------------------- | |||
1879 | case DW_OP_div: | |||
1880 | if (stack.size() < 2) { | |||
1881 | if (error_ptr) | |||
1882 | error_ptr->SetErrorString( | |||
1883 | "Expression stack needs at least 2 items for DW_OP_div."); | |||
1884 | return false; | |||
1885 | } else { | |||
1886 | tmp = stack.back(); | |||
1887 | if (tmp.ResolveValue(exe_ctx).IsZero()) { | |||
1888 | if (error_ptr) | |||
1889 | error_ptr->SetErrorString("Divide by zero."); | |||
1890 | return false; | |||
1891 | } else { | |||
1892 | stack.pop_back(); | |||
1893 | stack.back() = | |||
1894 | stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx); | |||
1895 | if (!stack.back().ResolveValue(exe_ctx).IsValid()) { | |||
1896 | if (error_ptr) | |||
1897 | error_ptr->SetErrorString("Divide failed."); | |||
1898 | return false; | |||
1899 | } | |||
1900 | } | |||
1901 | } | |||
1902 | break; | |||
1903 | ||||
1904 | //---------------------------------------------------------------------- | |||
1905 | // OPCODE: DW_OP_minus | |||
1906 | // OPERANDS: none | |||
1907 | // DESCRIPTION: pops the top two stack values, subtracts the former top | |||
1908 | // of the stack from the former second entry, and pushes the result. | |||
1909 | //---------------------------------------------------------------------- | |||
1910 | case DW_OP_minus: | |||
1911 | if (stack.size() < 2) { | |||
1912 | if (error_ptr) | |||
1913 | error_ptr->SetErrorString( | |||
1914 | "Expression stack needs at least 2 items for DW_OP_minus."); | |||
1915 | return false; | |||
1916 | } else { | |||
1917 | tmp = stack.back(); | |||
1918 | stack.pop_back(); | |||
1919 | stack.back().ResolveValue(exe_ctx) = | |||
1920 | stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx); | |||
1921 | } | |||
1922 | break; | |||
1923 | ||||
1924 | //---------------------------------------------------------------------- | |||
1925 | // OPCODE: DW_OP_mod | |||
1926 | // OPERANDS: none | |||
1927 | // DESCRIPTION: pops the top two stack values and pushes the result of | |||
1928 | // the calculation: former second stack entry modulo the former top of the | |||
1929 | // stack. | |||
1930 | //---------------------------------------------------------------------- | |||
1931 | case DW_OP_mod: | |||
1932 | if (stack.size() < 2) { | |||
1933 | if (error_ptr) | |||
1934 | error_ptr->SetErrorString( | |||
1935 | "Expression stack needs at least 2 items for DW_OP_mod."); | |||
1936 | return false; | |||
1937 | } else { | |||
1938 | tmp = stack.back(); | |||
1939 | stack.pop_back(); | |||
1940 | stack.back().ResolveValue(exe_ctx) = | |||
1941 | stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx); | |||
1942 | } | |||
1943 | break; | |||
1944 | ||||
1945 | //---------------------------------------------------------------------- | |||
1946 | // OPCODE: DW_OP_mul | |||
1947 | // OPERANDS: none | |||
1948 | // DESCRIPTION: pops the top two stack entries, multiplies them | |||
1949 | // together, and pushes the result. | |||
1950 | //---------------------------------------------------------------------- | |||
1951 | case DW_OP_mul: | |||
1952 | if (stack.size() < 2) { | |||
1953 | if (error_ptr) | |||
1954 | error_ptr->SetErrorString( | |||
1955 | "Expression stack needs at least 2 items for DW_OP_mul."); | |||
1956 | return false; | |||
1957 | } else { | |||
1958 | tmp = stack.back(); | |||
1959 | stack.pop_back(); | |||
1960 | stack.back().ResolveValue(exe_ctx) = | |||
1961 | stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx); | |||
1962 | } | |||
1963 | break; | |||
1964 | ||||
1965 | //---------------------------------------------------------------------- | |||
1966 | // OPCODE: DW_OP_neg | |||
1967 | // OPERANDS: none | |||
1968 | // DESCRIPTION: pops the top stack entry, and pushes its negation. | |||
1969 | //---------------------------------------------------------------------- | |||
1970 | case DW_OP_neg: | |||
1971 | if (stack.empty()) { | |||
1972 | if (error_ptr) | |||
1973 | error_ptr->SetErrorString( | |||
1974 | "Expression stack needs at least 1 item for DW_OP_neg."); | |||
1975 | return false; | |||
1976 | } else { | |||
1977 | if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false) { | |||
1978 | if (error_ptr) | |||
1979 | error_ptr->SetErrorString("Unary negate failed."); | |||
1980 | return false; | |||
1981 | } | |||
1982 | } | |||
1983 | break; | |||
1984 | ||||
1985 | //---------------------------------------------------------------------- | |||
1986 | // OPCODE: DW_OP_not | |||
1987 | // OPERANDS: none | |||
1988 | // DESCRIPTION: pops the top stack entry, and pushes its bitwise | |||
1989 | // complement | |||
1990 | //---------------------------------------------------------------------- | |||
1991 | case DW_OP_not: | |||
1992 | if (stack.empty()) { | |||
1993 | if (error_ptr) | |||
1994 | error_ptr->SetErrorString( | |||
1995 | "Expression stack needs at least 1 item for DW_OP_not."); | |||
1996 | return false; | |||
1997 | } else { | |||
1998 | if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false) { | |||
1999 | if (error_ptr) | |||
2000 | error_ptr->SetErrorString("Logical NOT failed."); | |||
2001 | return false; | |||
2002 | } | |||
2003 | } | |||
2004 | break; | |||
2005 | ||||
2006 | //---------------------------------------------------------------------- | |||
2007 | // OPCODE: DW_OP_or | |||
2008 | // OPERANDS: none | |||
2009 | // DESCRIPTION: pops the top two stack entries, performs a bitwise or | |||
2010 | // operation on the two, and pushes the result. | |||
2011 | //---------------------------------------------------------------------- | |||
2012 | case DW_OP_or: | |||
2013 | if (stack.size() < 2) { | |||
2014 | if (error_ptr) | |||
2015 | error_ptr->SetErrorString( | |||
2016 | "Expression stack needs at least 2 items for DW_OP_or."); | |||
2017 | return false; | |||
2018 | } else { | |||
2019 | tmp = stack.back(); | |||
2020 | stack.pop_back(); | |||
2021 | stack.back().ResolveValue(exe_ctx) = | |||
2022 | stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx); | |||
2023 | } | |||
2024 | break; | |||
2025 | ||||
2026 | //---------------------------------------------------------------------- | |||
2027 | // OPCODE: DW_OP_plus | |||
2028 | // OPERANDS: none | |||
2029 | // DESCRIPTION: pops the top two stack entries, adds them together, and | |||
2030 | // pushes the result. | |||
2031 | //---------------------------------------------------------------------- | |||
2032 | case DW_OP_plus: | |||
2033 | if (stack.size() < 2) { | |||
2034 | if (error_ptr) | |||
2035 | error_ptr->SetErrorString( | |||
2036 | "Expression stack needs at least 2 items for DW_OP_plus."); | |||
2037 | return false; | |||
2038 | } else { | |||
2039 | tmp = stack.back(); | |||
2040 | stack.pop_back(); | |||
2041 | stack.back().GetScalar() += tmp.GetScalar(); | |||
2042 | } | |||
2043 | break; | |||
2044 | ||||
2045 | //---------------------------------------------------------------------- | |||
2046 | // OPCODE: DW_OP_plus_uconst | |||
2047 | // OPERANDS: none | |||
2048 | // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128 | |||
2049 | // constant operand and pushes the result. | |||
2050 | //---------------------------------------------------------------------- | |||
2051 | case DW_OP_plus_uconst: | |||
2052 | if (stack.empty()) { | |||
2053 | if (error_ptr) | |||
2054 | error_ptr->SetErrorString( | |||
2055 | "Expression stack needs at least 1 item for DW_OP_plus_uconst."); | |||
2056 | return false; | |||
2057 | } else { | |||
2058 | const uint64_t uconst_value = opcodes.GetULEB128(&offset); | |||
2059 | // Implicit conversion from a UINT to a Scalar... | |||
2060 | stack.back().GetScalar() += uconst_value; | |||
2061 | if (!stack.back().GetScalar().IsValid()) { | |||
2062 | if (error_ptr) | |||
2063 | error_ptr->SetErrorString("DW_OP_plus_uconst failed."); | |||
2064 | return false; | |||
2065 | } | |||
2066 | } | |||
2067 | break; | |||
2068 | ||||
2069 | //---------------------------------------------------------------------- | |||
2070 | // OPCODE: DW_OP_shl | |||
2071 | // OPERANDS: none | |||
2072 | // DESCRIPTION: pops the top two stack entries, shifts the former | |||
2073 | // second entry left by the number of bits specified by the former top of | |||
2074 | // the stack, and pushes the result. | |||
2075 | //---------------------------------------------------------------------- | |||
2076 | case DW_OP_shl: | |||
2077 | if (stack.size() < 2) { | |||
2078 | if (error_ptr) | |||
2079 | error_ptr->SetErrorString( | |||
2080 | "Expression stack needs at least 2 items for DW_OP_shl."); | |||
2081 | return false; | |||
2082 | } else { | |||
2083 | tmp = stack.back(); | |||
2084 | stack.pop_back(); | |||
2085 | stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx); | |||
2086 | } | |||
2087 | break; | |||
2088 | ||||
2089 | //---------------------------------------------------------------------- | |||
2090 | // OPCODE: DW_OP_shr | |||
2091 | // OPERANDS: none | |||
2092 | // DESCRIPTION: pops the top two stack entries, shifts the former second | |||
2093 | // entry right logically (filling with zero bits) by the number of bits | |||
2094 | // specified by the former top of the stack, and pushes the result. | |||
2095 | //---------------------------------------------------------------------- | |||
2096 | case DW_OP_shr: | |||
2097 | if (stack.size() < 2) { | |||
2098 | if (error_ptr) | |||
2099 | error_ptr->SetErrorString( | |||
2100 | "Expression stack needs at least 2 items for DW_OP_shr."); | |||
2101 | return false; | |||
2102 | } else { | |||
2103 | tmp = stack.back(); | |||
2104 | stack.pop_back(); | |||
2105 | if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical( | |||
2106 | tmp.ResolveValue(exe_ctx)) == false) { | |||
2107 | if (error_ptr) | |||
2108 | error_ptr->SetErrorString("DW_OP_shr failed."); | |||
2109 | return false; | |||
2110 | } | |||
2111 | } | |||
2112 | break; | |||
2113 | ||||
2114 | //---------------------------------------------------------------------- | |||
2115 | // OPCODE: DW_OP_shra | |||
2116 | // OPERANDS: none | |||
2117 | // DESCRIPTION: pops the top two stack entries, shifts the former second | |||
2118 | // entry right arithmetically (divide the magnitude by 2, keep the same | |||
2119 | // sign for the result) by the number of bits specified by the former top | |||
2120 | // of the stack, and pushes the result. | |||
2121 | //---------------------------------------------------------------------- | |||
2122 | case DW_OP_shra: | |||
2123 | if (stack.size() < 2) { | |||
2124 | if (error_ptr) | |||
2125 | error_ptr->SetErrorString( | |||
2126 | "Expression stack needs at least 2 items for DW_OP_shra."); | |||
2127 | return false; | |||
2128 | } else { | |||
2129 | tmp = stack.back(); | |||
2130 | stack.pop_back(); | |||
2131 | stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx); | |||
2132 | } | |||
2133 | break; | |||
2134 | ||||
2135 | //---------------------------------------------------------------------- | |||
2136 | // OPCODE: DW_OP_xor | |||
2137 | // OPERANDS: none | |||
2138 | // DESCRIPTION: pops the top two stack entries, performs the bitwise | |||
2139 | // exclusive-or operation on the two, and pushes the result. | |||
2140 | //---------------------------------------------------------------------- | |||
2141 | case DW_OP_xor: | |||
2142 | if (stack.size() < 2) { | |||
2143 | if (error_ptr) | |||
2144 | error_ptr->SetErrorString( | |||
2145 | "Expression stack needs at least 2 items for DW_OP_xor."); | |||
2146 | return false; | |||
2147 | } else { | |||
2148 | tmp = stack.back(); | |||
2149 | stack.pop_back(); | |||
2150 | stack.back().ResolveValue(exe_ctx) = | |||
2151 | stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx); | |||
2152 | } | |||
2153 | break; | |||
2154 | ||||
2155 | //---------------------------------------------------------------------- | |||
2156 | // OPCODE: DW_OP_skip | |||
2157 | // OPERANDS: int16_t | |||
2158 | // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte | |||
2159 | // signed integer constant. The 2-byte constant is the number of bytes of | |||
2160 | // the DWARF expression to skip forward or backward from the current | |||
2161 | // operation, beginning after the 2-byte constant. | |||
2162 | //---------------------------------------------------------------------- | |||
2163 | case DW_OP_skip: { | |||
2164 | int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); | |||
2165 | lldb::offset_t new_offset = offset + skip_offset; | |||
2166 | if (new_offset >= opcodes_offset && new_offset < end_offset) | |||
2167 | offset = new_offset; | |||
2168 | else { | |||
2169 | if (error_ptr) | |||
2170 | error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); | |||
2171 | return false; | |||
2172 | } | |||
2173 | } break; | |||
2174 | ||||
2175 | //---------------------------------------------------------------------- | |||
2176 | // OPCODE: DW_OP_bra | |||
2177 | // OPERANDS: int16_t | |||
2178 | // DESCRIPTION: A conditional branch. Its single operand is a 2-byte | |||
2179 | // signed integer constant. This operation pops the top of stack. If the | |||
2180 | // value popped is not the constant 0, the 2-byte constant operand is the | |||
2181 | // number of bytes of the DWARF expression to skip forward or backward from | |||
2182 | // the current operation, beginning after the 2-byte constant. | |||
2183 | //---------------------------------------------------------------------- | |||
2184 | case DW_OP_bra: | |||
2185 | if (stack.empty()) { | |||
2186 | if (error_ptr) | |||
2187 | error_ptr->SetErrorString( | |||
2188 | "Expression stack needs at least 1 item for DW_OP_bra."); | |||
2189 | return false; | |||
2190 | } else { | |||
2191 | tmp = stack.back(); | |||
2192 | stack.pop_back(); | |||
2193 | int16_t bra_offset = (int16_t)opcodes.GetU16(&offset); | |||
2194 | Scalar zero(0); | |||
2195 | if (tmp.ResolveValue(exe_ctx) != zero) { | |||
2196 | lldb::offset_t new_offset = offset + bra_offset; | |||
2197 | if (new_offset >= opcodes_offset && new_offset < end_offset) | |||
2198 | offset = new_offset; | |||
2199 | else { | |||
2200 | if (error_ptr) | |||
2201 | error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); | |||
2202 | return false; | |||
2203 | } | |||
2204 | } | |||
2205 | } | |||
2206 | break; | |||
2207 | ||||
2208 | //---------------------------------------------------------------------- | |||
2209 | // OPCODE: DW_OP_eq | |||
2210 | // OPERANDS: none | |||
2211 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2212 | // equals (==) operator. | |||
2213 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2214 | // of the operation is true or the constant value 0 if the result of the | |||
2215 | // operation is false. | |||
2216 | //---------------------------------------------------------------------- | |||
2217 | case DW_OP_eq: | |||
2218 | if (stack.size() < 2) { | |||
2219 | if (error_ptr) | |||
2220 | error_ptr->SetErrorString( | |||
2221 | "Expression stack needs at least 2 items for DW_OP_eq."); | |||
2222 | return false; | |||
2223 | } else { | |||
2224 | tmp = stack.back(); | |||
2225 | stack.pop_back(); | |||
2226 | stack.back().ResolveValue(exe_ctx) = | |||
2227 | stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx); | |||
2228 | } | |||
2229 | break; | |||
2230 | ||||
2231 | //---------------------------------------------------------------------- | |||
2232 | // OPCODE: DW_OP_ge | |||
2233 | // OPERANDS: none | |||
2234 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2235 | // greater than or equal to (>=) operator. | |||
2236 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2237 | // of the operation is true or the constant value 0 if the result of the | |||
2238 | // operation is false. | |||
2239 | //---------------------------------------------------------------------- | |||
2240 | case DW_OP_ge: | |||
2241 | if (stack.size() < 2) { | |||
2242 | if (error_ptr) | |||
2243 | error_ptr->SetErrorString( | |||
2244 | "Expression stack needs at least 2 items for DW_OP_ge."); | |||
2245 | return false; | |||
2246 | } else { | |||
2247 | tmp = stack.back(); | |||
2248 | stack.pop_back(); | |||
2249 | stack.back().ResolveValue(exe_ctx) = | |||
2250 | stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx); | |||
2251 | } | |||
2252 | break; | |||
2253 | ||||
2254 | //---------------------------------------------------------------------- | |||
2255 | // OPCODE: DW_OP_gt | |||
2256 | // OPERANDS: none | |||
2257 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2258 | // greater than (>) operator. | |||
2259 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2260 | // of the operation is true or the constant value 0 if the result of the | |||
2261 | // operation is false. | |||
2262 | //---------------------------------------------------------------------- | |||
2263 | case DW_OP_gt: | |||
2264 | if (stack.size() < 2) { | |||
2265 | if (error_ptr) | |||
2266 | error_ptr->SetErrorString( | |||
2267 | "Expression stack needs at least 2 items for DW_OP_gt."); | |||
2268 | return false; | |||
2269 | } else { | |||
2270 | tmp = stack.back(); | |||
2271 | stack.pop_back(); | |||
2272 | stack.back().ResolveValue(exe_ctx) = | |||
2273 | stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx); | |||
2274 | } | |||
2275 | break; | |||
2276 | ||||
2277 | //---------------------------------------------------------------------- | |||
2278 | // OPCODE: DW_OP_le | |||
2279 | // OPERANDS: none | |||
2280 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2281 | // less than or equal to (<=) operator. | |||
2282 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2283 | // of the operation is true or the constant value 0 if the result of the | |||
2284 | // operation is false. | |||
2285 | //---------------------------------------------------------------------- | |||
2286 | case DW_OP_le: | |||
2287 | if (stack.size() < 2) { | |||
2288 | if (error_ptr) | |||
2289 | error_ptr->SetErrorString( | |||
2290 | "Expression stack needs at least 2 items for DW_OP_le."); | |||
2291 | return false; | |||
2292 | } else { | |||
2293 | tmp = stack.back(); | |||
2294 | stack.pop_back(); | |||
2295 | stack.back().ResolveValue(exe_ctx) = | |||
2296 | stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx); | |||
2297 | } | |||
2298 | break; | |||
2299 | ||||
2300 | //---------------------------------------------------------------------- | |||
2301 | // OPCODE: DW_OP_lt | |||
2302 | // OPERANDS: none | |||
2303 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2304 | // less than (<) operator. | |||
2305 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2306 | // of the operation is true or the constant value 0 if the result of the | |||
2307 | // operation is false. | |||
2308 | //---------------------------------------------------------------------- | |||
2309 | case DW_OP_lt: | |||
2310 | if (stack.size() < 2) { | |||
2311 | if (error_ptr) | |||
2312 | error_ptr->SetErrorString( | |||
2313 | "Expression stack needs at least 2 items for DW_OP_lt."); | |||
2314 | return false; | |||
2315 | } else { | |||
2316 | tmp = stack.back(); | |||
2317 | stack.pop_back(); | |||
2318 | stack.back().ResolveValue(exe_ctx) = | |||
2319 | stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx); | |||
2320 | } | |||
2321 | break; | |||
2322 | ||||
2323 | //---------------------------------------------------------------------- | |||
2324 | // OPCODE: DW_OP_ne | |||
2325 | // OPERANDS: none | |||
2326 | // DESCRIPTION: pops the top two stack values, compares using the | |||
2327 | // not equal (!=) operator. | |||
2328 | // STACK RESULT: push the constant value 1 onto the stack if the result | |||
2329 | // of the operation is true or the constant value 0 if the result of the | |||
2330 | // operation is false. | |||
2331 | //---------------------------------------------------------------------- | |||
2332 | case DW_OP_ne: | |||
2333 | if (stack.size() < 2) { | |||
2334 | if (error_ptr) | |||
2335 | error_ptr->SetErrorString( | |||
2336 | "Expression stack needs at least 2 items for DW_OP_ne."); | |||
2337 | return false; | |||
2338 | } else { | |||
2339 | tmp = stack.back(); | |||
2340 | stack.pop_back(); | |||
2341 | stack.back().ResolveValue(exe_ctx) = | |||
2342 | stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx); | |||
2343 | } | |||
2344 | break; | |||
2345 | ||||
2346 | //---------------------------------------------------------------------- | |||
2347 | // OPCODE: DW_OP_litn | |||
2348 | // OPERANDS: none | |||
2349 | // DESCRIPTION: encode the unsigned literal values from 0 through 31. | |||
2350 | // STACK RESULT: push the unsigned literal constant value onto the top | |||
2351 | // of the stack. | |||
2352 | //---------------------------------------------------------------------- | |||
2353 | case DW_OP_lit0: | |||
2354 | case DW_OP_lit1: | |||
2355 | case DW_OP_lit2: | |||
2356 | case DW_OP_lit3: | |||
2357 | case DW_OP_lit4: | |||
2358 | case DW_OP_lit5: | |||
2359 | case DW_OP_lit6: | |||
2360 | case DW_OP_lit7: | |||
2361 | case DW_OP_lit8: | |||
2362 | case DW_OP_lit9: | |||
2363 | case DW_OP_lit10: | |||
2364 | case DW_OP_lit11: | |||
2365 | case DW_OP_lit12: | |||
2366 | case DW_OP_lit13: | |||
2367 | case DW_OP_lit14: | |||
2368 | case DW_OP_lit15: | |||
2369 | case DW_OP_lit16: | |||
2370 | case DW_OP_lit17: | |||
2371 | case DW_OP_lit18: | |||
2372 | case DW_OP_lit19: | |||
2373 | case DW_OP_lit20: | |||
2374 | case DW_OP_lit21: | |||
2375 | case DW_OP_lit22: | |||
2376 | case DW_OP_lit23: | |||
2377 | case DW_OP_lit24: | |||
2378 | case DW_OP_lit25: | |||
2379 | case DW_OP_lit26: | |||
2380 | case DW_OP_lit27: | |||
2381 | case DW_OP_lit28: | |||
2382 | case DW_OP_lit29: | |||
2383 | case DW_OP_lit30: | |||
2384 | case DW_OP_lit31: | |||
2385 | stack.push_back(Scalar((uint64_t)(op - DW_OP_lit0))); | |||
2386 | break; | |||
2387 | ||||
2388 | //---------------------------------------------------------------------- | |||
2389 | // OPCODE: DW_OP_regN | |||
2390 | // OPERANDS: none | |||
2391 | // DESCRIPTION: Push the value in register n on the top of the stack. | |||
2392 | //---------------------------------------------------------------------- | |||
2393 | case DW_OP_reg0: | |||
2394 | case DW_OP_reg1: | |||
2395 | case DW_OP_reg2: | |||
2396 | case DW_OP_reg3: | |||
2397 | case DW_OP_reg4: | |||
2398 | case DW_OP_reg5: | |||
2399 | case DW_OP_reg6: | |||
2400 | case DW_OP_reg7: | |||
2401 | case DW_OP_reg8: | |||
2402 | case DW_OP_reg9: | |||
2403 | case DW_OP_reg10: | |||
2404 | case DW_OP_reg11: | |||
2405 | case DW_OP_reg12: | |||
2406 | case DW_OP_reg13: | |||
2407 | case DW_OP_reg14: | |||
2408 | case DW_OP_reg15: | |||
2409 | case DW_OP_reg16: | |||
2410 | case DW_OP_reg17: | |||
2411 | case DW_OP_reg18: | |||
2412 | case DW_OP_reg19: | |||
2413 | case DW_OP_reg20: | |||
2414 | case DW_OP_reg21: | |||
2415 | case DW_OP_reg22: | |||
2416 | case DW_OP_reg23: | |||
2417 | case DW_OP_reg24: | |||
2418 | case DW_OP_reg25: | |||
2419 | case DW_OP_reg26: | |||
2420 | case DW_OP_reg27: | |||
2421 | case DW_OP_reg28: | |||
2422 | case DW_OP_reg29: | |||
2423 | case DW_OP_reg30: | |||
2424 | case DW_OP_reg31: { | |||
2425 | reg_num = op - DW_OP_reg0; | |||
2426 | ||||
2427 | if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) | |||
2428 | stack.push_back(tmp); | |||
2429 | else | |||
2430 | return false; | |||
2431 | } break; | |||
2432 | //---------------------------------------------------------------------- | |||
2433 | // OPCODE: DW_OP_regx | |||
2434 | // OPERANDS: | |||
2435 | // ULEB128 literal operand that encodes the register. | |||
2436 | // DESCRIPTION: Push the value in register on the top of the stack. | |||
2437 | //---------------------------------------------------------------------- | |||
2438 | case DW_OP_regx: { | |||
2439 | reg_num = opcodes.GetULEB128(&offset); | |||
2440 | if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) | |||
2441 | stack.push_back(tmp); | |||
2442 | else | |||
2443 | return false; | |||
2444 | } break; | |||
2445 | ||||
2446 | //---------------------------------------------------------------------- | |||
2447 | // OPCODE: DW_OP_bregN | |||
2448 | // OPERANDS: | |||
2449 | // SLEB128 offset from register N | |||
2450 | // DESCRIPTION: Value is in memory at the address specified by register | |||
2451 | // N plus an offset. | |||
2452 | //---------------------------------------------------------------------- | |||
2453 | case DW_OP_breg0: | |||
2454 | case DW_OP_breg1: | |||
2455 | case DW_OP_breg2: | |||
2456 | case DW_OP_breg3: | |||
2457 | case DW_OP_breg4: | |||
2458 | case DW_OP_breg5: | |||
2459 | case DW_OP_breg6: | |||
2460 | case DW_OP_breg7: | |||
2461 | case DW_OP_breg8: | |||
2462 | case DW_OP_breg9: | |||
2463 | case DW_OP_breg10: | |||
2464 | case DW_OP_breg11: | |||
2465 | case DW_OP_breg12: | |||
2466 | case DW_OP_breg13: | |||
2467 | case DW_OP_breg14: | |||
2468 | case DW_OP_breg15: | |||
2469 | case DW_OP_breg16: | |||
2470 | case DW_OP_breg17: | |||
2471 | case DW_OP_breg18: | |||
2472 | case DW_OP_breg19: | |||
2473 | case DW_OP_breg20: | |||
2474 | case DW_OP_breg21: | |||
2475 | case DW_OP_breg22: | |||
2476 | case DW_OP_breg23: | |||
2477 | case DW_OP_breg24: | |||
2478 | case DW_OP_breg25: | |||
2479 | case DW_OP_breg26: | |||
2480 | case DW_OP_breg27: | |||
2481 | case DW_OP_breg28: | |||
2482 | case DW_OP_breg29: | |||
2483 | case DW_OP_breg30: | |||
2484 | case DW_OP_breg31: { | |||
2485 | reg_num = op - DW_OP_breg0; | |||
2486 | ||||
2487 | if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, | |||
2488 | tmp)) { | |||
2489 | int64_t breg_offset = opcodes.GetSLEB128(&offset); | |||
2490 | tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; | |||
2491 | tmp.ClearContext(); | |||
2492 | stack.push_back(tmp); | |||
2493 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
2494 | } else | |||
2495 | return false; | |||
2496 | } break; | |||
2497 | //---------------------------------------------------------------------- | |||
2498 | // OPCODE: DW_OP_bregx | |||
2499 | // OPERANDS: 2 | |||
2500 | // ULEB128 literal operand that encodes the register. | |||
2501 | // SLEB128 offset from register N | |||
2502 | // DESCRIPTION: Value is in memory at the address specified by register | |||
2503 | // N plus an offset. | |||
2504 | //---------------------------------------------------------------------- | |||
2505 | case DW_OP_bregx: { | |||
2506 | reg_num = opcodes.GetULEB128(&offset); | |||
2507 | ||||
2508 | if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, | |||
2509 | tmp)) { | |||
2510 | int64_t breg_offset = opcodes.GetSLEB128(&offset); | |||
2511 | tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; | |||
2512 | tmp.ClearContext(); | |||
2513 | stack.push_back(tmp); | |||
2514 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
2515 | } else | |||
2516 | return false; | |||
2517 | } break; | |||
2518 | ||||
2519 | case DW_OP_fbreg: | |||
2520 | if (exe_ctx) { | |||
2521 | if (frame) { | |||
2522 | Scalar value; | |||
2523 | if (frame->GetFrameBaseValue(value, error_ptr)) { | |||
2524 | int64_t fbreg_offset = opcodes.GetSLEB128(&offset); | |||
2525 | value += fbreg_offset; | |||
2526 | stack.push_back(value); | |||
2527 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
2528 | } else | |||
2529 | return false; | |||
2530 | } else { | |||
2531 | if (error_ptr) | |||
2532 | error_ptr->SetErrorString( | |||
2533 | "Invalid stack frame in context for DW_OP_fbreg opcode."); | |||
2534 | return false; | |||
2535 | } | |||
2536 | } else { | |||
2537 | if (error_ptr) | |||
2538 | error_ptr->SetErrorStringWithFormat( | |||
2539 | "NULL execution context for DW_OP_fbreg.\n"); | |||
2540 | return false; | |||
2541 | } | |||
2542 | ||||
2543 | break; | |||
2544 | ||||
2545 | //---------------------------------------------------------------------- | |||
2546 | // OPCODE: DW_OP_nop | |||
2547 | // OPERANDS: none | |||
2548 | // DESCRIPTION: A place holder. It has no effect on the location stack | |||
2549 | // or any of its values. | |||
2550 | //---------------------------------------------------------------------- | |||
2551 | case DW_OP_nop: | |||
2552 | break; | |||
2553 | ||||
2554 | //---------------------------------------------------------------------- | |||
2555 | // OPCODE: DW_OP_piece | |||
2556 | // OPERANDS: 1 | |||
2557 | // ULEB128: byte size of the piece | |||
2558 | // DESCRIPTION: The operand describes the size in bytes of the piece of | |||
2559 | // the object referenced by the DWARF expression whose result is at the top | |||
2560 | // of the stack. If the piece is located in a register, but does not occupy | |||
2561 | // the entire register, the placement of the piece within that register is | |||
2562 | // defined by the ABI. | |||
2563 | // | |||
2564 | // Many compilers store a single variable in sets of registers, or store a | |||
2565 | // variable partially in memory and partially in registers. DW_OP_piece | |||
2566 | // provides a way of describing how large a part of a variable a particular | |||
2567 | // DWARF expression refers to. | |||
2568 | //---------------------------------------------------------------------- | |||
2569 | case DW_OP_piece: { | |||
2570 | const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); | |||
2571 | ||||
2572 | if (piece_byte_size > 0) { | |||
2573 | Value curr_piece; | |||
2574 | ||||
2575 | if (stack.empty()) { | |||
2576 | // In a multi-piece expression, this means that the current piece is | |||
2577 | // not available. Fill with zeros for now by resizing the data and | |||
2578 | // appending it | |||
2579 | curr_piece.ResizeData(piece_byte_size); | |||
2580 | ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); | |||
2581 | pieces.AppendDataToHostBuffer(curr_piece); | |||
2582 | } else { | |||
2583 | Status error; | |||
2584 | // Extract the current piece into "curr_piece" | |||
2585 | Value curr_piece_source_value(stack.back()); | |||
2586 | stack.pop_back(); | |||
2587 | ||||
2588 | const Value::ValueType curr_piece_source_value_type = | |||
2589 | curr_piece_source_value.GetValueType(); | |||
2590 | switch (curr_piece_source_value_type) { | |||
2591 | case Value::eValueTypeLoadAddress: | |||
2592 | if (process) { | |||
2593 | if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { | |||
2594 | lldb::addr_t load_addr = | |||
2595 | curr_piece_source_value.GetScalar().ULongLong( | |||
2596 | LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
2597 | if (process->ReadMemory( | |||
2598 | load_addr, curr_piece.GetBuffer().GetBytes(), | |||
2599 | piece_byte_size, error) != piece_byte_size) { | |||
2600 | if (error_ptr) | |||
2601 | error_ptr->SetErrorStringWithFormat( | |||
2602 | "failed to read memory DW_OP_piece(%" PRIu64"l" "u" | |||
2603 | ") from 0x%" PRIx64"l" "x", | |||
2604 | piece_byte_size, load_addr); | |||
2605 | return false; | |||
2606 | } | |||
2607 | } else { | |||
2608 | if (error_ptr) | |||
2609 | error_ptr->SetErrorStringWithFormat( | |||
2610 | "failed to resize the piece memory buffer for " | |||
2611 | "DW_OP_piece(%" PRIu64"l" "u" ")", | |||
2612 | piece_byte_size); | |||
2613 | return false; | |||
2614 | } | |||
2615 | } | |||
2616 | break; | |||
2617 | ||||
2618 | case Value::eValueTypeFileAddress: | |||
2619 | case Value::eValueTypeHostAddress: | |||
2620 | if (error_ptr) { | |||
2621 | lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong( | |||
2622 | LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
2623 | error_ptr->SetErrorStringWithFormat( | |||
2624 | "failed to read memory DW_OP_piece(%" PRIu64"l" "u" | |||
2625 | ") from %s address 0x%" PRIx64"l" "x", | |||
2626 | piece_byte_size, curr_piece_source_value.GetValueType() == | |||
2627 | Value::eValueTypeFileAddress | |||
2628 | ? "file" | |||
2629 | : "host", | |||
2630 | addr); | |||
2631 | } | |||
2632 | return false; | |||
2633 | ||||
2634 | case Value::eValueTypeScalar: { | |||
2635 | uint32_t bit_size = piece_byte_size * 8; | |||
2636 | uint32_t bit_offset = 0; | |||
2637 | if (!curr_piece_source_value.GetScalar().ExtractBitfield( | |||
2638 | bit_size, bit_offset)) { | |||
2639 | if (error_ptr) | |||
2640 | error_ptr->SetErrorStringWithFormat( | |||
2641 | "unable to extract %" PRIu64"l" "u" " bytes from a %" PRIu64"l" "u" | |||
2642 | " byte scalar value.", | |||
2643 | piece_byte_size, | |||
2644 | (uint64_t)curr_piece_source_value.GetScalar() | |||
2645 | .GetByteSize()); | |||
2646 | return false; | |||
2647 | } | |||
2648 | curr_piece = curr_piece_source_value; | |||
2649 | } break; | |||
2650 | ||||
2651 | case Value::eValueTypeVector: { | |||
2652 | if (curr_piece_source_value.GetVector().length >= piece_byte_size) | |||
2653 | curr_piece_source_value.GetVector().length = piece_byte_size; | |||
2654 | else { | |||
2655 | if (error_ptr) | |||
2656 | error_ptr->SetErrorStringWithFormat( | |||
2657 | "unable to extract %" PRIu64"l" "u" " bytes from a %" PRIu64"l" "u" | |||
2658 | " byte vector value.", | |||
2659 | piece_byte_size, | |||
2660 | (uint64_t)curr_piece_source_value.GetVector().length); | |||
2661 | return false; | |||
2662 | } | |||
2663 | } break; | |||
2664 | } | |||
2665 | ||||
2666 | // Check if this is the first piece? | |||
2667 | if (op_piece_offset == 0) { | |||
2668 | // This is the first piece, we should push it back onto the stack | |||
2669 | // so subsequent pieces will be able to access this piece and add | |||
2670 | // to it | |||
2671 | if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { | |||
2672 | if (error_ptr) | |||
2673 | error_ptr->SetErrorString("failed to append piece data"); | |||
2674 | return false; | |||
2675 | } | |||
2676 | } else { | |||
2677 | // If this is the second or later piece there should be a value on | |||
2678 | // the stack | |||
2679 | if (pieces.GetBuffer().GetByteSize() != op_piece_offset) { | |||
2680 | if (error_ptr) | |||
2681 | error_ptr->SetErrorStringWithFormat( | |||
2682 | "DW_OP_piece for offset %" PRIu64"l" "u" | |||
2683 | " but top of stack is of size %" PRIu64"l" "u", | |||
2684 | op_piece_offset, pieces.GetBuffer().GetByteSize()); | |||
2685 | return false; | |||
2686 | } | |||
2687 | ||||
2688 | if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { | |||
2689 | if (error_ptr) | |||
2690 | error_ptr->SetErrorString("failed to append piece data"); | |||
2691 | return false; | |||
2692 | } | |||
2693 | } | |||
2694 | op_piece_offset += piece_byte_size; | |||
2695 | } | |||
2696 | } | |||
2697 | } break; | |||
2698 | ||||
2699 | case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); | |||
2700 | if (stack.size() < 1) { | |||
2701 | if (error_ptr) | |||
2702 | error_ptr->SetErrorString( | |||
2703 | "Expression stack needs at least 1 item for DW_OP_bit_piece."); | |||
2704 | return false; | |||
2705 | } else { | |||
2706 | const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); | |||
2707 | const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); | |||
2708 | switch (stack.back().GetValueType()) { | |||
2709 | case Value::eValueTypeScalar: { | |||
2710 | if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size, | |||
2711 | piece_bit_offset)) { | |||
2712 | if (error_ptr) | |||
2713 | error_ptr->SetErrorStringWithFormat( | |||
2714 | "unable to extract %" PRIu64"l" "u" " bit value with %" PRIu64"l" "u" | |||
2715 | " bit offset from a %" PRIu64"l" "u" " bit scalar value.", | |||
2716 | piece_bit_size, piece_bit_offset, | |||
2717 | (uint64_t)(stack.back().GetScalar().GetByteSize() * 8)); | |||
2718 | return false; | |||
2719 | } | |||
2720 | } break; | |||
2721 | ||||
2722 | case Value::eValueTypeFileAddress: | |||
2723 | case Value::eValueTypeLoadAddress: | |||
2724 | case Value::eValueTypeHostAddress: | |||
2725 | if (error_ptr) { | |||
2726 | error_ptr->SetErrorStringWithFormat( | |||
2727 | "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64"l" "u" | |||
2728 | ", bit_offset = %" PRIu64"l" "u" ") from an address value.", | |||
2729 | piece_bit_size, piece_bit_offset); | |||
2730 | } | |||
2731 | return false; | |||
2732 | ||||
2733 | case Value::eValueTypeVector: | |||
2734 | if (error_ptr) { | |||
2735 | error_ptr->SetErrorStringWithFormat( | |||
2736 | "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64"l" "u" | |||
2737 | ", bit_offset = %" PRIu64"l" "u" ") from a vector value.", | |||
2738 | piece_bit_size, piece_bit_offset); | |||
2739 | } | |||
2740 | return false; | |||
2741 | } | |||
2742 | } | |||
2743 | break; | |||
2744 | ||||
2745 | //---------------------------------------------------------------------- | |||
2746 | // OPCODE: DW_OP_push_object_address | |||
2747 | // OPERANDS: none | |||
2748 | // DESCRIPTION: Pushes the address of the object currently being | |||
2749 | // evaluated as part of evaluation of a user presented expression. This | |||
2750 | // object may correspond to an independent variable described by its own | |||
2751 | // DIE or it may be a component of an array, structure, or class whose | |||
2752 | // address has been dynamically determined by an earlier step during user | |||
2753 | // expression evaluation. | |||
2754 | //---------------------------------------------------------------------- | |||
2755 | case DW_OP_push_object_address: | |||
2756 | if (object_address_ptr) | |||
2757 | stack.push_back(*object_address_ptr); | |||
2758 | else { | |||
2759 | if (error_ptr) | |||
2760 | error_ptr->SetErrorString("DW_OP_push_object_address used without " | |||
2761 | "specifying an object address"); | |||
2762 | return false; | |||
2763 | } | |||
2764 | break; | |||
2765 | ||||
2766 | //---------------------------------------------------------------------- | |||
2767 | // OPCODE: DW_OP_call2 | |||
2768 | // OPERANDS: | |||
2769 | // uint16_t compile unit relative offset of a DIE | |||
2770 | // DESCRIPTION: Performs subroutine calls during evaluation | |||
2771 | // of a DWARF expression. The operand is the 2-byte unsigned offset of a | |||
2772 | // debugging information entry in the current compilation unit. | |||
2773 | // | |||
2774 | // Operand interpretation is exactly like that for DW_FORM_ref2. | |||
2775 | // | |||
2776 | // This operation transfers control of DWARF expression evaluation to the | |||
2777 | // DW_AT_location attribute of the referenced DIE. If there is no such | |||
2778 | // attribute, then there is no effect. Execution of the DWARF expression of | |||
2779 | // a DW_AT_location attribute may add to and/or remove from values on the | |||
2780 | // stack. Execution returns to the point following the call when the end of | |||
2781 | // the attribute is reached. Values on the stack at the time of the call | |||
2782 | // may be used as parameters by the called expression and values left on | |||
2783 | // the stack by the called expression may be used as return values by prior | |||
2784 | // agreement between the calling and called expressions. | |||
2785 | //---------------------------------------------------------------------- | |||
2786 | case DW_OP_call2: | |||
2787 | if (error_ptr) | |||
2788 | error_ptr->SetErrorString("Unimplemented opcode DW_OP_call2."); | |||
2789 | return false; | |||
2790 | //---------------------------------------------------------------------- | |||
2791 | // OPCODE: DW_OP_call4 | |||
2792 | // OPERANDS: 1 | |||
2793 | // uint32_t compile unit relative offset of a DIE | |||
2794 | // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF | |||
2795 | // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset of | |||
2796 | // a debugging information entry in the current compilation unit. | |||
2797 | // | |||
2798 | // Operand interpretation DW_OP_call4 is exactly like that for | |||
2799 | // DW_FORM_ref4. | |||
2800 | // | |||
2801 | // This operation transfers control of DWARF expression evaluation to the | |||
2802 | // DW_AT_location attribute of the referenced DIE. If there is no such | |||
2803 | // attribute, then there is no effect. Execution of the DWARF expression of | |||
2804 | // a DW_AT_location attribute may add to and/or remove from values on the | |||
2805 | // stack. Execution returns to the point following the call when the end of | |||
2806 | // the attribute is reached. Values on the stack at the time of the call | |||
2807 | // may be used as parameters by the called expression and values left on | |||
2808 | // the stack by the called expression may be used as return values by prior | |||
2809 | // agreement between the calling and called expressions. | |||
2810 | //---------------------------------------------------------------------- | |||
2811 | case DW_OP_call4: | |||
2812 | if (error_ptr) | |||
2813 | error_ptr->SetErrorString("Unimplemented opcode DW_OP_call4."); | |||
2814 | return false; | |||
2815 | ||||
2816 | //---------------------------------------------------------------------- | |||
2817 | // OPCODE: DW_OP_stack_value | |||
2818 | // OPERANDS: None | |||
2819 | // DESCRIPTION: Specifies that the object does not exist in memory but | |||
2820 | // rather is a constant value. The value from the top of the stack is the | |||
2821 | // value to be used. This is the actual object value and not the location. | |||
2822 | //---------------------------------------------------------------------- | |||
2823 | case DW_OP_stack_value: | |||
2824 | stack.back().SetValueType(Value::eValueTypeScalar); | |||
2825 | break; | |||
2826 | ||||
2827 | //---------------------------------------------------------------------- | |||
2828 | // OPCODE: DW_OP_call_frame_cfa | |||
2829 | // OPERANDS: None | |||
2830 | // DESCRIPTION: Specifies a DWARF expression that pushes the value of | |||
2831 | // the canonical frame address consistent with the call frame information | |||
2832 | // located in .debug_frame (or in the FDEs of the eh_frame section). | |||
2833 | //---------------------------------------------------------------------- | |||
2834 | case DW_OP_call_frame_cfa: | |||
2835 | if (frame) { | |||
2836 | // Note that we don't have to parse FDEs because this DWARF expression | |||
2837 | // is commonly evaluated with a valid stack frame. | |||
2838 | StackID id = frame->GetStackID(); | |||
2839 | addr_t cfa = id.GetCallFrameAddress(); | |||
2840 | if (cfa != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
2841 | stack.push_back(Scalar(cfa)); | |||
2842 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
2843 | } else if (error_ptr) | |||
2844 | error_ptr->SetErrorString("Stack frame does not include a canonical " | |||
2845 | "frame address for DW_OP_call_frame_cfa " | |||
2846 | "opcode."); | |||
2847 | } else { | |||
2848 | if (error_ptr) | |||
2849 | error_ptr->SetErrorString("Invalid stack frame in context for " | |||
2850 | "DW_OP_call_frame_cfa opcode."); | |||
2851 | return false; | |||
2852 | } | |||
2853 | break; | |||
2854 | ||||
2855 | //---------------------------------------------------------------------- | |||
2856 | // OPCODE: DW_OP_form_tls_address (or the old pre-DWARFv3 vendor extension | |||
2857 | // opcode, DW_OP_GNU_push_tls_address) | |||
2858 | // OPERANDS: none | |||
2859 | // DESCRIPTION: Pops a TLS offset from the stack, converts it to | |||
2860 | // an address in the current thread's thread-local storage block, and | |||
2861 | // pushes it on the stack. | |||
2862 | //---------------------------------------------------------------------- | |||
2863 | case DW_OP_form_tls_address: | |||
2864 | case DW_OP_GNU_push_tls_address: { | |||
2865 | if (stack.size() < 1) { | |||
2866 | if (error_ptr) { | |||
2867 | if (op == DW_OP_form_tls_address) | |||
2868 | error_ptr->SetErrorString( | |||
2869 | "DW_OP_form_tls_address needs an argument."); | |||
2870 | else | |||
2871 | error_ptr->SetErrorString( | |||
2872 | "DW_OP_GNU_push_tls_address needs an argument."); | |||
2873 | } | |||
2874 | return false; | |||
2875 | } | |||
2876 | ||||
2877 | if (!exe_ctx || !module_sp) { | |||
2878 | if (error_ptr) | |||
2879 | error_ptr->SetErrorString("No context to evaluate TLS within."); | |||
2880 | return false; | |||
2881 | } | |||
2882 | ||||
2883 | Thread *thread = exe_ctx->GetThreadPtr(); | |||
2884 | if (!thread) { | |||
2885 | if (error_ptr) | |||
2886 | error_ptr->SetErrorString("No thread to evaluate TLS within."); | |||
2887 | return false; | |||
2888 | } | |||
2889 | ||||
2890 | // Lookup the TLS block address for this thread and module. | |||
2891 | const addr_t tls_file_addr = | |||
2892 | stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS(18446744073709551615UL)); | |||
2893 | const addr_t tls_load_addr = | |||
2894 | thread->GetThreadLocalData(module_sp, tls_file_addr); | |||
2895 | ||||
2896 | if (tls_load_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
2897 | if (error_ptr) | |||
2898 | error_ptr->SetErrorString( | |||
2899 | "No TLS data currently exists for this thread."); | |||
2900 | return false; | |||
2901 | } | |||
2902 | ||||
2903 | stack.back().GetScalar() = tls_load_addr; | |||
2904 | stack.back().SetValueType(Value::eValueTypeLoadAddress); | |||
2905 | } break; | |||
2906 | ||||
2907 | //---------------------------------------------------------------------- | |||
2908 | // OPCODE: DW_OP_GNU_addr_index | |||
2909 | // OPERANDS: 1 | |||
2910 | // ULEB128: index to the .debug_addr section | |||
2911 | // DESCRIPTION: Pushes an address to the stack from the .debug_addr | |||
2912 | // section with the base address specified by the DW_AT_addr_base attribute | |||
2913 | // and the 0 based index is the ULEB128 encoded index. | |||
2914 | //---------------------------------------------------------------------- | |||
2915 | case DW_OP_GNU_addr_index: { | |||
2916 | if (!dwarf_cu) { | |||
2917 | if (error_ptr) | |||
2918 | error_ptr->SetErrorString("DW_OP_GNU_addr_index found without a " | |||
2919 | "compile unit being specified"); | |||
2920 | return false; | |||
2921 | } | |||
2922 | uint64_t index = opcodes.GetULEB128(&offset); | |||
2923 | uint32_t index_size = dwarf_cu->GetAddressByteSize(); | |||
2924 | dw_offset_t addr_base = dwarf_cu->GetAddrBase(); | |||
2925 | lldb::offset_t offset = addr_base + index * index_size; | |||
2926 | uint64_t value = | |||
2927 | dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64( | |||
2928 | &offset, index_size); | |||
2929 | stack.push_back(Scalar(value)); | |||
2930 | stack.back().SetValueType(Value::eValueTypeFileAddress); | |||
2931 | } break; | |||
2932 | ||||
2933 | //---------------------------------------------------------------------- | |||
2934 | // OPCODE: DW_OP_GNU_const_index | |||
2935 | // OPERANDS: 1 | |||
2936 | // ULEB128: index to the .debug_addr section | |||
2937 | // DESCRIPTION: Pushes an constant with the size of a machine address to | |||
2938 | // the stack from the .debug_addr section with the base address specified | |||
2939 | // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 | |||
2940 | // encoded index. | |||
2941 | //---------------------------------------------------------------------- | |||
2942 | case DW_OP_GNU_const_index: { | |||
2943 | if (!dwarf_cu) { | |||
2944 | if (error_ptr) | |||
2945 | error_ptr->SetErrorString("DW_OP_GNU_const_index found without a " | |||
2946 | "compile unit being specified"); | |||
2947 | return false; | |||
2948 | } | |||
2949 | uint64_t index = opcodes.GetULEB128(&offset); | |||
2950 | uint32_t index_size = dwarf_cu->GetAddressByteSize(); | |||
2951 | dw_offset_t addr_base = dwarf_cu->GetAddrBase(); | |||
2952 | lldb::offset_t offset = addr_base + index * index_size; | |||
2953 | const DWARFDataExtractor &debug_addr = | |||
2954 | dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data(); | |||
2955 | switch (index_size) { | |||
2956 | case 4: | |||
2957 | stack.push_back(Scalar(debug_addr.GetU32(&offset))); | |||
2958 | break; | |||
2959 | case 8: | |||
2960 | stack.push_back(Scalar(debug_addr.GetU64(&offset))); | |||
2961 | break; | |||
2962 | default: | |||
2963 | assert(false && "Unhandled index size")((false && "Unhandled index size") ? static_cast<void > (0) : __assert_fail ("false && \"Unhandled index size\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Expression/DWARFExpression.cpp" , 2963, __PRETTY_FUNCTION__)); | |||
2964 | return false; | |||
2965 | } | |||
2966 | } break; | |||
2967 | ||||
2968 | default: | |||
2969 | if (log) | |||
2970 | log->Printf("Unhandled opcode %s in DWARFExpression.", | |||
2971 | DW_OP_value_to_name(op)); | |||
2972 | break; | |||
2973 | } | |||
2974 | } | |||
2975 | ||||
2976 | if (stack.empty()) { | |||
2977 | // Nothing on the stack, check if we created a piece value from DW_OP_piece | |||
2978 | // or DW_OP_bit_piece opcodes | |||
2979 | if (pieces.GetBuffer().GetByteSize()) { | |||
2980 | result = pieces; | |||
2981 | } else { | |||
2982 | if (error_ptr) | |||
2983 | error_ptr->SetErrorString("Stack empty after evaluation."); | |||
2984 | return false; | |||
2985 | } | |||
2986 | } else { | |||
2987 | if (log && log->GetVerbose()) { | |||
2988 | size_t count = stack.size(); | |||
2989 | log->Printf("Stack after operation has %" PRIu64"l" "u" " values:", | |||
2990 | (uint64_t)count); | |||
2991 | for (size_t i = 0; i < count; ++i) { | |||
2992 | StreamString new_value; | |||
2993 | new_value.Printf("[%" PRIu64"l" "u" "]", (uint64_t)i); | |||
2994 | stack[i].Dump(&new_value); | |||
2995 | log->Printf(" %s", new_value.GetData()); | |||
2996 | } | |||
2997 | } | |||
2998 | result = stack.back(); | |||
2999 | } | |||
3000 | return true; // Return true on success | |||
3001 | } | |||
3002 | ||||
3003 | size_t DWARFExpression::LocationListSize(const DWARFUnit *dwarf_cu, | |||
3004 | const DataExtractor &debug_loc_data, | |||
3005 | lldb::offset_t offset) { | |||
3006 | const lldb::offset_t debug_loc_offset = offset; | |||
3007 | while (debug_loc_data.ValidOffset(offset)) { | |||
3008 | lldb::addr_t start_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3009 | lldb::addr_t end_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3010 | if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, | |||
3011 | start_addr, end_addr)) | |||
3012 | break; | |||
3013 | ||||
3014 | if (start_addr == 0 && end_addr == 0) | |||
3015 | break; | |||
3016 | ||||
3017 | uint16_t loc_length = debug_loc_data.GetU16(&offset); | |||
3018 | offset += loc_length; | |||
3019 | } | |||
3020 | ||||
3021 | if (offset > debug_loc_offset) | |||
3022 | return offset - debug_loc_offset; | |||
3023 | return 0; | |||
3024 | } | |||
3025 | ||||
3026 | bool DWARFExpression::AddressRangeForLocationListEntry( | |||
3027 | const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, | |||
3028 | lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) { | |||
3029 | if (!debug_loc_data.ValidOffset(*offset_ptr)) | |||
3030 | return false; | |||
3031 | ||||
3032 | DWARFExpression::LocationListFormat format = | |||
3033 | dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat(); | |||
3034 | switch (format) { | |||
3035 | case NonLocationList: | |||
3036 | return false; | |||
3037 | case RegularLocationList: | |||
3038 | low_pc = debug_loc_data.GetAddress(offset_ptr); | |||
3039 | high_pc = debug_loc_data.GetAddress(offset_ptr); | |||
3040 | return true; | |||
3041 | case SplitDwarfLocationList: | |||
3042 | case LocLists: | |||
3043 | switch (debug_loc_data.GetU8(offset_ptr)) { | |||
3044 | case DW_LLE_end_of_list: | |||
3045 | return false; | |||
3046 | case DW_LLE_startx_endx: { | |||
3047 | uint64_t index = debug_loc_data.GetULEB128(offset_ptr); | |||
3048 | low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); | |||
3049 | index = debug_loc_data.GetULEB128(offset_ptr); | |||
3050 | high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); | |||
3051 | return true; | |||
3052 | } | |||
3053 | case DW_LLE_startx_length: { | |||
3054 | uint64_t index = debug_loc_data.GetULEB128(offset_ptr); | |||
3055 | low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); | |||
3056 | uint64_t length = (format == LocLists) | |||
3057 | ? debug_loc_data.GetULEB128(offset_ptr) | |||
3058 | : debug_loc_data.GetU32(offset_ptr); | |||
3059 | high_pc = low_pc + length; | |||
3060 | return true; | |||
3061 | } | |||
3062 | case DW_LLE_start_length: { | |||
3063 | low_pc = debug_loc_data.GetAddress(offset_ptr); | |||
3064 | high_pc = low_pc + debug_loc_data.GetULEB128(offset_ptr); | |||
3065 | return true; | |||
3066 | } | |||
3067 | case DW_LLE_start_end: { | |||
3068 | low_pc = debug_loc_data.GetAddress(offset_ptr); | |||
3069 | high_pc = debug_loc_data.GetAddress(offset_ptr); | |||
3070 | return true; | |||
3071 | } | |||
3072 | default: | |||
3073 | // Not supported entry type | |||
3074 | lldbassert(false && "Not supported location list type")lldb_private::lldb_assert(static_cast<bool>(false && "Not supported location list type"), "false && \"Not supported location list type\"" , __FUNCTION__, "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Expression/DWARFExpression.cpp" , 3074); | |||
3075 | return false; | |||
3076 | } | |||
3077 | } | |||
3078 | assert(false && "Not supported location list type")((false && "Not supported location list type") ? static_cast <void> (0) : __assert_fail ("false && \"Not supported location list type\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Expression/DWARFExpression.cpp" , 3078, __PRETTY_FUNCTION__)); | |||
3079 | return false; | |||
3080 | } | |||
3081 | ||||
3082 | static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, | |||
3083 | lldb::offset_t *offset_ptr, int address_size, | |||
3084 | int dwarf_ref_size) { | |||
3085 | uint8_t opcode = data.GetU8(offset_ptr); | |||
3086 | DRC_class opcode_class; | |||
3087 | uint64_t uint; | |||
3088 | int64_t sint; | |||
3089 | ||||
3090 | int size; | |||
3091 | ||||
3092 | opcode_class = DW_OP_value_to_class(opcode) & (~DRC_DWARFv30x10); | |||
3093 | ||||
3094 | s.Printf("%s ", DW_OP_value_to_name(opcode)); | |||
3095 | ||||
3096 | /* Does this take zero parameters? If so we can shortcut this function. */ | |||
3097 | if (opcode_class == DRC_ZEROOPERANDS0x80000000) | |||
3098 | return true; | |||
3099 | ||||
3100 | if (opcode_class == DRC_TWOOPERANDS0x10000000 && opcode == DW_OP_bregx) { | |||
3101 | uint = data.GetULEB128(offset_ptr); | |||
3102 | sint = data.GetSLEB128(offset_ptr); | |||
3103 | s.Printf("%" PRIu64"l" "u" " %" PRIi64"l" "i", uint, sint); | |||
3104 | return true; | |||
3105 | } | |||
3106 | if (opcode_class != DRC_ONEOPERAND0x800) { | |||
3107 | s.Printf("UNKNOWN OP %u", opcode); | |||
3108 | return false; | |||
3109 | } | |||
3110 | ||||
3111 | switch (opcode) { | |||
3112 | case DW_OP_addr: | |||
3113 | size = address_size; | |||
3114 | break; | |||
3115 | case DW_OP_const1u: | |||
3116 | size = 1; | |||
3117 | break; | |||
3118 | case DW_OP_const1s: | |||
3119 | size = -1; | |||
3120 | break; | |||
3121 | case DW_OP_const2u: | |||
3122 | size = 2; | |||
3123 | break; | |||
3124 | case DW_OP_const2s: | |||
3125 | size = -2; | |||
3126 | break; | |||
3127 | case DW_OP_const4u: | |||
3128 | size = 4; | |||
3129 | break; | |||
3130 | case DW_OP_const4s: | |||
3131 | size = -4; | |||
3132 | break; | |||
3133 | case DW_OP_const8u: | |||
3134 | size = 8; | |||
3135 | break; | |||
3136 | case DW_OP_const8s: | |||
3137 | size = -8; | |||
3138 | break; | |||
3139 | case DW_OP_constu: | |||
3140 | size = 128; | |||
3141 | break; | |||
3142 | case DW_OP_consts: | |||
3143 | size = -128; | |||
3144 | break; | |||
3145 | case DW_OP_fbreg: | |||
3146 | size = -128; | |||
3147 | break; | |||
3148 | case DW_OP_breg0: | |||
3149 | case DW_OP_breg1: | |||
3150 | case DW_OP_breg2: | |||
3151 | case DW_OP_breg3: | |||
3152 | case DW_OP_breg4: | |||
3153 | case DW_OP_breg5: | |||
3154 | case DW_OP_breg6: | |||
3155 | case DW_OP_breg7: | |||
3156 | case DW_OP_breg8: | |||
3157 | case DW_OP_breg9: | |||
3158 | case DW_OP_breg10: | |||
3159 | case DW_OP_breg11: | |||
3160 | case DW_OP_breg12: | |||
3161 | case DW_OP_breg13: | |||
3162 | case DW_OP_breg14: | |||
3163 | case DW_OP_breg15: | |||
3164 | case DW_OP_breg16: | |||
3165 | case DW_OP_breg17: | |||
3166 | case DW_OP_breg18: | |||
3167 | case DW_OP_breg19: | |||
3168 | case DW_OP_breg20: | |||
3169 | case DW_OP_breg21: | |||
3170 | case DW_OP_breg22: | |||
3171 | case DW_OP_breg23: | |||
3172 | case DW_OP_breg24: | |||
3173 | case DW_OP_breg25: | |||
3174 | case DW_OP_breg26: | |||
3175 | case DW_OP_breg27: | |||
3176 | case DW_OP_breg28: | |||
3177 | case DW_OP_breg29: | |||
3178 | case DW_OP_breg30: | |||
3179 | case DW_OP_breg31: | |||
3180 | size = -128; | |||
3181 | break; | |||
3182 | case DW_OP_pick: | |||
3183 | case DW_OP_deref_size: | |||
3184 | case DW_OP_xderef_size: | |||
3185 | size = 1; | |||
3186 | break; | |||
3187 | case DW_OP_skip: | |||
3188 | case DW_OP_bra: | |||
3189 | size = -2; | |||
3190 | break; | |||
3191 | case DW_OP_call2: | |||
3192 | size = 2; | |||
3193 | break; | |||
3194 | case DW_OP_call4: | |||
3195 | size = 4; | |||
3196 | break; | |||
3197 | case DW_OP_call_ref: | |||
3198 | size = dwarf_ref_size; | |||
3199 | break; | |||
3200 | case DW_OP_piece: | |||
3201 | case DW_OP_plus_uconst: | |||
3202 | case DW_OP_regx: | |||
3203 | case DW_OP_GNU_addr_index: | |||
3204 | case DW_OP_GNU_const_index: | |||
3205 | size = 128; | |||
3206 | break; | |||
3207 | default: | |||
3208 | s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); | |||
3209 | return true; | |||
3210 | } | |||
3211 | ||||
3212 | switch (size) { | |||
3213 | case -1: | |||
3214 | sint = (int8_t)data.GetU8(offset_ptr); | |||
3215 | s.Printf("%+" PRIi64"l" "i", sint); | |||
3216 | break; | |||
3217 | case -2: | |||
3218 | sint = (int16_t)data.GetU16(offset_ptr); | |||
3219 | s.Printf("%+" PRIi64"l" "i", sint); | |||
3220 | break; | |||
3221 | case -4: | |||
3222 | sint = (int32_t)data.GetU32(offset_ptr); | |||
3223 | s.Printf("%+" PRIi64"l" "i", sint); | |||
3224 | break; | |||
3225 | case -8: | |||
3226 | sint = (int64_t)data.GetU64(offset_ptr); | |||
3227 | s.Printf("%+" PRIi64"l" "i", sint); | |||
3228 | break; | |||
3229 | case -128: | |||
3230 | sint = data.GetSLEB128(offset_ptr); | |||
3231 | s.Printf("%+" PRIi64"l" "i", sint); | |||
3232 | break; | |||
3233 | case 1: | |||
3234 | uint = data.GetU8(offset_ptr); | |||
3235 | s.Printf("0x%2.2" PRIx64"l" "x", uint); | |||
3236 | break; | |||
3237 | case 2: | |||
3238 | uint = data.GetU16(offset_ptr); | |||
3239 | s.Printf("0x%4.4" PRIx64"l" "x", uint); | |||
3240 | break; | |||
3241 | case 4: | |||
3242 | uint = data.GetU32(offset_ptr); | |||
3243 | s.Printf("0x%8.8" PRIx64"l" "x", uint); | |||
3244 | break; | |||
3245 | case 8: | |||
3246 | uint = data.GetU64(offset_ptr); | |||
3247 | s.Printf("0x%16.16" PRIx64"l" "x", uint); | |||
3248 | break; | |||
3249 | case 128: | |||
3250 | uint = data.GetULEB128(offset_ptr); | |||
3251 | s.Printf("0x%" PRIx64"l" "x", uint); | |||
3252 | break; | |||
3253 | } | |||
3254 | ||||
3255 | return false; | |||
3256 | } | |||
3257 | ||||
3258 | bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data, | |||
3259 | int address_size, int dwarf_ref_size, | |||
3260 | bool location_expression) { | |||
3261 | int op_count = 0; | |||
3262 | lldb::offset_t offset = 0; | |||
3263 | while (data.ValidOffset(offset)) { | |||
3264 | if (location_expression && op_count > 0) | |||
3265 | return false; | |||
3266 | if (op_count > 0) | |||
3267 | s.PutCString(", "); | |||
3268 | if (!print_dwarf_exp_op(s, data, &offset, address_size, dwarf_ref_size)) | |||
3269 | return false; | |||
3270 | op_count++; | |||
3271 | } | |||
3272 | ||||
3273 | return true; | |||
3274 | } | |||
3275 | ||||
3276 | void DWARFExpression::PrintDWARFLocationList( | |||
3277 | Stream &s, const DWARFUnit *cu, const DataExtractor &debug_loc_data, | |||
3278 | lldb::offset_t offset) { | |||
3279 | uint64_t start_addr, end_addr; | |||
3280 | uint32_t addr_size = DWARFUnit::GetAddressByteSize(cu); | |||
3281 | s.SetAddressByteSize(DWARFUnit::GetAddressByteSize(cu)); | |||
3282 | dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; | |||
3283 | while (debug_loc_data.ValidOffset(offset)) { | |||
3284 | start_addr = debug_loc_data.GetMaxU64(&offset, addr_size); | |||
3285 | end_addr = debug_loc_data.GetMaxU64(&offset, addr_size); | |||
3286 | ||||
3287 | if (start_addr == 0 && end_addr == 0) | |||
3288 | break; | |||
3289 | ||||
3290 | s.PutCString("\n "); | |||
3291 | s.Indent(); | |||
3292 | if (cu) | |||
3293 | s.AddressRange(start_addr + base_addr, end_addr + base_addr, | |||
3294 | cu->GetAddressByteSize(), NULL__null, ": "); | |||
3295 | uint32_t loc_length = debug_loc_data.GetU16(&offset); | |||
3296 | ||||
3297 | DataExtractor locationData(debug_loc_data, offset, loc_length); | |||
3298 | PrintDWARFExpression(s, locationData, addr_size, 4, false); | |||
3299 | offset += loc_length; | |||
3300 | } | |||
3301 | } | |||
3302 | ||||
3303 | bool DWARFExpression::GetOpAndEndOffsets(StackFrame &frame, | |||
3304 | lldb::offset_t &op_offset, | |||
3305 | lldb::offset_t &end_offset) { | |||
3306 | SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); | |||
3307 | if (!sc.function) { | |||
3308 | return false; | |||
3309 | } | |||
3310 | ||||
3311 | addr_t loclist_base_file_addr = | |||
3312 | sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); | |||
3313 | if (loclist_base_file_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
3314 | return false; | |||
3315 | } | |||
3316 | ||||
3317 | addr_t pc_file_addr = frame.GetFrameCodeAddress().GetFileAddress(); | |||
3318 | lldb::offset_t opcodes_offset, opcodes_length; | |||
3319 | if (!GetLocation(loclist_base_file_addr, pc_file_addr, opcodes_offset, | |||
3320 | opcodes_length)) { | |||
3321 | return false; | |||
3322 | } | |||
3323 | ||||
3324 | if (opcodes_length == 0) { | |||
3325 | return false; | |||
3326 | } | |||
3327 | ||||
3328 | op_offset = opcodes_offset; | |||
3329 | end_offset = opcodes_offset + opcodes_length; | |||
3330 | return true; | |||
3331 | } | |||
3332 | ||||
3333 | bool DWARFExpression::MatchesOperand(StackFrame &frame, | |||
3334 | const Instruction::Operand &operand) { | |||
3335 | using namespace OperandMatchers; | |||
3336 | ||||
3337 | lldb::offset_t op_offset; | |||
3338 | lldb::offset_t end_offset; | |||
3339 | if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { | |||
3340 | return false; | |||
3341 | } | |||
3342 | ||||
3343 | if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { | |||
3344 | return false; | |||
3345 | } | |||
3346 | ||||
3347 | RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); | |||
3348 | if (!reg_ctx_sp) { | |||
3349 | return false; | |||
3350 | } | |||
3351 | ||||
3352 | DataExtractor opcodes = m_data; | |||
3353 | uint8_t opcode = opcodes.GetU8(&op_offset); | |||
3354 | ||||
3355 | if (opcode == DW_OP_fbreg) { | |||
3356 | int64_t offset = opcodes.GetSLEB128(&op_offset); | |||
3357 | ||||
3358 | DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr); | |||
3359 | if (!fb_expr) { | |||
3360 | return false; | |||
3361 | } | |||
3362 | ||||
3363 | auto recurse = [&frame, fb_expr](const Instruction::Operand &child) { | |||
3364 | return fb_expr->MatchesOperand(frame, child); | |||
3365 | }; | |||
3366 | ||||
3367 | if (!offset && | |||
3368 | MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), | |||
3369 | recurse)(operand)) { | |||
3370 | return true; | |||
3371 | } | |||
3372 | ||||
3373 | return MatchUnaryOp( | |||
3374 | MatchOpType(Instruction::Operand::Type::Dereference), | |||
3375 | MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), | |||
3376 | MatchImmOp(offset), recurse))(operand); | |||
3377 | } | |||
3378 | ||||
3379 | bool dereference = false; | |||
3380 | const RegisterInfo *reg = nullptr; | |||
3381 | int64_t offset = 0; | |||
3382 | ||||
3383 | if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) { | |||
3384 | reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); | |||
3385 | } else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) { | |||
3386 | offset = opcodes.GetSLEB128(&op_offset); | |||
3387 | reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_breg0); | |||
3388 | } else if (opcode == DW_OP_regx) { | |||
3389 | uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); | |||
3390 | reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); | |||
3391 | } else if (opcode == DW_OP_bregx) { | |||
3392 | uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); | |||
3393 | offset = opcodes.GetSLEB128(&op_offset); | |||
3394 | reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); | |||
3395 | } else { | |||
3396 | return false; | |||
3397 | } | |||
3398 | ||||
3399 | if (!reg) { | |||
3400 | return false; | |||
3401 | } | |||
3402 | ||||
3403 | if (dereference) { | |||
3404 | if (!offset && | |||
3405 | MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), | |||
3406 | MatchRegOp(*reg))(operand)) { | |||
3407 | return true; | |||
3408 | } | |||
3409 | ||||
3410 | return MatchUnaryOp( | |||
3411 | MatchOpType(Instruction::Operand::Type::Dereference), | |||
3412 | MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), | |||
3413 | MatchRegOp(*reg), | |||
3414 | MatchImmOp(offset)))(operand); | |||
3415 | } else { | |||
3416 | return MatchRegOp(*reg)(operand); | |||
3417 | } | |||
3418 | } | |||
3419 |