diff options
Diffstat (limited to 'source/Expression')
-rw-r--r-- | source/Expression/ClangExpressionDeclMap.cpp | 25 | ||||
-rw-r--r-- | source/Expression/ClangExpressionParser.cpp | 5 | ||||
-rw-r--r-- | source/Expression/ClangModulesDeclVendor.cpp | 43 | ||||
-rw-r--r-- | source/Expression/ClangUserExpression.cpp | 3 | ||||
-rw-r--r-- | source/Expression/IRExecutionUnit.cpp | 2 | ||||
-rw-r--r-- | source/Expression/IRForTarget.cpp | 4 | ||||
-rw-r--r-- | source/Expression/IRInterpreter.cpp | 277 | ||||
-rw-r--r-- | source/Expression/IRMemoryMap.cpp | 26 |
8 files changed, 326 insertions, 59 deletions
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp index 1013bb5..2c66a0a 100644 --- a/source/Expression/ClangExpressionDeclMap.cpp +++ b/source/Expression/ClangExpressionDeclMap.cpp @@ -1527,6 +1527,31 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, context.m_found.function_with_type_info = true; context.m_found.function = true; } + else if (llvm::isa<clang::VarDecl>(decl_from_modules)) + { + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr; + + if (!copied_var_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_var_decl); + + context.m_found.variable = true; + } } } while (0); } diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp index 3d5350d..2b344b0 100644 --- a/source/Expression/ClangExpressionParser.cpp +++ b/source/Expression/ClangExpressionParser.cpp @@ -541,10 +541,11 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Error interpret_error; + Process *process = exe_ctx.GetProcessPtr(); - can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); + bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); + can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); - Process *process = exe_ctx.GetProcessPtr(); if (!ir_can_run) { diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp index 97a4d08..e825363 100644 --- a/source/Expression/ClangModulesDeclVendor.cpp +++ b/source/Expression/ClangModulesDeclVendor.cpp @@ -18,6 +18,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CompilerInstance.h" @@ -444,18 +445,18 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec } ssize_t found_priority = -1; - clang::MacroInfo *info = nullptr; + clang::MacroInfo *macro_info = nullptr; - for (clang::ModuleMacro *macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) + for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) { - clang::Module *module = macro->getOwningModule(); + clang::Module *module = module_macro->getOwningModule(); { ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module)); if (pi != module_priorities.end() && pi->second > found_priority) { - info = macro->getMacroInfo(); + macro_info = module_macro->getMacroInfo(); found_priority = pi->second; } } @@ -465,26 +466,20 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec if (top_level_module != module) { ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module)); - + if ((pi != module_priorities.end()) && pi->second > found_priority) { - info = macro->getMacroInfo(); + macro_info = module_macro->getMacroInfo(); found_priority = pi->second; } } } - if (!info) + if (macro_info) { - continue; - } - - if (mi->second.getLatest()->getKind() == clang::MacroDirective::MD_Define) - { std::string macro_expansion = "#define "; macro_expansion.append(mi->first->getName().str().c_str()); - - if (clang::MacroInfo *macro_info = mi->second.getLatest()->getMacroInfo()) + { if (macro_info->isFunctionLike()) { @@ -560,9 +555,7 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec if (invalid) { -#ifdef LLDB_CONFIGURATION_DEBUG - assert(!"Unhandled token kind"); -#endif + lldbassert(!"Unhandled token kind"); macro_expansion.append("<unknown literal value>"); } else @@ -594,17 +587,11 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec } } } - } - else - { -#ifdef LLDB_CONFIGURATION_DEBUG - assert(!"#define with no macro info"); -#endif - } - - if (handler(macro_expansion)) - { - return; + + if (handler(macro_expansion)) + { + return; + } } } } diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp index 661bab0..0da70e2 100644 --- a/source/Expression/ClangUserExpression.cpp +++ b/source/Expression/ClangUserExpression.cpp @@ -891,7 +891,8 @@ ClangUserExpression::Execute (Stream &error_stream, *m_execution_unit_sp.get(), interpreter_error, function_stack_bottom, - function_stack_top); + function_stack_top, + exe_ctx); if (!interpreter_error.Success()) { diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 7232685..59c7fb6 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -373,7 +373,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error, ss.PutCString("\n"); emitNewLine = true; ss.PutCString(" "); - ss.PutCString(Mangled(failed_lookup).GetDemangledName().AsCString()); + ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString()); } m_failed_lookups.clear(); diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp index 11bc011..cf2a93b 100644 --- a/source/Expression/IRForTarget.cpp +++ b/source/Expression/IRForTarget.cpp @@ -267,11 +267,11 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, { if (mangled_name.GetMangledName()) m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", - mangled_name.GetName().GetCString(), + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), mangled_name.GetMangledName().GetCString()); else m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", - mangled_name.GetName().GetCString()); + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); } return LookupResult::Fail; } diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index d11bdc1..926d1f2 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -10,17 +10,28 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/Module.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" #include "lldb/Expression/IRMemoryMap.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/Endian.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h" + #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" @@ -455,7 +466,8 @@ static const char *infinite_loop_error = "Interpreter ran for too m bool IRInterpreter::CanInterpret (llvm::Module &module, llvm::Function &function, - lldb_private::Error &error) + lldb_private::Error &error, + const bool support_function_calls) { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -507,7 +519,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, return false; } - if (!CanIgnoreCall(call_inst)) + if (!CanIgnoreCall(call_inst) && !support_function_calls) { if (log) log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str()); @@ -611,7 +623,8 @@ IRInterpreter::Interpret (llvm::Module &module, lldb_private::IRMemoryMap &memory_map, lldb_private::Error &error, lldb::addr_t stack_frame_bottom, - lldb::addr_t stack_frame_top) + lldb::addr_t stack_frame_top, + lldb_private::ExecutionContext &exe_ctx) { lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -668,29 +681,7 @@ IRInterpreter::Interpret (llvm::Module &module, { default: break; - case Instruction::Call: - { - const CallInst *call_inst = dyn_cast<CallInst>(inst); - - if (!call_inst) - { - if (log) - log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - if (!CanIgnoreCall(call_inst)) - { - if (log) - log->Printf("The interpreter shouldn't have accepted %s", PrintValue(call_inst).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - } - break; case Instruction::Add: case Instruction::Sub: case Instruction::Mul: @@ -1476,6 +1467,242 @@ IRInterpreter::Interpret (llvm::Module &module, } } break; + case Instruction::Call: + { + const CallInst *call_inst = dyn_cast<CallInst>(inst); + + if (!call_inst) + { + if (log) + log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + if (CanIgnoreCall(call_inst)) + break; + + // Get the return type + llvm::Type *returnType = call_inst->getType(); + if (returnType == nullptr) + { + error.SetErrorToGenericError(); + error.SetErrorString("unable to access return type"); + return false; + } + + // Work with void, integer and pointer return types + if (!returnType->isVoidTy() && + !returnType->isIntegerTy() && + !returnType->isPointerTy()) + { + error.SetErrorToGenericError(); + error.SetErrorString("return type is not supported"); + return false; + } + + // Check we can actually get a thread + if (exe_ctx.GetThreadPtr() == nullptr) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to acquire thread"); + return false; + } + + // Make sure we have a valid process + if (!exe_ctx.GetProcessPtr()) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to get the process"); + return false; + } + + // Find the address of the callee function + lldb_private::Scalar I; + const llvm::Value *val = call_inst->getCalledValue(); + + if (!frame.EvaluateValue(I, val, module)) + { + error.SetErrorToGenericError(); + error.SetErrorString("unable to get address of function"); + return false; + } + lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); + + lldb_private::StreamString error_stream; + lldb_private::EvaluateExpressionOptions options; + + // We generally receive a function pointer which we must dereference + llvm::Type* prototype = val->getType(); + if (!prototype->isPointerTy()) + { + error.SetErrorToGenericError(); + error.SetErrorString("call need function pointer"); + return false; + } + + // Dereference the function pointer + prototype = prototype->getPointerElementType(); + if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg())) + { + error.SetErrorToGenericError(); + error.SetErrorString("call need function pointer"); + return false; + } + + // Find number of arguments + const int numArgs = call_inst->getNumArgOperands(); + + // We work with a fixed array of 16 arguments which is our upper limit + static lldb_private::ABI::CallArgument rawArgs[16]; + if (numArgs >= 16) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("function takes too many arguments"); + return false; + } + + // Push all function arguments to the argument list that will + // be passed to the call function thread plan + for (int i = 0; i < numArgs; i++) + { + // Get details of this argument + llvm::Value *arg_op = call_inst->getArgOperand(i); + llvm::Type *arg_ty = arg_op->getType(); + + // Ensure that this argument is an supported type + if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("argument %d must be integer type", i); + return false; + } + + // Extract the arguments value + lldb_private::Scalar tmp_op = 0; + if (!frame.EvaluateValue(tmp_op, arg_op, module)) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to evaluate argument %d", i); + return false; + } + + // Check if this is a string literal or constant string pointer + if (arg_ty->isPointerTy()) + { + // Pointer to just one type + assert(arg_ty->getNumContainedTypes() == 1); + + lldb::addr_t addr = tmp_op.ULongLong(); + size_t dataSize = 0; + + if (memory_map.GetAllocSize(addr, dataSize)) + { + // Create the required buffer + rawArgs[i].size = dataSize; + rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]); + + // Read string from host memory + memory_map.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error); + if (error.Fail()) + { + assert(!"we have failed to read the string from memory"); + return false; + } + // Add null terminator + rawArgs[i].data_ap[dataSize] = '\0'; + rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer; + } + else + { + assert(!"unable to locate host data for transfer to device"); + return false; + } + } + else /* if ( arg_ty->isPointerTy() ) */ + { + rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue; + // Get argument size in bytes + rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8; + // Push value into argument list for thread plan + rawArgs[i].value = tmp_op.ULongLong(); + } + + } + + // Pack the arguments into an llvm::array + llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs); + + // Setup a thread plan to call the target function + lldb::ThreadPlanSP call_plan_sp + ( + new lldb_private::ThreadPlanCallFunctionUsingABI + ( + exe_ctx.GetThreadRef(), + funcAddr, + *prototype, + *returnType, + args, + options + ) + ); + + // Check if the plan is valid + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong()); + return false; + } + + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + // Execute the actual function call thread plan + lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + + // Check that the thread plan completed successfully + if (res != lldb::ExpressionResults::eExpressionCompleted) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed"); + return false; + } + + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + // Void return type + if (returnType->isVoidTy()) + { + // Cant assign to void types, so we leave the frame untouched + } + else + // Integer or pointer return type + if (returnType->isIntegerTy() || returnType->isPointerTy()) + { + // Get the encapsulated return value + lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject(); + + lldb_private::Scalar returnVal = -1; + lldb_private::ValueObject *vobj = retVal.get(); + + // Check if the return value is valid + if (vobj == nullptr || retVal.empty()) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to get the return value"); + return false; + } + + // Extract the return value as a integer + lldb_private::Value & value = vobj->GetValue(); + returnVal = value.GetScalar(); + + // Push the return value as the result + frame.AssignValue(inst, returnVal, module); + } + } + break; } ++frame.m_ii; diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp index a4fe7a9..4733b16 100644 --- a/source/Expression/IRMemoryMap.cpp +++ b/source/Expression/IRMemoryMap.cpp @@ -418,6 +418,32 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error) m_allocations.erase(iter); } +bool +IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) +{ + AllocationMap::iterator iter = FindAllocation(address, size); + if (iter == m_allocations.end()) + return false; + + Allocation &al = iter->second; + + if (address > (al.m_process_start + al.m_size)) + { + size = 0; + return false; + } + + if (address > al.m_process_start) + { + int dif = address - al.m_process_start; + size = al.m_size - dif; + return true; + } + + size = al.m_size; + return true; +} + void IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error) { |