1 | //===-- IRInterpreter.cpp -------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Expression/IRInterpreter.h" |
10 | #include "lldb/Core/Debugger.h" |
11 | #include "lldb/Core/Module.h" |
12 | #include "lldb/Core/ModuleSpec.h" |
13 | #include "lldb/Expression/DiagnosticManager.h" |
14 | #include "lldb/Expression/IRExecutionUnit.h" |
15 | #include "lldb/Expression/IRMemoryMap.h" |
16 | #include "lldb/Utility/ConstString.h" |
17 | #include "lldb/Utility/DataExtractor.h" |
18 | #include "lldb/Utility/Endian.h" |
19 | #include "lldb/Utility/LLDBLog.h" |
20 | #include "lldb/Utility/Log.h" |
21 | #include "lldb/Utility/Scalar.h" |
22 | #include "lldb/Utility/Status.h" |
23 | #include "lldb/Utility/StreamString.h" |
24 | #include "lldb/ValueObject/ValueObject.h" |
25 | |
26 | #include "lldb/Target/ABI.h" |
27 | #include "lldb/Target/ExecutionContext.h" |
28 | #include "lldb/Target/Target.h" |
29 | #include "lldb/Target/Thread.h" |
30 | #include "lldb/Target/ThreadPlan.h" |
31 | #include "lldb/Target/ThreadPlanCallFunctionUsingABI.h" |
32 | |
33 | #include "llvm/IR/Constants.h" |
34 | #include "llvm/IR/DataLayout.h" |
35 | #include "llvm/IR/Function.h" |
36 | #include "llvm/IR/Instructions.h" |
37 | #include "llvm/IR/Intrinsics.h" |
38 | #include "llvm/IR/LLVMContext.h" |
39 | #include "llvm/IR/Module.h" |
40 | #include "llvm/IR/Operator.h" |
41 | #include "llvm/Support/raw_ostream.h" |
42 | |
43 | #include <map> |
44 | |
45 | using namespace llvm; |
46 | using lldb_private::LLDBLog; |
47 | |
48 | static std::string PrintValue(const Value *value, bool truncate = false) { |
49 | std::string s; |
50 | raw_string_ostream rso(s); |
51 | value->print(O&: rso); |
52 | if (truncate) |
53 | s.resize(n: s.length() - 1); |
54 | |
55 | size_t offset; |
56 | while ((offset = s.find(c: '\n')) != s.npos) |
57 | s.erase(pos: offset, n: 1); |
58 | while (s[0] == ' ' || s[0] == '\t') |
59 | s.erase(pos: 0, n: 1); |
60 | |
61 | return s; |
62 | } |
63 | |
64 | static std::string PrintType(const Type *type, bool truncate = false) { |
65 | std::string s; |
66 | raw_string_ostream rso(s); |
67 | type->print(O&: rso); |
68 | if (truncate) |
69 | s.resize(n: s.length() - 1); |
70 | return s; |
71 | } |
72 | |
73 | static bool CanIgnoreCall(const CallInst *call) { |
74 | const llvm::Function *called_function = call->getCalledFunction(); |
75 | |
76 | if (!called_function) |
77 | return false; |
78 | |
79 | if (called_function->isIntrinsic()) { |
80 | switch (called_function->getIntrinsicID()) { |
81 | default: |
82 | break; |
83 | case llvm::Intrinsic::dbg_declare: |
84 | case llvm::Intrinsic::dbg_value: |
85 | return true; |
86 | } |
87 | } |
88 | |
89 | return false; |
90 | } |
91 | |
92 | class InterpreterStackFrame { |
93 | public: |
94 | typedef std::map<const Value *, lldb::addr_t> ValueMap; |
95 | |
96 | ValueMap m_values; |
97 | const DataLayout &m_target_data; |
98 | lldb_private::IRExecutionUnit &m_execution_unit; |
99 | const BasicBlock *m_bb = nullptr; |
100 | const BasicBlock *m_prev_bb = nullptr; |
101 | BasicBlock::const_iterator m_ii; |
102 | BasicBlock::const_iterator m_ie; |
103 | |
104 | lldb::addr_t m_frame_process_address; |
105 | size_t m_frame_size; |
106 | lldb::addr_t m_stack_pointer; |
107 | |
108 | lldb::ByteOrder m_byte_order; |
109 | size_t m_addr_byte_size; |
110 | |
111 | InterpreterStackFrame(const DataLayout &target_data, |
112 | lldb_private::IRExecutionUnit &execution_unit, |
113 | lldb::addr_t stack_frame_bottom, |
114 | lldb::addr_t stack_frame_top) |
115 | : m_target_data(target_data), m_execution_unit(execution_unit) { |
116 | m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle |
117 | : lldb::eByteOrderBig); |
118 | m_addr_byte_size = (target_data.getPointerSize(AS: 0)); |
119 | |
120 | m_frame_process_address = stack_frame_bottom; |
121 | m_frame_size = stack_frame_top - stack_frame_bottom; |
122 | m_stack_pointer = stack_frame_top; |
123 | } |
124 | |
125 | ~InterpreterStackFrame() = default; |
126 | |
127 | void Jump(const BasicBlock *bb) { |
128 | m_prev_bb = m_bb; |
129 | m_bb = bb; |
130 | m_ii = m_bb->begin(); |
131 | m_ie = m_bb->end(); |
132 | } |
133 | |
134 | std::string SummarizeValue(const Value *value) { |
135 | lldb_private::StreamString ss; |
136 | |
137 | ss.Printf(format: "%s", PrintValue(value).c_str()); |
138 | |
139 | ValueMap::iterator i = m_values.find(x: value); |
140 | |
141 | if (i != m_values.end()) { |
142 | lldb::addr_t addr = i->second; |
143 | |
144 | ss.Printf(format: " 0x%llx", (unsigned long long)addr); |
145 | } |
146 | |
147 | return std::string(ss.GetString()); |
148 | } |
149 | |
150 | bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value, |
151 | Type *type) { |
152 | size_t type_size = m_target_data.getTypeStoreSize(Ty: type); |
153 | |
154 | if (type_size > 8) |
155 | return false; |
156 | |
157 | if (type_size != 1) |
158 | type_size = PowerOf2Ceil(A: type_size); |
159 | |
160 | scalar = value.zextOrTrunc(width: type_size * 8); |
161 | return true; |
162 | } |
163 | |
164 | bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value, |
165 | Module &module) { |
166 | const Constant *constant = dyn_cast<Constant>(Val: value); |
167 | |
168 | if (constant) { |
169 | if (constant->getValueID() == Value::ConstantFPVal) { |
170 | if (auto *cfp = dyn_cast<ConstantFP>(Val: constant)) { |
171 | if (cfp->getType()->isDoubleTy()) |
172 | scalar = cfp->getValueAPF().convertToDouble(); |
173 | else if (cfp->getType()->isFloatTy()) |
174 | scalar = cfp->getValueAPF().convertToFloat(); |
175 | else |
176 | return false; |
177 | return true; |
178 | } |
179 | return false; |
180 | } |
181 | APInt value_apint; |
182 | |
183 | if (!ResolveConstantValue(value&: value_apint, constant)) |
184 | return false; |
185 | |
186 | return AssignToMatchType(scalar, value: value_apint, type: value->getType()); |
187 | } |
188 | |
189 | lldb::addr_t process_address = ResolveValue(value, module); |
190 | size_t value_size = m_target_data.getTypeStoreSize(Ty: value->getType()); |
191 | |
192 | lldb_private::DataExtractor value_extractor; |
193 | lldb_private::Status extract_error; |
194 | |
195 | m_execution_unit.GetMemoryData(extractor&: value_extractor, process_address, |
196 | size: value_size, error&: extract_error); |
197 | |
198 | if (!extract_error.Success()) |
199 | return false; |
200 | |
201 | lldb::offset_t offset = 0; |
202 | if (value_size <= 8) { |
203 | Type *ty = value->getType(); |
204 | if (ty->isDoubleTy()) { |
205 | scalar = value_extractor.GetDouble(offset_ptr: &offset); |
206 | return true; |
207 | } else if (ty->isFloatTy()) { |
208 | scalar = value_extractor.GetFloat(offset_ptr: &offset); |
209 | return true; |
210 | } else { |
211 | uint64_t u64value = value_extractor.GetMaxU64(offset_ptr: &offset, byte_size: value_size); |
212 | return AssignToMatchType(scalar, value: llvm::APInt(64, u64value), |
213 | type: value->getType()); |
214 | } |
215 | } |
216 | |
217 | return false; |
218 | } |
219 | |
220 | bool AssignValue(const Value *value, lldb_private::Scalar scalar, |
221 | Module &module) { |
222 | lldb::addr_t process_address = ResolveValue(value, module); |
223 | |
224 | if (process_address == LLDB_INVALID_ADDRESS) |
225 | return false; |
226 | |
227 | lldb_private::Scalar cast_scalar; |
228 | Type *vty = value->getType(); |
229 | if (vty->isFloatTy() || vty->isDoubleTy()) { |
230 | cast_scalar = scalar; |
231 | } else { |
232 | scalar.MakeUnsigned(); |
233 | if (!AssignToMatchType(scalar&: cast_scalar, value: scalar.UInt128(fail_value: llvm::APInt()), |
234 | type: value->getType())) |
235 | return false; |
236 | } |
237 | |
238 | size_t value_byte_size = m_target_data.getTypeStoreSize(Ty: value->getType()); |
239 | |
240 | lldb_private::DataBufferHeap buf(value_byte_size, 0); |
241 | |
242 | lldb_private::Status get_data_error; |
243 | |
244 | if (!cast_scalar.GetAsMemoryData(dst: buf.GetBytes(), dst_len: buf.GetByteSize(), |
245 | dst_byte_order: m_byte_order, error&: get_data_error)) |
246 | return false; |
247 | |
248 | lldb_private::Status write_error; |
249 | |
250 | m_execution_unit.WriteMemory(process_address, bytes: buf.GetBytes(), |
251 | size: buf.GetByteSize(), error&: write_error); |
252 | |
253 | return write_error.Success(); |
254 | } |
255 | |
256 | bool ResolveConstantValue(APInt &value, const Constant *constant) { |
257 | switch (constant->getValueID()) { |
258 | default: |
259 | break; |
260 | case Value::FunctionVal: |
261 | if (const Function *constant_func = dyn_cast<Function>(Val: constant)) { |
262 | lldb_private::ConstString name(constant_func->getName()); |
263 | bool missing_weak = false; |
264 | lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak); |
265 | if (addr == LLDB_INVALID_ADDRESS) |
266 | return false; |
267 | value = APInt(m_target_data.getPointerSizeInBits(), addr); |
268 | return true; |
269 | } |
270 | break; |
271 | case Value::ConstantIntVal: |
272 | if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(Val: constant)) { |
273 | value = constant_int->getValue(); |
274 | return true; |
275 | } |
276 | break; |
277 | case Value::ConstantFPVal: |
278 | if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(Val: constant)) { |
279 | value = constant_fp->getValueAPF().bitcastToAPInt(); |
280 | return true; |
281 | } |
282 | break; |
283 | case Value::ConstantExprVal: |
284 | if (const ConstantExpr *constant_expr = |
285 | dyn_cast<ConstantExpr>(Val: constant)) { |
286 | switch (constant_expr->getOpcode()) { |
287 | default: |
288 | return false; |
289 | case Instruction::IntToPtr: |
290 | case Instruction::PtrToInt: |
291 | case Instruction::BitCast: |
292 | return ResolveConstantValue(value, constant: constant_expr->getOperand(i_nocapture: 0)); |
293 | case Instruction::GetElementPtr: { |
294 | ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); |
295 | ConstantExpr::const_op_iterator op_end = constant_expr->op_end(); |
296 | |
297 | Constant *base = dyn_cast<Constant>(Val: *op_cursor); |
298 | |
299 | if (!base) |
300 | return false; |
301 | |
302 | if (!ResolveConstantValue(value, constant: base)) |
303 | return false; |
304 | |
305 | op_cursor++; |
306 | |
307 | if (op_cursor == op_end) |
308 | return true; // no offset to apply! |
309 | |
310 | SmallVector<Value *, 8> indices(op_cursor, op_end); |
311 | Type *src_elem_ty = |
312 | cast<GEPOperator>(Val: constant_expr)->getSourceElementType(); |
313 | |
314 | // DataLayout::getIndexedOffsetInType assumes the indices are |
315 | // instances of ConstantInt. |
316 | uint64_t offset = |
317 | m_target_data.getIndexedOffsetInType(ElemTy: src_elem_ty, Indices: indices); |
318 | |
319 | const bool is_signed = true; |
320 | value += APInt(value.getBitWidth(), offset, is_signed); |
321 | |
322 | return true; |
323 | } |
324 | } |
325 | } |
326 | break; |
327 | case Value::ConstantPointerNullVal: |
328 | if (isa<ConstantPointerNull>(Val: constant)) { |
329 | value = APInt(m_target_data.getPointerSizeInBits(), 0); |
330 | return true; |
331 | } |
332 | break; |
333 | } |
334 | return false; |
335 | } |
336 | |
337 | bool MakeArgument(const Argument *value, uint64_t address) { |
338 | lldb::addr_t data_address = Malloc(type: value->getType()); |
339 | |
340 | if (data_address == LLDB_INVALID_ADDRESS) |
341 | return false; |
342 | |
343 | lldb_private::Status write_error; |
344 | |
345 | m_execution_unit.WritePointerToMemory(process_address: data_address, address, error&: write_error); |
346 | |
347 | if (!write_error.Success()) { |
348 | lldb_private::Status free_error; |
349 | m_execution_unit.Free(process_address: data_address, error&: free_error); |
350 | return false; |
351 | } |
352 | |
353 | m_values[value] = data_address; |
354 | |
355 | lldb_private::Log *log(GetLog(mask: LLDBLog::Expressions)); |
356 | |
357 | if (log) { |
358 | LLDB_LOGF(log, "Made an allocation for argument %s", |
359 | PrintValue(value).c_str()); |
360 | LLDB_LOGF(log, " Data region : %llx", (unsigned long long)address); |
361 | LLDB_LOGF(log, " Ref region : %llx", |
362 | (unsigned long long)data_address); |
363 | } |
364 | |
365 | return true; |
366 | } |
367 | |
368 | bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) { |
369 | APInt resolved_value; |
370 | |
371 | if (!ResolveConstantValue(value&: resolved_value, constant)) |
372 | return false; |
373 | |
374 | size_t constant_size = m_target_data.getTypeStoreSize(Ty: constant->getType()); |
375 | lldb_private::DataBufferHeap buf(constant_size, 0); |
376 | |
377 | lldb_private::Status get_data_error; |
378 | |
379 | lldb_private::Scalar resolved_scalar( |
380 | resolved_value.zextOrTrunc(width: llvm::NextPowerOf2(A: constant_size) * 8)); |
381 | if (!resolved_scalar.GetAsMemoryData(dst: buf.GetBytes(), dst_len: buf.GetByteSize(), |
382 | dst_byte_order: m_byte_order, error&: get_data_error)) |
383 | return false; |
384 | |
385 | lldb_private::Status write_error; |
386 | |
387 | m_execution_unit.WriteMemory(process_address, bytes: buf.GetBytes(), |
388 | size: buf.GetByteSize(), error&: write_error); |
389 | |
390 | return write_error.Success(); |
391 | } |
392 | |
393 | lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) { |
394 | lldb::addr_t ret = m_stack_pointer; |
395 | |
396 | ret -= size; |
397 | ret -= (ret % byte_alignment); |
398 | |
399 | if (ret < m_frame_process_address) |
400 | return LLDB_INVALID_ADDRESS; |
401 | |
402 | m_stack_pointer = ret; |
403 | return ret; |
404 | } |
405 | |
406 | lldb::addr_t Malloc(llvm::Type *type) { |
407 | lldb_private::Status alloc_error; |
408 | |
409 | return Malloc(size: m_target_data.getTypeAllocSize(Ty: type), |
410 | byte_alignment: m_target_data.getPrefTypeAlign(Ty: type).value()); |
411 | } |
412 | |
413 | std::string PrintData(lldb::addr_t addr, llvm::Type *type) { |
414 | size_t length = m_target_data.getTypeStoreSize(Ty: type); |
415 | |
416 | lldb_private::DataBufferHeap buf(length, 0); |
417 | |
418 | lldb_private::Status read_error; |
419 | |
420 | m_execution_unit.ReadMemory(bytes: buf.GetBytes(), process_address: addr, size: length, error&: read_error); |
421 | |
422 | if (!read_error.Success()) |
423 | return std::string("<couldn't read data>"); |
424 | |
425 | lldb_private::StreamString ss; |
426 | |
427 | for (size_t i = 0; i < length; i++) { |
428 | if ((!(i & 0xf)) && i) |
429 | ss.Printf(format: "%02hhx - ", buf.GetBytes()[i]); |
430 | else |
431 | ss.Printf(format: "%02hhx ", buf.GetBytes()[i]); |
432 | } |
433 | |
434 | return std::string(ss.GetString()); |
435 | } |
436 | |
437 | lldb::addr_t ResolveValue(const Value *value, Module &module) { |
438 | ValueMap::iterator i = m_values.find(x: value); |
439 | |
440 | if (i != m_values.end()) |
441 | return i->second; |
442 | |
443 | // Fall back and allocate space [allocation type Alloca] |
444 | |
445 | lldb::addr_t data_address = Malloc(type: value->getType()); |
446 | |
447 | if (const Constant *constant = dyn_cast<Constant>(Val: value)) { |
448 | if (!ResolveConstant(process_address: data_address, constant)) { |
449 | lldb_private::Status free_error; |
450 | m_execution_unit.Free(process_address: data_address, error&: free_error); |
451 | return LLDB_INVALID_ADDRESS; |
452 | } |
453 | } |
454 | |
455 | m_values[value] = data_address; |
456 | return data_address; |
457 | } |
458 | }; |
459 | |
460 | static const char *unsupported_opcode_error = |
461 | "Interpreter doesn't handle one of the expression's opcodes"; |
462 | static const char *unsupported_operand_error = |
463 | "Interpreter doesn't handle one of the expression's operands"; |
464 | static const char *interpreter_internal_error = |
465 | "Interpreter encountered an internal error"; |
466 | static const char *interrupt_error = |
467 | "Interrupted while interpreting expression"; |
468 | static const char *bad_value_error = |
469 | "Interpreter couldn't resolve a value during execution"; |
470 | static const char *memory_allocation_error = |
471 | "Interpreter couldn't allocate memory"; |
472 | static const char *memory_write_error = "Interpreter couldn't write to memory"; |
473 | static const char *memory_read_error = "Interpreter couldn't read from memory"; |
474 | static const char *timeout_error = |
475 | "Reached timeout while interpreting expression"; |
476 | static const char *too_many_functions_error = |
477 | "Interpreter doesn't handle modules with multiple function bodies."; |
478 | |
479 | static bool CanResolveConstant(llvm::Constant *constant) { |
480 | switch (constant->getValueID()) { |
481 | default: |
482 | return false; |
483 | case Value::ConstantIntVal: |
484 | case Value::ConstantFPVal: |
485 | case Value::FunctionVal: |
486 | return true; |
487 | case Value::ConstantExprVal: |
488 | if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(Val: constant)) { |
489 | switch (constant_expr->getOpcode()) { |
490 | default: |
491 | return false; |
492 | case Instruction::IntToPtr: |
493 | case Instruction::PtrToInt: |
494 | case Instruction::BitCast: |
495 | return CanResolveConstant(constant: constant_expr->getOperand(i_nocapture: 0)); |
496 | case Instruction::GetElementPtr: { |
497 | // Check that the base can be constant-resolved. |
498 | ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); |
499 | Constant *base = dyn_cast<Constant>(Val: *op_cursor); |
500 | if (!base || !CanResolveConstant(constant: base)) |
501 | return false; |
502 | |
503 | // Check that all other operands are just ConstantInt. |
504 | for (Value *op : make_range(x: constant_expr->op_begin() + 1, |
505 | y: constant_expr->op_end())) { |
506 | ConstantInt *constant_int = dyn_cast<ConstantInt>(Val: op); |
507 | if (!constant_int) |
508 | return false; |
509 | } |
510 | return true; |
511 | } |
512 | } |
513 | } else { |
514 | return false; |
515 | } |
516 | case Value::ConstantPointerNullVal: |
517 | return true; |
518 | } |
519 | } |
520 | |
521 | bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, |
522 | lldb_private::Status &error, |
523 | const bool support_function_calls) { |
524 | lldb_private::Log *log(GetLog(mask: LLDBLog::Expressions)); |
525 | |
526 | bool saw_function_with_body = false; |
527 | for (Function &f : module) { |
528 | if (f.begin() != f.end()) { |
529 | if (saw_function_with_body) { |
530 | LLDB_LOGF(log, "More than one function in the module has a body"); |
531 | error = lldb_private::Status::FromErrorString(str: too_many_functions_error); |
532 | return false; |
533 | } |
534 | saw_function_with_body = true; |
535 | LLDB_LOGF(log, "Saw function with body: %s", f.getName().str().c_str()); |
536 | } |
537 | } |
538 | |
539 | for (BasicBlock &bb : function) { |
540 | for (Instruction &ii : bb) { |
541 | switch (ii.getOpcode()) { |
542 | default: { |
543 | LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str()); |
544 | error = lldb_private::Status::FromErrorString(str: unsupported_opcode_error); |
545 | return false; |
546 | } |
547 | case Instruction::Add: |
548 | case Instruction::Alloca: |
549 | case Instruction::BitCast: |
550 | case Instruction::Br: |
551 | case Instruction::PHI: |
552 | break; |
553 | case Instruction::Call: { |
554 | CallInst *call_inst = dyn_cast<CallInst>(Val: &ii); |
555 | |
556 | if (!call_inst) { |
557 | error = |
558 | lldb_private::Status::FromErrorString(str: interpreter_internal_error); |
559 | return false; |
560 | } |
561 | |
562 | if (!CanIgnoreCall(call: call_inst) && !support_function_calls) { |
563 | LLDB_LOGF(log, "Unsupported instruction: %s", |
564 | PrintValue(&ii).c_str()); |
565 | error = |
566 | lldb_private::Status::FromErrorString(str: unsupported_opcode_error); |
567 | return false; |
568 | } |
569 | } break; |
570 | case Instruction::GetElementPtr: |
571 | break; |
572 | case Instruction::FCmp: |
573 | case Instruction::ICmp: { |
574 | CmpInst *cmp_inst = dyn_cast<CmpInst>(Val: &ii); |
575 | |
576 | if (!cmp_inst) { |
577 | error = |
578 | lldb_private::Status::FromErrorString(str: interpreter_internal_error); |
579 | return false; |
580 | } |
581 | |
582 | switch (cmp_inst->getPredicate()) { |
583 | default: { |
584 | LLDB_LOGF(log, "Unsupported ICmp predicate: %s", |
585 | PrintValue(&ii).c_str()); |
586 | |
587 | error = |
588 | lldb_private::Status::FromErrorString(str: unsupported_opcode_error); |
589 | return false; |
590 | } |
591 | case CmpInst::FCMP_OEQ: |
592 | case CmpInst::ICMP_EQ: |
593 | case CmpInst::FCMP_UNE: |
594 | case CmpInst::ICMP_NE: |
595 | case CmpInst::FCMP_OGT: |
596 | case CmpInst::ICMP_UGT: |
597 | case CmpInst::FCMP_OGE: |
598 | case CmpInst::ICMP_UGE: |
599 | case CmpInst::FCMP_OLT: |
600 | case CmpInst::ICMP_ULT: |
601 | case CmpInst::FCMP_OLE: |
602 | case CmpInst::ICMP_ULE: |
603 | case CmpInst::ICMP_SGT: |
604 | case CmpInst::ICMP_SGE: |
605 | case CmpInst::ICMP_SLT: |
606 | case CmpInst::ICMP_SLE: |
607 | break; |
608 | } |
609 | } break; |
610 | case Instruction::And: |
611 | case Instruction::AShr: |
612 | case Instruction::IntToPtr: |
613 | case Instruction::PtrToInt: |
614 | case Instruction::Load: |
615 | case Instruction::LShr: |
616 | case Instruction::Mul: |
617 | case Instruction::Or: |
618 | case Instruction::Ret: |
619 | case Instruction::SDiv: |
620 | case Instruction::SExt: |
621 | case Instruction::Shl: |
622 | case Instruction::SRem: |
623 | case Instruction::Store: |
624 | case Instruction::Sub: |
625 | case Instruction::Trunc: |
626 | case Instruction::UDiv: |
627 | case Instruction::URem: |
628 | case Instruction::Xor: |
629 | case Instruction::ZExt: |
630 | break; |
631 | case Instruction::FAdd: |
632 | case Instruction::FSub: |
633 | case Instruction::FMul: |
634 | case Instruction::FDiv: |
635 | break; |
636 | } |
637 | |
638 | for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) { |
639 | Value *operand = ii.getOperand(i: oi); |
640 | Type *operand_type = operand->getType(); |
641 | |
642 | switch (operand_type->getTypeID()) { |
643 | default: |
644 | break; |
645 | case Type::FixedVectorTyID: |
646 | case Type::ScalableVectorTyID: { |
647 | LLDB_LOGF(log, "Unsupported operand type: %s", |
648 | PrintType(operand_type).c_str()); |
649 | error = |
650 | lldb_private::Status::FromErrorString(str: unsupported_operand_error); |
651 | return false; |
652 | } |
653 | } |
654 | |
655 | // The IR interpreter currently doesn't know about |
656 | // 128-bit integers. As they're not that frequent, |
657 | // we can just fall back to the JIT rather than |
658 | // choking. |
659 | if (operand_type->getPrimitiveSizeInBits() > 64) { |
660 | LLDB_LOGF(log, "Unsupported operand type: %s", |
661 | PrintType(operand_type).c_str()); |
662 | error = |
663 | lldb_private::Status::FromErrorString(str: unsupported_operand_error); |
664 | return false; |
665 | } |
666 | |
667 | if (Constant *constant = llvm::dyn_cast<Constant>(Val: operand)) { |
668 | if (!CanResolveConstant(constant)) { |
669 | LLDB_LOGF(log, "Unsupported constant: %s", |
670 | PrintValue(constant).c_str()); |
671 | error = lldb_private::Status::FromErrorString( |
672 | str: unsupported_operand_error); |
673 | return false; |
674 | } |
675 | } |
676 | } |
677 | } |
678 | } |
679 | |
680 | return true; |
681 | } |
682 | |
683 | bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, |
684 | llvm::ArrayRef<lldb::addr_t> args, |
685 | lldb_private::IRExecutionUnit &execution_unit, |
686 | lldb_private::Status &error, |
687 | lldb::addr_t stack_frame_bottom, |
688 | lldb::addr_t stack_frame_top, |
689 | lldb_private::ExecutionContext &exe_ctx, |
690 | lldb_private::Timeout<std::micro> timeout) { |
691 | lldb_private::Log *log(GetLog(mask: LLDBLog::Expressions)); |
692 | |
693 | if (log) { |
694 | std::string s; |
695 | raw_string_ostream oss(s); |
696 | |
697 | module.print(OS&: oss, AAW: nullptr); |
698 | |
699 | LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"", |
700 | s.c_str()); |
701 | } |
702 | |
703 | const DataLayout &data_layout = module.getDataLayout(); |
704 | |
705 | InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom, |
706 | stack_frame_top); |
707 | |
708 | if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) { |
709 | error = |
710 | lldb_private::Status::FromErrorString(str: "Couldn't allocate stack frame"); |
711 | } |
712 | |
713 | int arg_index = 0; |
714 | |
715 | for (llvm::Function::arg_iterator ai = function.arg_begin(), |
716 | ae = function.arg_end(); |
717 | ai != ae; ++ai, ++arg_index) { |
718 | if (args.size() <= static_cast<size_t>(arg_index)) { |
719 | error = lldb_private::Status::FromErrorString( |
720 | str: "Not enough arguments passed in to function"); |
721 | return false; |
722 | } |
723 | |
724 | lldb::addr_t ptr = args[arg_index]; |
725 | |
726 | frame.MakeArgument(value: &*ai, address: ptr); |
727 | } |
728 | |
729 | frame.Jump(bb: &function.front()); |
730 | |
731 | lldb_private::Process *process = exe_ctx.GetProcessPtr(); |
732 | lldb_private::Target *target = exe_ctx.GetTargetPtr(); |
733 | |
734 | using clock = std::chrono::steady_clock; |
735 | |
736 | // Compute the time at which the timeout has been exceeded. |
737 | std::optional<clock::time_point> end_time; |
738 | if (timeout && timeout->count() > 0) |
739 | end_time = clock::now() + *timeout; |
740 | |
741 | while (frame.m_ii != frame.m_ie) { |
742 | // Timeout reached: stop interpreting. |
743 | if (end_time && clock::now() >= *end_time) { |
744 | error = lldb_private::Status::FromErrorString(str: timeout_error); |
745 | return false; |
746 | } |
747 | |
748 | // If we have access to the debugger we can honor an interrupt request. |
749 | if (target) { |
750 | if (INTERRUPT_REQUESTED(target->GetDebugger(), |
751 | "Interrupted in IR interpreting.")) { |
752 | error = lldb_private::Status::FromErrorString(str: interrupt_error); |
753 | return false; |
754 | } |
755 | } |
756 | |
757 | const Instruction *inst = &*frame.m_ii; |
758 | |
759 | LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str()); |
760 | |
761 | switch (inst->getOpcode()) { |
762 | default: |
763 | break; |
764 | |
765 | case Instruction::Add: |
766 | case Instruction::Sub: |
767 | case Instruction::Mul: |
768 | case Instruction::SDiv: |
769 | case Instruction::UDiv: |
770 | case Instruction::SRem: |
771 | case Instruction::URem: |
772 | case Instruction::Shl: |
773 | case Instruction::LShr: |
774 | case Instruction::AShr: |
775 | case Instruction::And: |
776 | case Instruction::Or: |
777 | case Instruction::Xor: |
778 | case Instruction::FAdd: |
779 | case Instruction::FSub: |
780 | case Instruction::FMul: |
781 | case Instruction::FDiv: { |
782 | const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(Val: inst); |
783 | |
784 | if (!bin_op) { |
785 | LLDB_LOGF( |
786 | log, |
787 | "getOpcode() returns %s, but instruction is not a BinaryOperator", |
788 | inst->getOpcodeName()); |
789 | error = |
790 | lldb_private::Status::FromErrorString(str: interpreter_internal_error); |
791 | return false; |
792 | } |
793 | |
794 | Value *lhs = inst->getOperand(i: 0); |
795 | Value *rhs = inst->getOperand(i: 1); |
796 | |
797 | lldb_private::Scalar L; |
798 | lldb_private::Scalar R; |
799 | |
800 | if (!frame.EvaluateValue(scalar&: L, value: lhs, module)) { |
801 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str()); |
802 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
803 | return false; |
804 | } |
805 | |
806 | if (!frame.EvaluateValue(scalar&: R, value: rhs, module)) { |
807 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str()); |
808 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
809 | return false; |
810 | } |
811 | |
812 | lldb_private::Scalar result; |
813 | |
814 | switch (inst->getOpcode()) { |
815 | default: |
816 | break; |
817 | case Instruction::Add: |
818 | case Instruction::FAdd: |
819 | result = L + R; |
820 | break; |
821 | case Instruction::Mul: |
822 | case Instruction::FMul: |
823 | result = L * R; |
824 | break; |
825 | case Instruction::Sub: |
826 | case Instruction::FSub: |
827 | result = L - R; |
828 | break; |
829 | case Instruction::SDiv: |
830 | L.MakeSigned(); |
831 | R.MakeSigned(); |
832 | result = L / R; |
833 | break; |
834 | case Instruction::UDiv: |
835 | L.MakeUnsigned(); |
836 | R.MakeUnsigned(); |
837 | result = L / R; |
838 | break; |
839 | case Instruction::FDiv: |
840 | result = L / R; |
841 | break; |
842 | case Instruction::SRem: |
843 | L.MakeSigned(); |
844 | R.MakeSigned(); |
845 | result = L % R; |
846 | break; |
847 | case Instruction::URem: |
848 | L.MakeUnsigned(); |
849 | R.MakeUnsigned(); |
850 | result = L % R; |
851 | break; |
852 | case Instruction::Shl: |
853 | result = L << R; |
854 | break; |
855 | case Instruction::AShr: |
856 | result = L >> R; |
857 | break; |
858 | case Instruction::LShr: |
859 | result = L; |
860 | result.ShiftRightLogical(rhs: R); |
861 | break; |
862 | case Instruction::And: |
863 | result = L & R; |
864 | break; |
865 | case Instruction::Or: |
866 | result = L | R; |
867 | break; |
868 | case Instruction::Xor: |
869 | result = L ^ R; |
870 | break; |
871 | } |
872 | |
873 | frame.AssignValue(value: inst, scalar: result, module); |
874 | |
875 | if (log) { |
876 | LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName()); |
877 | LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str()); |
878 | LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str()); |
879 | LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); |
880 | } |
881 | } break; |
882 | case Instruction::Alloca: { |
883 | const AllocaInst *alloca_inst = cast<AllocaInst>(Val: inst); |
884 | |
885 | if (alloca_inst->isArrayAllocation()) { |
886 | LLDB_LOGF(log, |
887 | "AllocaInsts are not handled if isArrayAllocation() is true"); |
888 | error = lldb_private::Status::FromErrorString(str: unsupported_opcode_error); |
889 | return false; |
890 | } |
891 | |
892 | // The semantics of Alloca are: |
893 | // Create a region R of virtual memory of type T, backed by a data |
894 | // buffer |
895 | // Create a region P of virtual memory of type T*, backed by a data |
896 | // buffer |
897 | // Write the virtual address of R into P |
898 | |
899 | Type *T = alloca_inst->getAllocatedType(); |
900 | Type *Tptr = alloca_inst->getType(); |
901 | |
902 | lldb::addr_t R = frame.Malloc(type: T); |
903 | |
904 | if (R == LLDB_INVALID_ADDRESS) { |
905 | LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst"); |
906 | error = lldb_private::Status::FromErrorString(str: memory_allocation_error); |
907 | return false; |
908 | } |
909 | |
910 | lldb::addr_t P = frame.Malloc(type: Tptr); |
911 | |
912 | if (P == LLDB_INVALID_ADDRESS) { |
913 | LLDB_LOGF(log, |
914 | "Couldn't allocate the result pointer for an AllocaInst"); |
915 | error = lldb_private::Status::FromErrorString(str: memory_allocation_error); |
916 | return false; |
917 | } |
918 | |
919 | lldb_private::Status write_error; |
920 | |
921 | execution_unit.WritePointerToMemory(process_address: P, address: R, error&: write_error); |
922 | |
923 | if (!write_error.Success()) { |
924 | LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst"); |
925 | error = lldb_private::Status::FromErrorString(str: memory_write_error); |
926 | lldb_private::Status free_error; |
927 | execution_unit.Free(process_address: P, error&: free_error); |
928 | execution_unit.Free(process_address: R, error&: free_error); |
929 | return false; |
930 | } |
931 | |
932 | frame.m_values[alloca_inst] = P; |
933 | |
934 | if (log) { |
935 | LLDB_LOGF(log, "Interpreted an AllocaInst"); |
936 | LLDB_LOGF(log, " R : 0x%"PRIx64, R); |
937 | LLDB_LOGF(log, " P : 0x%"PRIx64, P); |
938 | } |
939 | } break; |
940 | case Instruction::BitCast: |
941 | case Instruction::ZExt: { |
942 | const CastInst *cast_inst = cast<CastInst>(Val: inst); |
943 | |
944 | Value *source = cast_inst->getOperand(i_nocapture: 0); |
945 | |
946 | lldb_private::Scalar S; |
947 | |
948 | if (!frame.EvaluateValue(scalar&: S, value: source, module)) { |
949 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str()); |
950 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
951 | return false; |
952 | } |
953 | |
954 | frame.AssignValue(value: inst, scalar: S, module); |
955 | } break; |
956 | case Instruction::SExt: { |
957 | const CastInst *cast_inst = cast<CastInst>(Val: inst); |
958 | |
959 | Value *source = cast_inst->getOperand(i_nocapture: 0); |
960 | |
961 | lldb_private::Scalar S; |
962 | |
963 | if (!frame.EvaluateValue(scalar&: S, value: source, module)) { |
964 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str()); |
965 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
966 | return false; |
967 | } |
968 | |
969 | S.MakeSigned(); |
970 | |
971 | lldb_private::Scalar S_signextend(S.SLongLong()); |
972 | |
973 | frame.AssignValue(value: inst, scalar: S_signextend, module); |
974 | } break; |
975 | case Instruction::Br: { |
976 | const BranchInst *br_inst = cast<BranchInst>(Val: inst); |
977 | |
978 | if (br_inst->isConditional()) { |
979 | Value *condition = br_inst->getCondition(); |
980 | |
981 | lldb_private::Scalar C; |
982 | |
983 | if (!frame.EvaluateValue(scalar&: C, value: condition, module)) { |
984 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str()); |
985 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
986 | return false; |
987 | } |
988 | |
989 | if (!C.IsZero()) |
990 | frame.Jump(bb: br_inst->getSuccessor(i: 0)); |
991 | else |
992 | frame.Jump(bb: br_inst->getSuccessor(i: 1)); |
993 | |
994 | if (log) { |
995 | LLDB_LOGF(log, "Interpreted a BrInst with a condition"); |
996 | LLDB_LOGF(log, " cond : %s", |
997 | frame.SummarizeValue(condition).c_str()); |
998 | } |
999 | } else { |
1000 | frame.Jump(bb: br_inst->getSuccessor(i: 0)); |
1001 | |
1002 | if (log) { |
1003 | LLDB_LOGF(log, "Interpreted a BrInst with no condition"); |
1004 | } |
1005 | } |
1006 | } |
1007 | continue; |
1008 | case Instruction::PHI: { |
1009 | const PHINode *phi_inst = cast<PHINode>(Val: inst); |
1010 | if (!frame.m_prev_bb) { |
1011 | LLDB_LOGF(log, |
1012 | "Encountered PHI node without having jumped from another " |
1013 | "basic block"); |
1014 | error = |
1015 | lldb_private::Status::FromErrorString(str: interpreter_internal_error); |
1016 | return false; |
1017 | } |
1018 | |
1019 | Value *value = phi_inst->getIncomingValueForBlock(BB: frame.m_prev_bb); |
1020 | lldb_private::Scalar result; |
1021 | if (!frame.EvaluateValue(scalar&: result, value, module)) { |
1022 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str()); |
1023 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1024 | return false; |
1025 | } |
1026 | frame.AssignValue(value: inst, scalar: result, module); |
1027 | |
1028 | if (log) { |
1029 | LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName()); |
1030 | LLDB_LOGF(log, " Incoming value : %s", |
1031 | frame.SummarizeValue(value).c_str()); |
1032 | } |
1033 | } break; |
1034 | case Instruction::GetElementPtr: { |
1035 | const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(Val: inst); |
1036 | |
1037 | const Value *pointer_operand = gep_inst->getPointerOperand(); |
1038 | Type *src_elem_ty = gep_inst->getSourceElementType(); |
1039 | |
1040 | lldb_private::Scalar P; |
1041 | |
1042 | if (!frame.EvaluateValue(scalar&: P, value: pointer_operand, module)) { |
1043 | LLDB_LOGF(log, "Couldn't evaluate %s", |
1044 | PrintValue(pointer_operand).c_str()); |
1045 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1046 | return false; |
1047 | } |
1048 | |
1049 | typedef SmallVector<Value *, 8> IndexVector; |
1050 | typedef IndexVector::iterator IndexIterator; |
1051 | |
1052 | SmallVector<Value *, 8> indices(gep_inst->idx_begin(), |
1053 | gep_inst->idx_end()); |
1054 | |
1055 | SmallVector<Value *, 8> const_indices; |
1056 | |
1057 | for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie; |
1058 | ++ii) { |
1059 | ConstantInt *constant_index = dyn_cast<ConstantInt>(Val: *ii); |
1060 | |
1061 | if (!constant_index) { |
1062 | lldb_private::Scalar I; |
1063 | |
1064 | if (!frame.EvaluateValue(scalar&: I, value: *ii, module)) { |
1065 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str()); |
1066 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1067 | return false; |
1068 | } |
1069 | |
1070 | LLDB_LOGF(log, "Evaluated constant index %s as %llu", |
1071 | PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS)); |
1072 | |
1073 | constant_index = cast<ConstantInt>(Val: ConstantInt::get( |
1074 | Ty: (*ii)->getType(), V: I.ULongLong(LLDB_INVALID_ADDRESS))); |
1075 | } |
1076 | |
1077 | const_indices.push_back(Elt: constant_index); |
1078 | } |
1079 | |
1080 | uint64_t offset = |
1081 | data_layout.getIndexedOffsetInType(ElemTy: src_elem_ty, Indices: const_indices); |
1082 | |
1083 | lldb_private::Scalar Poffset = P + offset; |
1084 | |
1085 | frame.AssignValue(value: inst, scalar: Poffset, module); |
1086 | |
1087 | if (log) { |
1088 | LLDB_LOGF(log, "Interpreted a GetElementPtrInst"); |
1089 | LLDB_LOGF(log, " P : %s", |
1090 | frame.SummarizeValue(pointer_operand).c_str()); |
1091 | LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str()); |
1092 | } |
1093 | } break; |
1094 | case Instruction::FCmp: |
1095 | case Instruction::ICmp: { |
1096 | const CmpInst *icmp_inst = cast<CmpInst>(Val: inst); |
1097 | |
1098 | CmpInst::Predicate predicate = icmp_inst->getPredicate(); |
1099 | |
1100 | Value *lhs = inst->getOperand(i: 0); |
1101 | Value *rhs = inst->getOperand(i: 1); |
1102 | |
1103 | lldb_private::Scalar L; |
1104 | lldb_private::Scalar R; |
1105 | |
1106 | if (!frame.EvaluateValue(scalar&: L, value: lhs, module)) { |
1107 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str()); |
1108 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1109 | return false; |
1110 | } |
1111 | |
1112 | if (!frame.EvaluateValue(scalar&: R, value: rhs, module)) { |
1113 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str()); |
1114 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1115 | return false; |
1116 | } |
1117 | |
1118 | lldb_private::Scalar result; |
1119 | |
1120 | switch (predicate) { |
1121 | default: |
1122 | return false; |
1123 | case CmpInst::ICMP_EQ: |
1124 | case CmpInst::FCMP_OEQ: |
1125 | result = (L == R); |
1126 | break; |
1127 | case CmpInst::ICMP_NE: |
1128 | case CmpInst::FCMP_UNE: |
1129 | result = (L != R); |
1130 | break; |
1131 | case CmpInst::ICMP_UGT: |
1132 | L.MakeUnsigned(); |
1133 | R.MakeUnsigned(); |
1134 | result = (L > R); |
1135 | break; |
1136 | case CmpInst::ICMP_UGE: |
1137 | L.MakeUnsigned(); |
1138 | R.MakeUnsigned(); |
1139 | result = (L >= R); |
1140 | break; |
1141 | case CmpInst::FCMP_OGE: |
1142 | result = (L >= R); |
1143 | break; |
1144 | case CmpInst::FCMP_OGT: |
1145 | result = (L > R); |
1146 | break; |
1147 | case CmpInst::ICMP_ULT: |
1148 | L.MakeUnsigned(); |
1149 | R.MakeUnsigned(); |
1150 | result = (L < R); |
1151 | break; |
1152 | case CmpInst::FCMP_OLT: |
1153 | result = (L < R); |
1154 | break; |
1155 | case CmpInst::ICMP_ULE: |
1156 | L.MakeUnsigned(); |
1157 | R.MakeUnsigned(); |
1158 | result = (L <= R); |
1159 | break; |
1160 | case CmpInst::FCMP_OLE: |
1161 | result = (L <= R); |
1162 | break; |
1163 | case CmpInst::ICMP_SGT: |
1164 | L.MakeSigned(); |
1165 | R.MakeSigned(); |
1166 | result = (L > R); |
1167 | break; |
1168 | case CmpInst::ICMP_SGE: |
1169 | L.MakeSigned(); |
1170 | R.MakeSigned(); |
1171 | result = (L >= R); |
1172 | break; |
1173 | case CmpInst::ICMP_SLT: |
1174 | L.MakeSigned(); |
1175 | R.MakeSigned(); |
1176 | result = (L < R); |
1177 | break; |
1178 | case CmpInst::ICMP_SLE: |
1179 | L.MakeSigned(); |
1180 | R.MakeSigned(); |
1181 | result = (L <= R); |
1182 | break; |
1183 | } |
1184 | |
1185 | frame.AssignValue(value: inst, scalar: result, module); |
1186 | |
1187 | if (log) { |
1188 | LLDB_LOGF(log, "Interpreted an ICmpInst"); |
1189 | LLDB_LOGF(log, " L : %s", frame.SummarizeValue(lhs).c_str()); |
1190 | LLDB_LOGF(log, " R : %s", frame.SummarizeValue(rhs).c_str()); |
1191 | LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); |
1192 | } |
1193 | } break; |
1194 | case Instruction::IntToPtr: { |
1195 | const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(Val: inst); |
1196 | |
1197 | Value *src_operand = int_to_ptr_inst->getOperand(i_nocapture: 0); |
1198 | |
1199 | lldb_private::Scalar I; |
1200 | |
1201 | if (!frame.EvaluateValue(scalar&: I, value: src_operand, module)) { |
1202 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); |
1203 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1204 | return false; |
1205 | } |
1206 | |
1207 | frame.AssignValue(value: inst, scalar: I, module); |
1208 | |
1209 | if (log) { |
1210 | LLDB_LOGF(log, "Interpreted an IntToPtr"); |
1211 | LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); |
1212 | LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); |
1213 | } |
1214 | } break; |
1215 | case Instruction::PtrToInt: { |
1216 | const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(Val: inst); |
1217 | |
1218 | Value *src_operand = ptr_to_int_inst->getOperand(i_nocapture: 0); |
1219 | |
1220 | lldb_private::Scalar I; |
1221 | |
1222 | if (!frame.EvaluateValue(scalar&: I, value: src_operand, module)) { |
1223 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); |
1224 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1225 | return false; |
1226 | } |
1227 | |
1228 | frame.AssignValue(value: inst, scalar: I, module); |
1229 | |
1230 | if (log) { |
1231 | LLDB_LOGF(log, "Interpreted a PtrToInt"); |
1232 | LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); |
1233 | LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); |
1234 | } |
1235 | } break; |
1236 | case Instruction::Trunc: { |
1237 | const TruncInst *trunc_inst = cast<TruncInst>(Val: inst); |
1238 | |
1239 | Value *src_operand = trunc_inst->getOperand(i_nocapture: 0); |
1240 | |
1241 | lldb_private::Scalar I; |
1242 | |
1243 | if (!frame.EvaluateValue(scalar&: I, value: src_operand, module)) { |
1244 | LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str()); |
1245 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1246 | return false; |
1247 | } |
1248 | |
1249 | frame.AssignValue(value: inst, scalar: I, module); |
1250 | |
1251 | if (log) { |
1252 | LLDB_LOGF(log, "Interpreted a Trunc"); |
1253 | LLDB_LOGF(log, " Src : %s", frame.SummarizeValue(src_operand).c_str()); |
1254 | LLDB_LOGF(log, " = : %s", frame.SummarizeValue(inst).c_str()); |
1255 | } |
1256 | } break; |
1257 | case Instruction::Load: { |
1258 | const LoadInst *load_inst = cast<LoadInst>(Val: inst); |
1259 | |
1260 | // The semantics of Load are: |
1261 | // Create a region D that will contain the loaded data |
1262 | // Resolve the region P containing a pointer |
1263 | // Dereference P to get the region R that the data should be loaded from |
1264 | // Transfer a unit of type type(D) from R to D |
1265 | |
1266 | const Value *pointer_operand = load_inst->getPointerOperand(); |
1267 | |
1268 | lldb::addr_t D = frame.ResolveValue(value: load_inst, module); |
1269 | lldb::addr_t P = frame.ResolveValue(value: pointer_operand, module); |
1270 | |
1271 | if (D == LLDB_INVALID_ADDRESS) { |
1272 | LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything"); |
1273 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1274 | return false; |
1275 | } |
1276 | |
1277 | if (P == LLDB_INVALID_ADDRESS) { |
1278 | LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything"); |
1279 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1280 | return false; |
1281 | } |
1282 | |
1283 | lldb::addr_t R; |
1284 | lldb_private::Status read_error; |
1285 | execution_unit.ReadPointerFromMemory(address: &R, process_address: P, error&: read_error); |
1286 | |
1287 | if (!read_error.Success()) { |
1288 | LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst"); |
1289 | error = lldb_private::Status::FromErrorString(str: memory_read_error); |
1290 | return false; |
1291 | } |
1292 | |
1293 | Type *target_ty = load_inst->getType(); |
1294 | size_t target_size = data_layout.getTypeStoreSize(Ty: target_ty); |
1295 | lldb_private::DataBufferHeap buffer(target_size, 0); |
1296 | |
1297 | read_error.Clear(); |
1298 | execution_unit.ReadMemory(bytes: buffer.GetBytes(), process_address: R, size: buffer.GetByteSize(), |
1299 | error&: read_error); |
1300 | if (!read_error.Success()) { |
1301 | LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst"); |
1302 | error = lldb_private::Status::FromErrorString(str: memory_read_error); |
1303 | return false; |
1304 | } |
1305 | |
1306 | lldb_private::Status write_error; |
1307 | execution_unit.WriteMemory(process_address: D, bytes: buffer.GetBytes(), size: buffer.GetByteSize(), |
1308 | error&: write_error); |
1309 | if (!write_error.Success()) { |
1310 | LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst"); |
1311 | error = lldb_private::Status::FromErrorString(str: memory_write_error); |
1312 | return false; |
1313 | } |
1314 | |
1315 | if (log) { |
1316 | LLDB_LOGF(log, "Interpreted a LoadInst"); |
1317 | LLDB_LOGF(log, " P : 0x%"PRIx64, P); |
1318 | LLDB_LOGF(log, " R : 0x%"PRIx64, R); |
1319 | LLDB_LOGF(log, " D : 0x%"PRIx64, D); |
1320 | } |
1321 | } break; |
1322 | case Instruction::Ret: { |
1323 | return true; |
1324 | } |
1325 | case Instruction::Store: { |
1326 | const StoreInst *store_inst = cast<StoreInst>(Val: inst); |
1327 | |
1328 | // The semantics of Store are: |
1329 | // Resolve the region D containing the data to be stored |
1330 | // Resolve the region P containing a pointer |
1331 | // Dereference P to get the region R that the data should be stored in |
1332 | // Transfer a unit of type type(D) from D to R |
1333 | |
1334 | const Value *value_operand = store_inst->getValueOperand(); |
1335 | const Value *pointer_operand = store_inst->getPointerOperand(); |
1336 | |
1337 | lldb::addr_t D = frame.ResolveValue(value: value_operand, module); |
1338 | lldb::addr_t P = frame.ResolveValue(value: pointer_operand, module); |
1339 | |
1340 | if (D == LLDB_INVALID_ADDRESS) { |
1341 | LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything"); |
1342 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1343 | return false; |
1344 | } |
1345 | |
1346 | if (P == LLDB_INVALID_ADDRESS) { |
1347 | LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything"); |
1348 | error = lldb_private::Status::FromErrorString(str: bad_value_error); |
1349 | return false; |
1350 | } |
1351 | |
1352 | lldb::addr_t R; |
1353 | lldb_private::Status read_error; |
1354 | execution_unit.ReadPointerFromMemory(address: &R, process_address: P, error&: read_error); |
1355 | |
1356 | if (!read_error.Success()) { |
1357 | LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst"); |
1358 | error = lldb_private::Status::FromErrorString(str: memory_read_error); |
1359 | return false; |
1360 | } |
1361 | |
1362 | Type *target_ty = value_operand->getType(); |
1363 | size_t target_size = data_layout.getTypeStoreSize(Ty: target_ty); |
1364 | lldb_private::DataBufferHeap buffer(target_size, 0); |
1365 | |
1366 | read_error.Clear(); |
1367 | execution_unit.ReadMemory(bytes: buffer.GetBytes(), process_address: D, size: buffer.GetByteSize(), |
1368 | error&: read_error); |
1369 | if (!read_error.Success()) { |
1370 | LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst"); |
1371 | error = lldb_private::Status::FromErrorString(str: memory_read_error); |
1372 | return false; |
1373 | } |
1374 | |
1375 | lldb_private::Status write_error; |
1376 | execution_unit.WriteMemory(process_address: R, bytes: buffer.GetBytes(), size: buffer.GetByteSize(), |
1377 | error&: write_error); |
1378 | if (!write_error.Success()) { |
1379 | LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst"); |
1380 | error = lldb_private::Status::FromErrorString(str: memory_write_error); |
1381 | return false; |
1382 | } |
1383 | |
1384 | if (log) { |
1385 | LLDB_LOGF(log, "Interpreted a StoreInst"); |
1386 | LLDB_LOGF(log, " D : 0x%"PRIx64, D); |
1387 | LLDB_LOGF(log, " P : 0x%"PRIx64, P); |
1388 | LLDB_LOGF(log, " R : 0x%"PRIx64, R); |
1389 | } |
1390 | } break; |
1391 | case Instruction::Call: { |
1392 | const CallInst *call_inst = cast<CallInst>(Val: inst); |
1393 | |
1394 | if (CanIgnoreCall(call: call_inst)) |
1395 | break; |
1396 | |
1397 | // Get the return type |
1398 | llvm::Type *returnType = call_inst->getType(); |
1399 | if (returnType == nullptr) { |
1400 | error = lldb_private::Status::FromErrorString( |
1401 | str: "unable to access return type"); |
1402 | return false; |
1403 | } |
1404 | |
1405 | // Work with void, integer and pointer return types |
1406 | if (!returnType->isVoidTy() && !returnType->isIntegerTy() && |
1407 | !returnType->isPointerTy()) { |
1408 | error = lldb_private::Status::FromErrorString( |
1409 | str: "return type is not supported"); |
1410 | return false; |
1411 | } |
1412 | |
1413 | // Check we can actually get a thread |
1414 | if (exe_ctx.GetThreadPtr() == nullptr) { |
1415 | error = |
1416 | lldb_private::Status::FromErrorString(str: "unable to acquire thread"); |
1417 | return false; |
1418 | } |
1419 | |
1420 | // Make sure we have a valid process |
1421 | if (!process) { |
1422 | error = |
1423 | lldb_private::Status::FromErrorString(str: "unable to get the process"); |
1424 | return false; |
1425 | } |
1426 | |
1427 | // Find the address of the callee function |
1428 | lldb_private::Scalar I; |
1429 | const llvm::Value *val = call_inst->getCalledOperand(); |
1430 | |
1431 | if (!frame.EvaluateValue(scalar&: I, value: val, module)) { |
1432 | error = lldb_private::Status::FromErrorString( |
1433 | str: "unable to get address of function"); |
1434 | return false; |
1435 | } |
1436 | lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); |
1437 | |
1438 | lldb_private::DiagnosticManager diagnostics; |
1439 | lldb_private::EvaluateExpressionOptions options; |
1440 | |
1441 | llvm::FunctionType *prototype = call_inst->getFunctionType(); |
1442 | |
1443 | // Find number of arguments |
1444 | const int numArgs = call_inst->arg_size(); |
1445 | |
1446 | // We work with a fixed array of 16 arguments which is our upper limit |
1447 | static lldb_private::ABI::CallArgument rawArgs[16]; |
1448 | if (numArgs >= 16) { |
1449 | error = lldb_private::Status::FromErrorString( |
1450 | str: "function takes too many arguments"); |
1451 | return false; |
1452 | } |
1453 | |
1454 | // Push all function arguments to the argument list that will be passed |
1455 | // to the call function thread plan |
1456 | for (int i = 0; i < numArgs; i++) { |
1457 | // Get details of this argument |
1458 | llvm::Value *arg_op = call_inst->getArgOperand(i); |
1459 | llvm::Type *arg_ty = arg_op->getType(); |
1460 | |
1461 | // Ensure that this argument is an supported type |
1462 | if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) { |
1463 | error = lldb_private::Status::FromErrorStringWithFormat( |
1464 | format: "argument %d must be integer type", i); |
1465 | return false; |
1466 | } |
1467 | |
1468 | // Extract the arguments value |
1469 | lldb_private::Scalar tmp_op = 0; |
1470 | if (!frame.EvaluateValue(scalar&: tmp_op, value: arg_op, module)) { |
1471 | error = lldb_private::Status::FromErrorStringWithFormat( |
1472 | format: "unable to evaluate argument %d", i); |
1473 | return false; |
1474 | } |
1475 | |
1476 | // Check if this is a string literal or constant string pointer |
1477 | if (arg_ty->isPointerTy()) { |
1478 | lldb::addr_t addr = tmp_op.ULongLong(); |
1479 | size_t dataSize = 0; |
1480 | |
1481 | bool Success = execution_unit.GetAllocSize(address: addr, size&: dataSize); |
1482 | UNUSED_IF_ASSERT_DISABLED(Success); |
1483 | assert(Success && |
1484 | "unable to locate host data for transfer to device"); |
1485 | // Create the required buffer |
1486 | rawArgs[i].size = dataSize; |
1487 | rawArgs[i].data_up.reset(p: new uint8_t[dataSize + 1]); |
1488 | |
1489 | // Read string from host memory |
1490 | execution_unit.ReadMemory(bytes: rawArgs[i].data_up.get(), process_address: addr, size: dataSize, |
1491 | error); |
1492 | assert(!error.Fail() && |
1493 | "we have failed to read the string from memory"); |
1494 | |
1495 | // Add null terminator |
1496 | rawArgs[i].data_up[dataSize] = '\0'; |
1497 | rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer; |
1498 | } else /* if ( arg_ty->isPointerTy() ) */ |
1499 | { |
1500 | rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue; |
1501 | // Get argument size in bytes |
1502 | rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8; |
1503 | // Push value into argument list for thread plan |
1504 | rawArgs[i].value = tmp_op.ULongLong(); |
1505 | } |
1506 | } |
1507 | |
1508 | // Pack the arguments into an llvm::array |
1509 | llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs); |
1510 | |
1511 | // Setup a thread plan to call the target function |
1512 | lldb::ThreadPlanSP call_plan_sp( |
1513 | new lldb_private::ThreadPlanCallFunctionUsingABI( |
1514 | exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args, |
1515 | options)); |
1516 | |
1517 | // Check if the plan is valid |
1518 | lldb_private::StreamString ss; |
1519 | if (!call_plan_sp || !call_plan_sp->ValidatePlan(error: &ss)) { |
1520 | error = lldb_private::Status::FromErrorStringWithFormat( |
1521 | format: "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", |
1522 | I.ULongLong()); |
1523 | return false; |
1524 | } |
1525 | |
1526 | process->SetRunningUserExpression(true); |
1527 | |
1528 | // Execute the actual function call thread plan |
1529 | lldb::ExpressionResults res = |
1530 | process->RunThreadPlan(exe_ctx, thread_plan_sp&: call_plan_sp, options, diagnostic_manager&: diagnostics); |
1531 | |
1532 | // Check that the thread plan completed successfully |
1533 | if (res != lldb::ExpressionResults::eExpressionCompleted) { |
1534 | error = lldb_private::Status::FromErrorString( |
1535 | str: "ThreadPlanCallFunctionUsingABI failed"); |
1536 | return false; |
1537 | } |
1538 | |
1539 | process->SetRunningUserExpression(false); |
1540 | |
1541 | // Void return type |
1542 | if (returnType->isVoidTy()) { |
1543 | // Cant assign to void types, so we leave the frame untouched |
1544 | } else |
1545 | // Integer or pointer return type |
1546 | if (returnType->isIntegerTy() || returnType->isPointerTy()) { |
1547 | // Get the encapsulated return value |
1548 | lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject(); |
1549 | |
1550 | lldb_private::Scalar returnVal = -1; |
1551 | lldb_private::ValueObject *vobj = retVal.get(); |
1552 | |
1553 | // Check if the return value is valid |
1554 | if (vobj == nullptr || !retVal) { |
1555 | error = lldb_private::Status::FromErrorString( |
1556 | str: "unable to get the return value"); |
1557 | return false; |
1558 | } |
1559 | |
1560 | // Extract the return value as a integer |
1561 | lldb_private::Value &value = vobj->GetValue(); |
1562 | returnVal = value.GetScalar(); |
1563 | |
1564 | // Push the return value as the result |
1565 | frame.AssignValue(value: inst, scalar: returnVal, module); |
1566 | } |
1567 | } break; |
1568 | } |
1569 | |
1570 | ++frame.m_ii; |
1571 | } |
1572 | |
1573 | return false; |
1574 | } |
1575 |
Definitions
- PrintValue
- PrintType
- CanIgnoreCall
- InterpreterStackFrame
- InterpreterStackFrame
- ~InterpreterStackFrame
- Jump
- SummarizeValue
- AssignToMatchType
- EvaluateValue
- AssignValue
- ResolveConstantValue
- MakeArgument
- ResolveConstant
- Malloc
- Malloc
- PrintData
- ResolveValue
- unsupported_opcode_error
- unsupported_operand_error
- interpreter_internal_error
- interrupt_error
- bad_value_error
- memory_allocation_error
- memory_write_error
- memory_read_error
- timeout_error
- too_many_functions_error
- CanResolveConstant
- CanInterpret
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more