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