diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Expression | |
parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) |
Notes
Diffstat (limited to 'source/Expression')
-rw-r--r-- | source/Expression/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/Expression/DWARFExpression.cpp | 165 | ||||
-rw-r--r-- | source/Expression/DiagnosticManager.cpp | 91 | ||||
-rw-r--r-- | source/Expression/ExpressionSourceCode.cpp | 113 | ||||
-rw-r--r-- | source/Expression/ExpressionVariable.cpp | 54 | ||||
-rw-r--r-- | source/Expression/FunctionCaller.cpp | 89 | ||||
-rw-r--r-- | source/Expression/IRDynamicChecks.cpp | 68 | ||||
-rw-r--r-- | source/Expression/IRExecutionUnit.cpp | 655 | ||||
-rw-r--r-- | source/Expression/IRInterpreter.cpp | 242 | ||||
-rw-r--r-- | source/Expression/IRMemoryMap.cpp | 127 | ||||
-rw-r--r-- | source/Expression/LLVMUserExpression.cpp | 90 | ||||
-rw-r--r-- | source/Expression/Makefile | 14 | ||||
-rw-r--r-- | source/Expression/Materializer.cpp | 516 | ||||
-rw-r--r-- | source/Expression/REPL.cpp | 3 | ||||
-rw-r--r-- | source/Expression/UserExpression.cpp | 132 | ||||
-rw-r--r-- | source/Expression/UtilityFunction.cpp | 34 |
16 files changed, 1739 insertions, 655 deletions
diff --git a/source/Expression/CMakeLists.txt b/source/Expression/CMakeLists.txt index 52392f13319aa..48e67888e436d 100644 --- a/source/Expression/CMakeLists.txt +++ b/source/Expression/CMakeLists.txt @@ -1,4 +1,5 @@ add_lldb_library(lldbExpression + DiagnosticManager.cpp DWARFExpression.cpp Expression.cpp ExpressionSourceCode.cpp diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index ebcc284603958..b81d60e9b065b 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -1003,7 +1003,128 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr) } bool -DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, lldb::addr_t addr) const +DWARFExpression::ContainsThreadLocalStorage() const +{ + // We are assuming for now that any thread local variable will not + // have a location list. This has been true for all thread local + // variables we have seen so far produced by any compiler. + if (IsLocationList()) + return false; + lldb::offset_t offset = 0; + while (m_data.ValidOffset(offset)) + { + const uint8_t op = m_data.GetU8(&offset); + + if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) + return true; + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) + return false; + else + offset += op_arg_size; + } + return false; +} +bool +DWARFExpression::LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback) +{ + // We are assuming for now that any thread local variable will not + // have a location list. This has been true for all thread local + // variables we have seen so far produced by any compiler. + if (IsLocationList()) + return false; + + const uint32_t addr_byte_size = m_data.GetAddressByteSize(); + // We have to make a copy of the data as we don't know if this + // data is from a read only memory mapped buffer, so we duplicate + // all of the data first, then modify it, and if all goes well, + // we then replace the data for this expression + + // So first we copy the data into a heap buffer + std::shared_ptr<DataBufferHeap> heap_data_sp(new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + + // Make en encoder so we can write the address into the buffer using + // the correct byte order (endianness) + DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), m_data.GetByteOrder(), addr_byte_size); + + lldb::offset_t offset = 0; + lldb::offset_t const_offset = 0; + lldb::addr_t const_value = 0; + size_t const_byte_size = 0; + while (m_data.ValidOffset(offset)) + { + const uint8_t op = m_data.GetU8(&offset); + + bool decoded_data = false; + switch (op) + { + case DW_OP_const4u: + // Remember the const offset in case we later have a DW_OP_form_tls_address + // or DW_OP_GNU_push_tls_address + const_offset = offset; + const_value = m_data.GetU32(&offset); + decoded_data = true; + const_byte_size = 4; + break; + + case DW_OP_const8u: + // Remember the const offset in case we later have a DW_OP_form_tls_address + // or DW_OP_GNU_push_tls_address + const_offset = offset; + const_value = m_data.GetU64(&offset); + decoded_data = true; + const_byte_size = 8; + break; + + case DW_OP_form_tls_address: + case DW_OP_GNU_push_tls_address: + // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded by + // a file address on the stack. We assume that DW_OP_const4u or DW_OP_const8u + // is used for these values, and we check that the last opcode we got before + // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can link + // the value accodingly. For Darwin, the value in the DW_OP_const4u or + // DW_OP_const8u is the file address of a structure that contains a function + // pointer, the pthread key and the offset into the data pointed to by the + // pthread key. So we must link this address and also set the module of this + // expression to the new_module_sp so we can resolve the file address correctly + if (const_byte_size > 0) + { + lldb::addr_t linked_file_addr = link_address_callback(const_value); + if (linked_file_addr == LLDB_INVALID_ADDRESS) + return false; + // Replace the address in the new buffer + if (encoder.PutMaxU64(const_offset, const_byte_size, linked_file_addr) == UINT32_MAX) + return false; + } + break; + + default: + const_offset = 0; + const_value = 0; + const_byte_size = 0; + break; + } + + if (!decoded_data) + { + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) + return false; + else + offset += op_arg_size; + } + } + + // If we linked the TLS address correctly, update the module so that when the expression + // is evaluated it can resolve the file address to a load address and read the TLS data + m_module_wp = new_module_sp; + m_data.SetData(heap_data_sp); + return true; +} + +bool +DWARFExpression::LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const { if (addr == LLDB_INVALID_ADDRESS) return false; @@ -1108,12 +1229,21 @@ DWARFExpression::Evaluate ClangExpressionDeclMap *decl_map, lldb::addr_t loclist_base_load_addr, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr ) const { ExecutionContext exe_ctx (exe_scope); - return Evaluate(&exe_ctx, expr_locals, decl_map, NULL, loclist_base_load_addr, initial_value_ptr, result, error_ptr); + return Evaluate(&exe_ctx, + expr_locals, + decl_map, + nullptr, + loclist_base_load_addr, + initial_value_ptr, + object_address_ptr, + result, + error_ptr); } bool @@ -1125,6 +1255,7 @@ DWARFExpression::Evaluate RegisterContext *reg_ctx, lldb::addr_t loclist_base_load_addr, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr ) const @@ -1189,6 +1320,7 @@ DWARFExpression::Evaluate length, m_reg_kind, initial_value_ptr, + object_address_ptr, result, error_ptr); } @@ -1212,6 +1344,7 @@ DWARFExpression::Evaluate m_data.GetByteSize(), m_reg_kind, initial_value_ptr, + object_address_ptr, result, error_ptr); } @@ -1232,6 +1365,7 @@ DWARFExpression::Evaluate const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr ) @@ -1931,7 +2065,7 @@ DWARFExpression::Evaluate { tmp = stack.back(); stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) + tmp.ResolveValue(exe_ctx); + stack.back().GetScalar() += tmp.GetScalar(); } break; @@ -1952,8 +2086,8 @@ DWARFExpression::Evaluate { const uint64_t uconst_value = opcodes.GetULEB128(&offset); // Implicit conversion from a UINT to a Scalar... - stack.back().ResolveValue(exe_ctx) += uconst_value; - if (!stack.back().ResolveValue(exe_ctx).IsValid()) + stack.back().GetScalar() += uconst_value; + if (!stack.back().GetScalar().IsValid()) { if (error_ptr) error_ptr->SetErrorString("DW_OP_plus_uconst failed."); @@ -2689,9 +2823,15 @@ DWARFExpression::Evaluate // during user expression evaluation. //---------------------------------------------------------------------- case DW_OP_push_object_address: - if (error_ptr) - error_ptr->SetErrorString ("Unimplemented opcode DW_OP_push_object_address."); - return false; + if (object_address_ptr) + stack.push_back(*object_address_ptr); + else + { + if (error_ptr) + error_ptr->SetErrorString ("DW_OP_push_object_address used without specifying an object address"); + return false; + } + break; //---------------------------------------------------------------------- // OPCODE: DW_OP_call2 @@ -2826,18 +2966,17 @@ DWARFExpression::Evaluate } // Lookup the TLS block address for this thread and module. - addr_t tls_addr = thread->GetThreadLocalData (module_sp); + const addr_t tls_file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + const addr_t tls_load_addr = thread->GetThreadLocalData(module_sp, tls_file_addr); - if (tls_addr == LLDB_INVALID_ADDRESS) + if (tls_load_addr == LLDB_INVALID_ADDRESS) { if (error_ptr) error_ptr->SetErrorString ("No TLS data currently exists for this thread."); return false; } - // Convert the TLS offset into the absolute address. - Scalar tmp = stack.back().ResolveValue(exe_ctx); - stack.back() = tmp + tls_addr; + stack.back().GetScalar() = tls_load_addr; stack.back().SetValueType (Value::eValueTypeLoadAddress); } break; diff --git a/source/Expression/DiagnosticManager.cpp b/source/Expression/DiagnosticManager.cpp new file mode 100644 index 0000000000000..5156ee38a67bf --- /dev/null +++ b/source/Expression/DiagnosticManager.cpp @@ -0,0 +1,91 @@ +//===-- DiagnosticManager.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/DiagnosticManager.h" + +#include "llvm/Support/ErrorHandling.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" + +using namespace lldb_private; + +void +DiagnosticManager::Dump(Log *log) +{ + if (!log) + return; + + std::string str = GetString(); + + // GetString() puts a separator after each diagnostic. + // We want to remove the last '\n' because log->PutCString will add one for us. + + if (str.size() && str.back() == '\n') + { + str.pop_back(); + } + + log->PutCString(str.c_str()); +} + +static const char * +StringForSeverity(DiagnosticSeverity severity) +{ + switch (severity) + { + // this should be exhaustive + case lldb_private::eDiagnosticSeverityError: + return "error: "; + case lldb_private::eDiagnosticSeverityWarning: + return "warning: "; + case lldb_private::eDiagnosticSeverityRemark: + return ""; + } + llvm_unreachable("switch needs another case for DiagnosticSeverity enum"); +} + +std::string +DiagnosticManager::GetString(char separator) +{ + std::string ret; + + for (const Diagnostic *diagnostic : Diagnostics()) + { + ret.append(StringForSeverity(diagnostic->GetSeverity())); + ret.append(diagnostic->GetMessage()); + ret.push_back(separator); + } + + return ret; +} + +size_t +DiagnosticManager::Printf(DiagnosticSeverity severity, const char *format, ...) +{ + StreamString ss; + + va_list args; + va_start(args, format); + size_t result = ss.PrintfVarArg(format, args); + va_end(args); + + AddDiagnostic(ss.GetData(), severity, eDiagnosticOriginLLDB); + + return result; +} + +size_t +DiagnosticManager::PutCString(DiagnosticSeverity severity, const char *cstr) +{ + if (!cstr) + return 0; + AddDiagnostic(cstr, severity, eDiagnosticOriginLLDB); + return strlen(cstr); +} diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp index c4ab7a95d7a9a..2d41d1a8b449d 100644 --- a/source/Expression/ExpressionSourceCode.cpp +++ b/source/Expression/ExpressionSourceCode.cpp @@ -16,7 +16,9 @@ #include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Platform.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -59,6 +61,9 @@ extern "C" } )"; +static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; +static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; + namespace { class AddMacroState @@ -106,8 +111,6 @@ public: { case CURRENT_FILE_NOT_YET_PUSHED: return true; - case CURRENT_FILE_POPPED: - return false; case CURRENT_FILE_PUSHED: // If we are in file included in the current file, // the entry should be added. @@ -118,6 +121,8 @@ public: return false; else return true; + default: + return false; } } @@ -175,12 +180,28 @@ AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, S } } -bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const +static void +AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, StreamString &stream) +{ + for (size_t i = 0; i < var_list_sp->GetSize(); i++) + { + lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); + + ConstString var_name = var_sp->GetName(); + if (!var_name || var_name == ConstString("this") || var_name == ConstString(".block_descriptor")) + continue; + + stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); + } +} + +bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool static_method, ExecutionContext &exe_ctx) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; std::string module_macros; - if (Target *target = exe_ctx.GetTargetPtr()) + Target *target = exe_ctx.GetTargetPtr(); + if (target) { if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { @@ -239,6 +260,7 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi } StreamString debug_macros_stream; + StreamString lldb_local_var_decls; if (StackFrame *frame = exe_ctx.GetFramePtr()) { const SymbolContext &sc = frame->GetSymbolContext( @@ -253,8 +275,18 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi AddMacros(dm, sc.comp_unit, state, debug_macros_stream); } } + + ConstString object_name; + if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) + { + if (target->GetInjectLocalVariables(&exe_ctx)) + { + lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); + AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); + } + } } - + if (m_wrap) { switch (wrapping_language) @@ -276,6 +308,22 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi target_specific_defines, m_prefix.c_str()); + // First construct a tagged form of the user expression so we can find it later: + std::string tagged_body; + switch (wrapping_language) + { + default: + tagged_body = m_body; + break; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + tagged_body.append(c_start_marker); + tagged_body.append(m_body); + tagged_body.append(c_end_marker); + break; + + } switch (wrapping_language) { default: @@ -284,20 +332,23 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi wrap_stream.Printf("void \n" "%s(void *$__lldb_arg) \n" "{ \n" - " %s; \n" + " %s; \n" + "%s" "} \n", m_name.c_str(), - m_body.c_str()); + lldb_local_var_decls.GetData(), + tagged_body.c_str()); break; case lldb::eLanguageTypeC_plus_plus: wrap_stream.Printf("void \n" - "$__lldb_class::%s(void *$__lldb_arg) %s\n" + "$__lldb_class::%s(void *$__lldb_arg) \n" "{ \n" - " %s; \n" + " %s; \n" + "%s" "} \n", m_name.c_str(), - (const_object ? "const" : ""), - m_body.c_str()); + lldb_local_var_decls.GetData(), + tagged_body.c_str()); break; case lldb::eLanguageTypeObjC: if (static_method) @@ -308,12 +359,12 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi "@implementation $__lldb_objc_class ($__lldb_category) \n" "+(void)%s:(void *)$__lldb_arg \n" "{ \n" - " %s; \n" + "%s" "} \n" "@end \n", m_name.c_str(), m_name.c_str(), - m_body.c_str()); + tagged_body.c_str()); } else { @@ -323,12 +374,12 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi "@implementation $__lldb_objc_class ($__lldb_category) \n" "-(void)%s:(void *)$__lldb_arg \n" "{ \n" - " %s; \n" + "%s" "} \n" "@end \n", m_name.c_str(), m_name.c_str(), - m_body.c_str()); + tagged_body.c_str()); } break; } @@ -339,6 +390,38 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi { text.append(m_body); } + + return true; +} + +bool +ExpressionSourceCode::GetOriginalBodyBounds(std::string transformed_text, + lldb::LanguageType wrapping_language, + size_t &start_loc, + size_t &end_loc) +{ + const char *start_marker; + const char *end_marker; + switch (wrapping_language) + { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + start_marker = c_start_marker; + end_marker = c_end_marker; + break; + } + + start_loc = transformed_text.find(start_marker); + if (start_loc == std::string::npos) + return false; + start_loc += strlen(start_marker); + end_loc = transformed_text.find(end_marker); + if (end_loc == std::string::npos) + return false; return true; } + diff --git a/source/Expression/ExpressionVariable.cpp b/source/Expression/ExpressionVariable.cpp index 8bef60fdf1d7b..5567ee286aa94 100644 --- a/source/Expression/ExpressionVariable.cpp +++ b/source/Expression/ExpressionVariable.cpp @@ -7,7 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Core/Log.h" #include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Expression/IRExecutionUnit.h" using namespace lldb_private; @@ -34,3 +36,55 @@ ExpressionVariable::GetValueBytes() PersistentExpressionState::~PersistentExpressionState () { } + +lldb::addr_t +PersistentExpressionState::LookupSymbol (const ConstString &name) +{ + SymbolMap::iterator si = m_symbol_map.find(name.GetCString()); + + if (si != m_symbol_map.end()) + return si->second; + else + return LLDB_INVALID_ADDRESS; +} + + +void +PersistentExpressionState::RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_execution_units.insert(execution_unit_sp); + + if (log) + log->Printf ("Registering JITted Functions:\n"); + + for (const IRExecutionUnit::JittedFunction &jitted_function : execution_unit_sp->GetJittedFunctions()) + { + if (jitted_function.m_external && + jitted_function.m_name != execution_unit_sp->GetFunctionName() && + jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) + { + m_symbol_map[jitted_function.m_name.GetCString()] = jitted_function.m_remote_addr; + if (log) + log->Printf (" Function: %s at 0x%" PRIx64 ".", jitted_function.m_name.GetCString(), jitted_function.m_remote_addr); + } + } + + if (log) + log->Printf ("Registering JIIted Symbols:\n"); + + for (const IRExecutionUnit::JittedGlobalVariable &global_var : execution_unit_sp->GetJittedGlobalVariables()) + { + if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS) + { + // Demangle the name before inserting it, so that lookups by the ConstStr of the demangled name + // will find the mangled one (needed for looking up metadata pointers.) + Mangled mangler(global_var.m_name); + mangler.GetDemangledName(lldb::eLanguageTypeUnknown); + m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr; + if (log) + log->Printf (" Symbol: %s at 0x%" PRIx64 ".", global_var.m_name.GetCString(), global_var.m_remote_addr); + } + } +} diff --git a/source/Expression/FunctionCaller.cpp b/source/Expression/FunctionCaller.cpp index ddc378dcb4161..3a4f1fe33add0 100644 --- a/source/Expression/FunctionCaller.cpp +++ b/source/Expression/FunctionCaller.cpp @@ -13,13 +13,14 @@ // Other libraries and framework includes // Project includes +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Function.h" @@ -76,11 +77,11 @@ FunctionCaller::~FunctionCaller() lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); if (jit_module_sp) process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } + } } bool -FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) +FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { Process *process = exe_ctx.GetProcessPtr(); @@ -133,27 +134,28 @@ FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) } bool -FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors); + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager); } // FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. bool -FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - ValueList &arg_values, - Stream &errors) +FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, + DiagnosticManager &diagnostic_manager) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { - errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "Argument information was not correctly parsed, so the function cannot be called."); return false; } - + Error error; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; @@ -191,14 +193,16 @@ FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, // FIXME: We will need to extend this for Variadic functions. Error value_error; - + size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { - errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", + (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } - + for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. @@ -225,16 +229,17 @@ FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, } bool -FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { - if (CompileFunction(errors) != 0) + if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) return false; - if (!WriteFunctionWrapper(exe_ctx, errors)) + if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) return false; - if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors)) + if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager)) return false; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref); @@ -242,13 +247,12 @@ FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_ad } lldb::ThreadPlanSP -FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, +FunctionCaller::GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, - Stream &errors) + DiagnosticManager &diagnostic_manager) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + if (log) log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); @@ -256,7 +260,7 @@ FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, Thread *thread = exe_ctx.GetThreadPtr(); if (thread == NULL) { - errors.Printf("Can't call a function without a valid thread."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "Can't call a function without a valid thread."); return NULL; } @@ -322,15 +326,12 @@ FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr } lldb::ExpressionResults -FunctionCaller::ExecuteFunction( - ExecutionContext &exe_ctx, - lldb::addr_t *args_addr_ptr, - const EvaluateExpressionOptions &options, - Stream &errors, - Value &results) +FunctionCaller::ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, + Value &results) { lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - + // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore // breakpoints, unwind on error, and don't try to debug it. EvaluateExpressionOptions real_options = options; @@ -345,12 +346,12 @@ FunctionCaller::ExecuteFunction( else args_addr = LLDB_INVALID_ADDRESS; - if (CompileFunction(errors) != 0) + if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) return lldb::eExpressionSetupError; - + if (args_addr == LLDB_INVALID_ADDRESS) { - if (!InsertFunction(exe_ctx, args_addr, errors)) + if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager)) return lldb::eExpressionSetupError; } @@ -358,24 +359,18 @@ FunctionCaller::ExecuteFunction( if (log) log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); - - lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, - args_addr, - real_options, - errors); + + lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(exe_ctx, args_addr, real_options, diagnostic_manager); if (!call_plan_sp) return lldb::eExpressionSetupError; - + // We need to make sure we record the fact that we are running an expression here // otherwise this fact will fail to be recorded when fetching an Objective-C object description if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, - call_plan_sp, - real_options, - errors); - + + return_value = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, real_options, diagnostic_manager); + if (log) { if (return_value != lldb::eExpressionCompleted) diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp index 64fdb08157aa7..62bcfe0d14b83 100644 --- a/source/Expression/IRDynamicChecks.cpp +++ b/source/Expression/IRDynamicChecks.cpp @@ -50,8 +50,7 @@ DynamicCheckerFunctions::DynamicCheckerFunctions() = default; DynamicCheckerFunctions::~DynamicCheckerFunctions() = default; bool -DynamicCheckerFunctions::Install(Stream &error_stream, - ExecutionContext &exe_ctx) +DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { Error error; m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, @@ -60,8 +59,8 @@ DynamicCheckerFunctions::Install(Stream &error_stream, error)); if (error.Fail()) return false; - - if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) + + if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) return false; Process *process = exe_ctx.GetProcessPtr(); @@ -74,7 +73,7 @@ DynamicCheckerFunctions::Install(Stream &error_stream, { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); - if (!m_objc_object_check->Install(error_stream, exe_ctx)) + if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) return false; } } @@ -506,6 +505,32 @@ protected: return true; } + + static llvm::Function *GetFunction(llvm::Value *value) + { + if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) + { + return function; + } + + if (llvm::ConstantExpr *const_expr = llvm::dyn_cast<llvm::ConstantExpr>(value)) + { + switch (const_expr->getOpcode()) + { + default: + return nullptr; + case llvm::Instruction::BitCast: + return GetFunction(const_expr->getOperand(0)); + } + } + + return nullptr; + } + + static llvm::Function *GetCalledFunction(llvm::CallInst *inst) + { + return GetFunction(inst->getCalledValue()); + } bool InspectInstruction(llvm::Instruction &i) override { @@ -515,35 +540,12 @@ protected: if (call_inst) { - // This metadata is set by IRForTarget::MaybeHandleCall(). - - MDNode *metadata = call_inst->getMetadata("lldb.call.realName"); - - if (!metadata) + const llvm::Function *called_function = GetCalledFunction(call_inst); + + if (!called_function) return true; - - if (metadata->getNumOperands() != 1) - { - if (log) - log->Printf("Function call metadata has %d operands for [%p] %s", - metadata->getNumOperands(), - static_cast<void*>(call_inst), - PrintValue(call_inst).c_str()); - return false; - } - - MDString *real_name = dyn_cast<MDString>(metadata->getOperand(0)); - - if (!real_name) - { - if (log) - log->Printf("Function call metadata is not an MDString for [%p] %s", - static_cast<void*>(call_inst), - PrintValue(call_inst).c_str()); - return false; - } - - std::string name_str = real_name->getString(); + + std::string name_str = called_function->getName().str(); const char* name_cstr = name_str.c_str(); if (log) diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 3f19c508c9267..103d76328c3a8 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" @@ -20,11 +21,17 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Utility/LLDBAssert.h" + +#include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" using namespace lldb_private; @@ -32,6 +39,7 @@ IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap std::unique_ptr<llvm::Module> &module_ap, ConstString &name, const lldb::TargetSP &target_sp, + const SymbolContext &sym_ctx, std::vector<std::string> &cpu_features) : IRMemoryMap(target_sp), m_context_ap(context_ap.release()), @@ -39,9 +47,11 @@ IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap m_module(m_module_ap.get()), m_cpu_features(cpu_features), m_name(name), + m_sym_ctx(sym_ctx), m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS), - m_function_end_load_addr(LLDB_INVALID_ADDRESS) + m_function_end_load_addr(LLDB_INVALID_ADDRESS), + m_reported_allocations(false) { } @@ -115,7 +125,7 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, for (JittedFunction &function : m_jitted_functions) { - if (strstr(function.m_name.c_str(), m_name.AsCString())) + if (function.m_name == m_name) { func_local_addr = function.m_local_addr; func_remote_addr = function.m_remote_addr; @@ -206,10 +216,6 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, InstructionList &instruction_list = disassembler_sp->GetInstructionList(); instruction_list.Dump(&stream, true, true, &exe_ctx); - - // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. - // I'll fix that but for now, just clear the list and it will go away nicely. - disassembler_sp->GetInstructionList().Clear(); return ret; } @@ -237,7 +243,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error, { lldb::ProcessSP process_sp(GetProcessWP().lock()); - static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive); + static std::recursive_mutex s_runnable_info_mutex; func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; @@ -257,7 +263,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error, return; }; - Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex); + std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex); m_did_jit = true; @@ -278,22 +284,21 @@ IRExecutionUnit::GetRunnableInfo(Error &error, } llvm::Triple triple(m_module->getTargetTriple()); - llvm::Function *function = m_module->getFunction (m_name.AsCString()); llvm::Reloc::Model relocModel; llvm::CodeModel::Model codeModel; if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; - // This will be small for 32-bit and large for 64-bit. - codeModel = llvm::CodeModel::JITDefault; } else { relocModel = llvm::Reloc::PIC_; - codeModel = llvm::CodeModel::Small; } + // This will be small for 32-bit and large for 64-bit. + codeModel = llvm::CodeModel::JITDefault; + m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); llvm::EngineBuilder builder(std::move(m_module_ap)); @@ -319,6 +324,8 @@ IRExecutionUnit::GetRunnableInfo(Error &error, m_execution_engine_ap.reset(builder.create(target_machine)); + m_strip_underscore = (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_'); + if (!m_execution_engine_ap.get()) { error.SetErrorToGenericError(); @@ -331,44 +338,79 @@ IRExecutionUnit::GetRunnableInfo(Error &error, m_execution_engine_ap->DisableLazyCompilation(); - // We don't actually need the function pointer here, this just forces it to get resolved. - - void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function); - - if (!error.Success()) + for (llvm::Function &function : *m_module) { - // We got an error through our callback! - return; + if (function.isDeclaration() || function.hasPrivateLinkage()) + continue; + + const bool external = function.hasExternalLinkage() || function.hasLinkOnceODRLinkage(); + + void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function); + + if (!error.Success()) + { + // We got an error through our callback! + return; + } + + if (!fun_ptr) + { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function.getName().str().c_str()); + return; + } + m_jitted_functions.push_back (JittedFunction(function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr)); } - if (!function) + CommitAllocations(process_sp); + ReportAllocations(*m_execution_engine_ap); + + // We have to do this after calling ReportAllocations because for the MCJIT, getGlobalValueAddress + // will cause the JIT to perform all relocations. That can only be done once, and has to happen + // after we do the remapping from local -> remote. + // That means we don't know the local address of the Variables, but we don't need that for anything, + // so that's okay. + + std::function<void (llvm::GlobalValue &)> RegisterOneValue = [this] (llvm::GlobalValue &val) { + if (val.hasExternalLinkage() && !val.isDeclaration()) + { + uint64_t var_ptr_addr = m_execution_engine_ap->getGlobalValueAddress(val.getName().str()); + + lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr); + + // This is a really unfortunae API that sometimes returns local addresses and sometimes returns remote addresses, based on whether + // the variable was relocated during ReportAllocations or not. + + if (remote_addr == LLDB_INVALID_ADDRESS) + { + remote_addr = var_ptr_addr; + } + + if (var_ptr_addr != 0) + m_jitted_global_variables.push_back (JittedGlobalVariable (val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr)); + } + }; + + for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString()); - return; + RegisterOneValue(global_var); } - - if (!fun_ptr) + + for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString()); - return; + RegisterOneValue(global_alias); } - m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr)); - - CommitAllocations(process_sp); - ReportAllocations(*m_execution_engine_ap); WriteData(process_sp); if (m_failed_lookups.size()) { StreamString ss; - + ss.PutCString("Couldn't lookup symbols:\n"); - + bool emitNewLine = false; - + for (const ConstString &failed_lookup : m_failed_lookups) { if (emitNewLine) @@ -377,14 +419,14 @@ IRExecutionUnit::GetRunnableInfo(Error &error, ss.PutCString(" "); ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString()); } - + m_failed_lookups.clear(); - + error.SetErrorString(ss.GetData()); - + return; } - + m_function_load_addr = LLDB_INVALID_ADDRESS; m_function_end_load_addr = LLDB_INVALID_ADDRESS; @@ -392,7 +434,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error, { jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); - if (!jitted_function.m_name.compare(m_name.AsCString())) + if (!m_name.IsEmpty() && jitted_function.m_name == m_name) { AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr); m_function_end_load_addr = func_range.first + func_range.second; @@ -437,7 +479,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error, else { record.dump(log); - + DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8); my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8); } @@ -603,6 +645,14 @@ IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size, log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, (void *)return_value); } + + if (m_parent.m_reported_allocations) + { + Error err; + lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess(); + + m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); + } return return_value; } @@ -633,105 +683,449 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, (void *)return_value); } + + if (m_parent.m_reported_allocations) + { + Error err; + lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess(); + + m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); + } return return_value; } -uint64_t -IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) +static ConstString +FindBestAlternateMangledName(const ConstString &demangled, + const lldb::LanguageType &lang_type, + const SymbolContext &sym_ctx) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SymbolContextList sc_list; - - ExecutionContextScope *exe_scope = m_parent.GetBestExecutionContextScope(); - - lldb::TargetSP target_sp = exe_scope->CalculateTarget(); - - const char *name = Name.c_str(); - - ConstString bare_name_cs(name); - ConstString name_cs; - - if (name[0] == '_') - name_cs = ConstString(name + 1); - - if (!target_sp) + CPlusPlusLanguage::MethodName cpp_name(demangled); + std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); + + if (!scope_qualified_name.size()) + return ConstString(); + + if (!sym_ctx.module_sp) + return ConstString(); + + SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); + if (!sym_vendor) + return ConstString(); + + lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + if (!sym_file) + return ConstString(); + + std::vector<ConstString> alternates; + sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); + + std::vector<ConstString> param_and_qual_matches; + std::vector<ConstString> param_matches; + for (size_t i = 0; i < alternates.size(); i++) { - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <no target>", - Name.c_str()); - - m_parent.ReportSymbolLookupError(name_cs); - - return 0xbad0bad0; + ConstString alternate_mangled_name = alternates[i]; + Mangled mangled(alternate_mangled_name, true); + ConstString demangled = mangled.GetDemangledName(lang_type); + + CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); + if (!cpp_name.IsValid()) + continue; + + if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) + { + if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) + param_and_qual_matches.push_back(alternate_mangled_name); + else + param_matches.push_back(alternate_mangled_name); + } } - - uint32_t num_matches = 0; - lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); - - if (!name_cs.IsEmpty()) + + if (param_and_qual_matches.size()) + return param_and_qual_matches[0]; // It is assumed that there will be only one! + else if (param_matches.size()) + return param_matches[0]; // Return one of them as a best match + else + return ConstString(); +} + +struct IRExecutionUnit::SearchSpec +{ + ConstString name; + uint32_t mask; + + SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) : + name(n), + mask(m) { - target_sp->GetImages().FindSymbolsWithNameAndType(name_cs, lldb::eSymbolTypeAny, sc_list); - num_matches = sc_list.GetSize(); } - - if (!num_matches) +}; + +void +IRExecutionUnit::CollectCandidateCNames(std::vector<IRExecutionUnit::SearchSpec> &C_specs, const ConstString &name) +{ + if (m_strip_underscore && name.AsCString()[0] == '_') + C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1])); + C_specs.push_back(SearchSpec(name)); +} + +void +IRExecutionUnit::CollectCandidateCPlusPlusNames(std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, const std::vector<SearchSpec> &C_specs, const SymbolContext &sc) +{ + for (const SearchSpec &C_spec : C_specs) { - target_sp->GetImages().FindSymbolsWithNameAndType(bare_name_cs, lldb::eSymbolTypeAny, sc_list); - num_matches = sc_list.GetSize(); + const ConstString &name = C_spec.name; + + if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) + { + Mangled mangled(name, true); + ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); + + if (demangled) + { + ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lldb::eLanguageTypeC_plus_plus, sc); + + if (best_alternate_mangled_name) + { + CPP_specs.push_back(best_alternate_mangled_name); + } + + CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull)); + } + } + + // Maybe we're looking for a const symbol but the debug info told us it was const... + if (!strncmp(name.GetCString(), "_ZN", 3) && + strncmp(name.GetCString(), "_ZNK", 4)) + { + std::string fixed_scratch("_ZNK"); + fixed_scratch.append(name.GetCString() + 3); + CPP_specs.push_back(ConstString(fixed_scratch.c_str())); + } + + // Maybe we're looking for a static symbol but we thought it was global... + if (!strncmp(name.GetCString(), "_Z", 2) && + strncmp(name.GetCString(), "_ZL", 3)) + { + std::string fixed_scratch("_ZL"); + fixed_scratch.append(name.GetCString() + 2); + CPP_specs.push_back(ConstString(fixed_scratch.c_str())); + } + } - - lldb::addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; +} + +void +IRExecutionUnit::CollectFallbackNames(std::vector<SearchSpec> &fallback_specs, + const std::vector<SearchSpec> &C_specs) +{ + // As a last-ditch fallback, try the base name for C++ names. It's terrible, + // but the DWARF doesn't always encode "extern C" correctly. - for (uint32_t i=0; i<num_matches && (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); i++) + for (const SearchSpec &C_spec : C_specs) { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(i, sym_ctx); + const ConstString &name = C_spec.name; - symbol_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target_sp); + if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) + { + Mangled mangled_name(name); + ConstString demangled_name = mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus); + if (!demangled_name.IsEmpty()) + { + const char *demangled_cstr = demangled_name.AsCString(); + const char *lparen_loc = strchr(demangled_cstr, '('); + if (lparen_loc) + { + llvm::StringRef base_name(demangled_cstr, lparen_loc-demangled_cstr); + fallback_specs.push_back(ConstString(base_name)); + } + } + } + } +} + + +lldb::addr_t +IRExecutionUnit::FindInSymbols(const std::vector<IRExecutionUnit::SearchSpec> &specs, const lldb_private::SymbolContext &sc) +{ + Target *target = sc.target_sp.get(); - if (symbol_load_addr == LLDB_INVALID_ADDRESS) - symbol_load_addr = sym_ctx.symbol->GetAddress().GetLoadAddress(target_sp.get()); + if (!target) + { + // we shouldn't be doing any symbol lookup at all without a target + return LLDB_INVALID_ADDRESS; } + + for (const SearchSpec &spec : specs) + { + SymbolContextList sc_list; + + lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS; + + std::function<bool (lldb::addr_t &, SymbolContextList &, const lldb_private::SymbolContext &)> get_external_load_address = + [&best_internal_load_address, target](lldb::addr_t &load_address, + SymbolContextList &sc_list, + const lldb_private::SymbolContext &sc) -> lldb::addr_t + { + load_address = LLDB_INVALID_ADDRESS; + + for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) + { + SymbolContext candidate_sc; + + sc_list.GetContextAtIndex(si, candidate_sc); + + const bool is_external = (candidate_sc.function) || + (candidate_sc.symbol && candidate_sc.symbol->IsExternal()); + if (candidate_sc.symbol) + { + load_address = candidate_sc.symbol->ResolveCallableAddress(*target); + + if (load_address == LLDB_INVALID_ADDRESS) + { + if (target->GetProcessSP()) + load_address = candidate_sc.symbol->GetAddress().GetLoadAddress(target); + else + load_address = candidate_sc.symbol->GetAddress().GetFileAddress(); + } + } + + if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) + { + if (target->GetProcessSP()) + load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); + else + load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + } + + if (load_address != LLDB_INVALID_ADDRESS) + { + if (is_external) + { + return true; + } + else if (best_internal_load_address == LLDB_INVALID_ADDRESS) + { + best_internal_load_address = load_address; + load_address = LLDB_INVALID_ADDRESS; + } + } + } + + return false; + }; + + if (sc.module_sp) + { + sc.module_sp->FindFunctions(spec.name, + NULL, + spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } + + lldb::addr_t load_address = LLDB_INVALID_ADDRESS; + + if (get_external_load_address(load_address, sc_list, sc)) + { + return load_address; + } + else + { + sc_list.Clear(); + } + + if (sc_list.GetSize() == 0 && sc.target_sp) + { + sc.target_sp->GetImages().FindFunctions(spec.name, + spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } + + if (get_external_load_address(load_address, sc_list, sc)) + { + return load_address; + } + else + { + sc_list.Clear(); + } + + if (sc_list.GetSize() == 0 && sc.target_sp) + { + sc.target_sp->GetImages().FindSymbolsWithNameAndType(spec.name, lldb::eSymbolTypeAny, sc_list); + } + + if (get_external_load_address(load_address, sc_list, sc)) + { + return load_address; + } + // if there are any searches we try after this, add an sc_list.Clear() in an "else" clause here + + if (best_internal_load_address != LLDB_INVALID_ADDRESS) + { + return best_internal_load_address; + } + } + + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc) +{ + lldb::TargetSP target_sp = sc.target_sp; + + if (!target_sp) + { + return LLDB_INVALID_ADDRESS; + } + + lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP(); + + if (!process_sp) + { + return LLDB_INVALID_ADDRESS; + } + + ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + + if (runtime) + { + for (const SearchSpec &spec : specs) + { + lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name); + + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + return symbol_load_addr; + } + } + + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +IRExecutionUnit::FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc) +{ + lldb::TargetSP target_sp = sc.target_sp; - if (symbol_load_addr == LLDB_INVALID_ADDRESS && process_sp && name_cs) + for (const SearchSpec &spec : specs) { - // Try the Objective-C language runtime. - - ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name); - if (runtime) - symbol_load_addr = runtime->LookupRuntimeSymbol(name_cs); + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + return symbol_load_addr; } - if (symbol_load_addr == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name) +{ + std::vector<SearchSpec> candidate_C_names; + std::vector<SearchSpec> candidate_CPlusPlus_names; + + CollectCandidateCNames(candidate_C_names, name); + + lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx); + if (ret == LLDB_INVALID_ADDRESS) + ret = FindInRuntimes(candidate_C_names, m_sym_ctx); + + if (ret == LLDB_INVALID_ADDRESS) + ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx); + + if (ret == LLDB_INVALID_ADDRESS) + { + CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx); + ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx); + } + + if (ret == LLDB_INVALID_ADDRESS) + { + std::vector<SearchSpec> candidate_fallback_names; + + CollectFallbackNames(candidate_fallback_names, candidate_C_names); + ret = FindInSymbols(candidate_fallback_names, m_sym_ctx); + } + + return ret; +} + +void +IRExecutionUnit::GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers) +{ + if (llvm::GlobalVariable *global_ctors = m_module->getNamedGlobal("llvm.global_ctors")) + { + if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer())) + { + for (llvm::Use &ctor_use : ctor_array->operands()) + { + if (llvm::ConstantStruct *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) + { + lldbassert(ctor_struct->getNumOperands() == 3); // this is standardized + if (llvm::Function *ctor_function = llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) + { + ctor_function->dump(); + + ConstString ctor_function_name_cs(ctor_function->getName().str()); + + for (JittedFunction &jitted_function : m_jitted_functions) + { + if (ctor_function_name_cs == jitted_function.m_name) + { + if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) + { + static_initializers.push_back(jitted_function.m_remote_addr); + } + break; + } + } + } + } + } + } + } +} + +uint64_t +IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ConstString name_cs(Name.c_str()); + + lldb::addr_t ret = m_parent.FindSymbol(name_cs); + + if (ret == LLDB_INVALID_ADDRESS) { if (log) log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", - name); - - m_parent.ReportSymbolLookupError(bare_name_cs); - + Name.c_str()); + + m_parent.ReportSymbolLookupError(name_cs); return 0xbad0bad0; } - - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, - name, - symbol_load_addr); - - if (symbol_load_addr == 0) - return 0xbad00add; - - return symbol_load_addr; + else + { + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, + Name.c_str(), + ret); + return ret; + } } void * IRExecutionUnit::MemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) { assert (sizeof(void *) == 8); - + return (void*)getSymbolAddress(Name); } @@ -787,19 +1181,17 @@ IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address) } bool -IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) +IRExecutionUnit::CommitOneAllocation (lldb::ProcessSP &process_sp, + Error &error, + AllocationRecord &record) { - bool ret = true; - - lldb_private::Error err; - - for (AllocationRecord &record : m_records) + if (record.m_process_address != LLDB_INVALID_ADDRESS) + { + return true; + } + + switch (record.m_sect_type) { - if (record.m_process_address != LLDB_INVALID_ADDRESS) - continue; - - switch (record.m_sect_type) - { case lldb::eSectionTypeInvalid: case lldb::eSectionTypeDWARFDebugAbbrev: case lldb::eSectionTypeDWARFDebugAddr: @@ -818,7 +1210,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) case lldb::eSectionTypeDWARFAppleTypes: case lldb::eSectionTypeDWARFAppleNamespaces: case lldb::eSectionTypeDWARFAppleObjC: - err.Clear(); + error.Clear(); break; default: const bool zero_memory = false; @@ -827,13 +1219,26 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) record.m_permissions, eAllocationPolicyProcessOnly, zero_memory, - err); + error); break; - } + } + + return error.Success(); +} - if (!err.Success()) +bool +IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) +{ + bool ret = true; + + lldb_private::Error err; + + for (AllocationRecord &record : m_records) + { + ret = CommitOneAllocation(process_sp, err, record); + + if (!ret) { - ret = false; break; } } @@ -856,6 +1261,8 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) void IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) { + m_reported_allocations = true; + for (AllocationRecord &record : m_records) { if (record.m_process_address == LLDB_INVALID_ADDRESS) diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index a2b0c5b86851d..0285248314b67 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -7,16 +7,19 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Core/ConstString.h" #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/ModuleSpec.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRMemoryMap.h" -#include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/Endian.h" #include "lldb/Target/ABI.h" @@ -33,6 +36,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/raw_ostream.h" #include <map> @@ -100,8 +104,9 @@ public: ValueMap m_values; DataLayout &m_target_data; - lldb_private::IRMemoryMap &m_memory_map; + lldb_private::IRExecutionUnit &m_execution_unit; const BasicBlock *m_bb; + const BasicBlock *m_prev_bb; BasicBlock::const_iterator m_ii; BasicBlock::const_iterator m_ie; @@ -113,11 +118,13 @@ public: size_t m_addr_byte_size; InterpreterStackFrame (DataLayout &target_data, - lldb_private::IRMemoryMap &memory_map, + lldb_private::IRExecutionUnit &execution_unit, lldb::addr_t stack_frame_bottom, lldb::addr_t stack_frame_top) : m_target_data (target_data), - m_memory_map (memory_map) + m_execution_unit (execution_unit), + m_bb (nullptr), + m_prev_bb (nullptr) { m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig); m_addr_byte_size = (target_data.getPointerSize(0)); @@ -133,6 +140,7 @@ public: void Jump (const BasicBlock *bb) { + m_prev_bb = m_bb; m_bb = bb; m_ii = m_bb->begin(); m_ie = m_bb->end(); @@ -202,7 +210,7 @@ public: lldb_private::DataExtractor value_extractor; lldb_private::Error extract_error; - m_memory_map.GetMemoryData(value_extractor, process_address, value_size, extract_error); + m_execution_unit.GetMemoryData(value_extractor, process_address, value_size, extract_error); if (!extract_error.Success()) return false; @@ -227,7 +235,7 @@ public: lldb_private::Scalar cast_scalar; - if (!AssignToMatchType(cast_scalar, scalar.GetRawBits64(0), value->getType())) + if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType())) return false; size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); @@ -241,7 +249,7 @@ public: lldb_private::Error write_error; - m_memory_map.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); + m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); return write_error.Success(); } @@ -252,6 +260,17 @@ public: { default: break; + case Value::FunctionVal: + if (const Function *constant_func = dyn_cast<Function>(constant)) + { + lldb_private::ConstString name(constant_func->getName()); + lldb::addr_t addr = m_execution_unit.FindSymbol(name); + if (addr == LLDB_INVALID_ADDRESS) + return false; + value = APInt(m_target_data.getPointerSizeInBits(), addr); + return true; + } + break; case Value::ConstantIntVal: if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) { @@ -297,7 +316,8 @@ public: SmallVector <Value *, 8> indices (op_cursor, op_end); - uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices); + Type *src_elem_ty = cast<GEPOperator>(constant_expr)->getSourceElementType(); + uint64_t offset = m_target_data.getIndexedOffsetInType(src_elem_ty, indices); const bool is_signed = true; value += APInt(value.getBitWidth(), offset, is_signed); @@ -327,12 +347,12 @@ public: lldb_private::Error write_error; - m_memory_map.WritePointerToMemory(data_address, address, write_error); + m_execution_unit.WritePointerToMemory(data_address, address, write_error); if (!write_error.Success()) { lldb_private::Error free_error; - m_memory_map.Free(data_address, free_error); + m_execution_unit.Free(data_address, free_error); return false; } @@ -357,19 +377,18 @@ public: if (!ResolveConstantValue(resolved_value, constant)) return false; - lldb_private::StreamString buffer (lldb_private::Stream::eBinary, - m_memory_map.GetAddressByteSize(), - m_memory_map.GetByteOrder()); - size_t constant_size = m_target_data.getTypeStoreSize(constant->getType()); + lldb_private::DataBufferHeap buf(constant_size, 0); - const uint64_t *raw_data = resolved_value.getRawData(); + lldb_private::Error get_data_error; - buffer.PutRawBytes(raw_data, constant_size, lldb_private::endian::InlHostByteOrder()); + lldb_private::Scalar resolved_scalar(resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8)); + if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error)) + return false; lldb_private::Error write_error; - m_memory_map.WriteMemory(process_address, (const uint8_t*)buffer.GetData(), constant_size, write_error); + m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); return write_error.Success(); } @@ -408,7 +427,7 @@ public: lldb_private::Error read_error; - m_memory_map.ReadMemory(buf.GetBytes(), addr, length, read_error); + m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error); if (!read_error.Success()) return std::string("<couldn't read data>"); @@ -442,7 +461,7 @@ public: if (!ResolveConstant (data_address, constant)) { lldb_private::Error free_error; - m_memory_map.Free(data_address, free_error); + m_execution_unit.Free(data_address, free_error); return LLDB_INVALID_ADDRESS; } } @@ -462,6 +481,47 @@ static const char *memory_write_error = "Interpreter couldn't writ static const char *memory_read_error = "Interpreter couldn't read from memory"; static const char *infinite_loop_error = "Interpreter ran for too many cycles"; //static const char *bad_result_error = "Result of expression is in bad memory"; +static const char *too_many_functions_error = "Interpreter doesn't handle modules with multiple function bodies."; + +static bool +CanResolveConstant (llvm::Constant *constant) +{ + switch (constant->getValueID()) + { + default: + return false; + case Value::ConstantIntVal: + case Value::ConstantFPVal: + case Value::FunctionVal: + return true; + case Value::ConstantExprVal: + if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) + { + switch (constant_expr->getOpcode()) + { + default: + return false; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + return CanResolveConstant(constant_expr->getOperand(0)); + case Instruction::GetElementPtr: + { + ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); + Constant *base = dyn_cast<Constant>(*op_cursor); + if (!base) + return false; + + return CanResolveConstant(base); + } + } + } else { + return false; + } + case Value::ConstantPointerNullVal: + return true; + } +} bool IRInterpreter::CanInterpret (llvm::Module &module, @@ -480,7 +540,13 @@ IRInterpreter::CanInterpret (llvm::Module &module, if (fi->begin() != fi->end()) { if (saw_function_with_body) + { + if (log) + log->Printf("More than one function in the module has a body"); + error.SetErrorToGenericError(); + error.SetErrorString(too_many_functions_error); return false; + } saw_function_with_body = true; } } @@ -507,6 +573,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, case Instruction::Alloca: case Instruction::BitCast: case Instruction::Br: + case Instruction::PHI: break; case Instruction::Call: { @@ -609,18 +676,30 @@ IRInterpreter::CanInterpret (llvm::Module &module, return false; } } + + if (Constant *constant = llvm::dyn_cast<Constant>(operand)) + { + if (!CanResolveConstant(constant)) + { + if (log) + log->Printf("Unsupported constant: %s", PrintValue(constant).c_str()); + error.SetErrorString(unsupported_operand_error); + return false; + } + } } } } - return true;} + return true; +} bool IRInterpreter::Interpret (llvm::Module &module, llvm::Function &function, llvm::ArrayRef<lldb::addr_t> args, - lldb_private::IRMemoryMap &memory_map, + lldb_private::IRExecutionUnit &execution_unit, lldb_private::Error &error, lldb::addr_t stack_frame_bottom, lldb::addr_t stack_frame_top, @@ -642,7 +721,7 @@ IRInterpreter::Interpret (llvm::Module &module, DataLayout data_layout(&module); - InterpreterStackFrame frame(data_layout, memory_map, stack_frame_bottom, stack_frame_top); + InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom, stack_frame_top); if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) { @@ -752,7 +831,9 @@ IRInterpreter::Interpret (llvm::Module &module, result = L / R; break; case Instruction::UDiv: - result = L.GetRawBits64(0) / R.GetRawBits64(1); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = L / R; break; case Instruction::SRem: L.MakeSigned(); @@ -760,7 +841,9 @@ IRInterpreter::Interpret (llvm::Module &module, result = L % R; break; case Instruction::URem: - result = L.GetRawBits64(0) % R.GetRawBits64(1); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = L % R; break; case Instruction::Shl: result = L << R; @@ -848,7 +931,7 @@ IRInterpreter::Interpret (llvm::Module &module, lldb_private::Error write_error; - memory_map.WritePointerToMemory(P, R, write_error); + execution_unit.WritePointerToMemory(P, R, write_error); if (!write_error.Success()) { @@ -857,8 +940,8 @@ IRInterpreter::Interpret (llvm::Module &module, error.SetErrorToGenericError(); error.SetErrorString(memory_write_error); lldb_private::Error free_error; - memory_map.Free(P, free_error); - memory_map.Free(R, free_error); + execution_unit.Free(P, free_error); + execution_unit.Free(R, free_error); return false; } @@ -963,7 +1046,7 @@ IRInterpreter::Interpret (llvm::Module &module, return false; } - if (C.GetRawBits64(0)) + if (!C.IsZero()) frame.Jump(br_inst->getSuccessor(0)); else frame.Jump(br_inst->getSuccessor(1)); @@ -985,6 +1068,46 @@ IRInterpreter::Interpret (llvm::Module &module, } } continue; + case Instruction::PHI: + { + const PHINode *phi_inst = dyn_cast<PHINode>(inst); + + if (!phi_inst) + { + if (log) + log->Printf("getOpcode() returns PHI, but instruction is not a PHINode"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + if (!frame.m_prev_bb) + { + if (log) + log->Printf("Encountered PHI node without having jumped from another basic block"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value* value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb); + lldb_private::Scalar result; + if (!frame.EvaluateValue(result, value, module)) + { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(value).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + frame.AssignValue(inst, result, module); + + if (log) + { + log->Printf("Interpreted a %s", inst->getOpcodeName()); + log->Printf(" Incoming value : %s", frame.SummarizeValue(value).c_str()); + } + } + break; case Instruction::GetElementPtr: { const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst); @@ -999,7 +1122,7 @@ IRInterpreter::Interpret (llvm::Module &module, } const Value *pointer_operand = gep_inst->getPointerOperand(); - Type *pointer_type = pointer_operand->getType(); + Type *src_elem_ty = gep_inst->getSourceElementType(); lldb_private::Scalar P; @@ -1048,7 +1171,7 @@ IRInterpreter::Interpret (llvm::Module &module, const_indices.push_back(constant_index); } - uint64_t offset = data_layout.getIndexedOffset(pointer_type, const_indices); + uint64_t offset = data_layout.getIndexedOffsetInType(src_elem_ty, const_indices); lldb_private::Scalar Poffset = P + offset; @@ -1114,16 +1237,24 @@ IRInterpreter::Interpret (llvm::Module &module, result = (L != R); break; case CmpInst::ICMP_UGT: - result = (L.GetRawBits64(0) > R.GetRawBits64(0)); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L > R); break; case CmpInst::ICMP_UGE: - result = (L.GetRawBits64(0) >= R.GetRawBits64(0)); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L >= R); break; case CmpInst::ICMP_ULT: - result = (L.GetRawBits64(0) < R.GetRawBits64(0)); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L < R); break; case CmpInst::ICMP_ULE: - result = (L.GetRawBits64(0) <= R.GetRawBits64(0)); + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L <= R); break; case CmpInst::ICMP_SGT: L.MakeSigned(); @@ -1322,7 +1453,7 @@ IRInterpreter::Interpret (llvm::Module &module, lldb::addr_t R; lldb_private::Error read_error; - memory_map.ReadPointerFromMemory(&R, P, read_error); + execution_unit.ReadPointerFromMemory(&R, P, read_error); if (!read_error.Success()) { @@ -1337,7 +1468,7 @@ IRInterpreter::Interpret (llvm::Module &module, lldb_private::DataBufferHeap buffer(target_size, 0); read_error.Clear(); - memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error); + execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error); if (!read_error.Success()) { if (log) @@ -1348,7 +1479,7 @@ IRInterpreter::Interpret (llvm::Module &module, } lldb_private::Error write_error; - memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error); + execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) { if (log) @@ -1422,7 +1553,7 @@ IRInterpreter::Interpret (llvm::Module &module, lldb::addr_t R; lldb_private::Error read_error; - memory_map.ReadPointerFromMemory(&R, P, read_error); + execution_unit.ReadPointerFromMemory(&R, P, read_error); if (!read_error.Success()) { @@ -1437,7 +1568,7 @@ IRInterpreter::Interpret (llvm::Module &module, lldb_private::DataBufferHeap buffer(target_size, 0); read_error.Clear(); - memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error); + execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error); if (!read_error.Success()) { if (log) @@ -1448,7 +1579,7 @@ IRInterpreter::Interpret (llvm::Module &module, } lldb_private::Error write_error; - memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error); + execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error); if (!write_error.Success()) { if (log) @@ -1530,7 +1661,7 @@ IRInterpreter::Interpret (llvm::Module &module, } lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); - lldb_private::StreamString error_stream; + lldb_private::DiagnosticManager diagnostics; lldb_private::EvaluateExpressionOptions options; // We generally receive a function pointer which we must dereference @@ -1597,14 +1728,14 @@ IRInterpreter::Interpret (llvm::Module &module, lldb::addr_t addr = tmp_op.ULongLong(); size_t dataSize = 0; - if (memory_map.GetAllocSize(addr, dataSize)) + if (execution_unit.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); + execution_unit.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error); if (error.Fail()) { assert(!"we have failed to read the string from memory"); @@ -1635,31 +1766,24 @@ IRInterpreter::Interpret (llvm::Module &module, 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 - ) - ); + 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)) + lldb_private::StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong()); + 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); + lldb::ExpressionResults res = + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); // Check that the thread plan completed successfully if (res != lldb::ExpressionResults::eExpressionCompleted) diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp index e96bddde7cbb8..aa165722c437c 100644 --- a/source/Expression/IRMemoryMap.cpp +++ b/source/Expression/IRMemoryMap.cpp @@ -13,8 +13,10 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Scalar.h" #include "lldb/Expression/IRMemoryMap.h" +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" using namespace lldb_private; @@ -47,37 +49,136 @@ IRMemoryMap::~IRMemoryMap () } lldb::addr_t -IRMemoryMap::FindSpace (size_t size, bool zero_memory) +IRMemoryMap::FindSpace (size_t size) { + // The FindSpace algorithm's job is to find a region of memory that the + // underlying process is unlikely to be using. + // + // The memory returned by this function will never be written to. The only + // point is that it should not shadow process memory if possible, so that + // expressions processing real values from the process do not use the + // wrong data. + // + // If the process can in fact allocate memory (CanJIT() lets us know this) + // then this can be accomplished just be allocating memory in the inferior. + // Then no guessing is required. + lldb::TargetSP target_sp = m_target_wp.lock(); lldb::ProcessSP process_sp = m_process_wp.lock(); + + const bool process_is_alive = process_sp && process_sp->IsAlive(); lldb::addr_t ret = LLDB_INVALID_ADDRESS; if (size == 0) return ret; - if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) + if (process_is_alive && process_sp->CanJIT()) { Error alloc_error; - if (!zero_memory) - ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); - else - ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); + ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); if (!alloc_error.Success()) return LLDB_INVALID_ADDRESS; else return ret; } + + // At this point we know that we need to hunt. + // + // First, go to the end of the existing allocations we've made if there are + // any allocations. Otherwise start at the beginning of memory. - ret = 0; - if (!m_allocations.empty()) + if (m_allocations.empty()) + { + ret = 0x0; + } + else + { + auto back = m_allocations.rbegin(); + lldb::addr_t addr = back->first; + size_t alloc_size = back->second.m_size; + ret = llvm::alignTo(addr+alloc_size, 4096); + } + + // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped + // regions, walk forward through memory until a region is found that + // has adequate space for our allocation. + if (process_is_alive) + { + const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 ? + 0xffffffffffffffffull : 0xffffffffull; + + lldbassert(process_sp->GetAddressByteSize() == 4 || end_of_memory != 0xffffffffull); + + MemoryRegionInfo region_info; + Error err = process_sp->GetMemoryRegionInfo(ret, region_info); + if (err.Success()) + { + while (true) + { + if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo || + region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo || + region_info.GetExecutable() != MemoryRegionInfo::OptionalBool::eNo) + { + if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) + { + ret = LLDB_INVALID_ADDRESS; + break; + } + else + { + ret = region_info.GetRange().GetRangeEnd(); + } + } + else if (ret + size < region_info.GetRange().GetRangeEnd()) + { + return ret; + } + else + { + // ret stays the same. We just need to walk a bit further. + } + + err = process_sp->GetMemoryRegionInfo(region_info.GetRange().GetRangeEnd(), region_info); + if (err.Fail()) + { + lldbassert(!"GetMemoryRegionInfo() succeeded, then failed"); + ret = LLDB_INVALID_ADDRESS; + break; + } + } + } + } + + // We've tried our algorithm, and it didn't work. Now we have to reset back + // to the end of the allocations we've already reported, or use a 'sensible' + // default if this is our first allocation. + + if (m_allocations.empty()) + { + uint32_t address_byte_size = GetAddressByteSize(); + if (address_byte_size != UINT32_MAX) + { + switch (address_byte_size) + { + case 8: + ret = 0xffffffff00000000ull; + break; + case 4: + ret = 0xee000000ull; + break; + default: + break; + } + } + } + else { auto back = m_allocations.rbegin(); lldb::addr_t addr = back->first; size_t alloc_size = back->second.m_size; - ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096); + ret = llvm::alignTo(addr+alloc_size, 4096); } return ret; @@ -329,6 +430,13 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc alignment, policy); + if (zero_memory) + { + Error write_error; + std::vector<uint8_t> zero_buf(size, 0); + WriteMemory(aligned_address, zero_buf.data(), size, write_error); + } + if (log) { const char * policy_string; @@ -784,6 +892,7 @@ IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_addre return; } } + break; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp index eff0a2dc30d6d..0b969806280e7 100644 --- a/source/Expression/LLVMUserExpression.cpp +++ b/source/Expression/LLVMUserExpression.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" @@ -25,11 +26,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -58,7 +59,6 @@ LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, m_in_objectivec_method(false), m_in_static_method(false), m_needs_object_ptr(false), - m_const_object(false), m_target(NULL), m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) @@ -76,8 +76,9 @@ LLVMUserExpression::~LLVMUserExpression() } lldb::ExpressionResults -LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) { // The expression log is quite verbose, and if you're just tracking the execution of the // expression, it's quite convenient to have these logs come out with the STEP log as well. @@ -87,9 +88,10 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address)) + if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address)) { - error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -103,7 +105,7 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con if (!module || !function) { - error_stream.Printf("Supposed to interpret, but nothing is there"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "supposed to interpret, but nothing is there"); return lldb::eExpressionSetupError; } @@ -111,9 +113,10 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con std::vector<lldb::addr_t> args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", + __FUNCTION__); return lldb::eExpressionSetupError; } @@ -121,11 +124,12 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con function_stack_top = m_stack_frame_top; IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error, - function_stack_bottom, function_stack_top, exe_ctx); + function_stack_bottom, function_stack_top, exe_ctx); if (!interpreter_error.Success()) { - error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "supposed to interpret, but failed: %s", + interpreter_error.AsCString()); return lldb::eExpressionDiscarded; } } @@ -133,7 +137,7 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con { if (!exe_ctx.HasThreadScope()) { - error_stream.Printf("UserExpression::Execute called with no thread selected."); + diagnostic_manager.Printf(eDiagnosticSeverityError, "%s called with no thread selected", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -141,17 +145,22 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con std::vector<lldb::addr_t> args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", + __FUNCTION__); return lldb::eExpressionSetupError; } lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address, args, options, shared_ptr_to_me)); - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData()); return lldb::eExpressionSetupError; + } ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); @@ -168,7 +177,7 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); lldb::ExpressionResults execution_result = - exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); @@ -187,20 +196,21 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) - error_stream.Printf("Execution was interrupted, reason: %s.", error_desc); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Execution was interrupted, reason: %s.", + error_desc); else - error_stream.PutCString("Execution was interrupted."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "Execution was interrupted."); if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) - error_stream.PutCString( - "\nThe process has been returned to the state before expression evaluation."); + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been returned to the state before expression evaluation."); else { if (execution_result == lldb::eExpressionHitBreakpoint) user_expression_plan->TransferExpressionOwnership(); - error_stream.PutCString( - "\nThe process has been left at the point where it was interrupted, " + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been left at the point where it was interrupted, " "use \"thread return -x\" to return to the state before expression evaluation."); } @@ -208,7 +218,8 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con } else if (execution_result == lldb::eExpressionStoppedForDebug) { - error_stream.PutCString( + diagnostic_manager.PutCString( + eDiagnosticSeverityRemark, "Execution was halted at the first instruction of the expression " "function because \"debug\" was requested.\n" "Use \"thread return -x\" to return to the state before expression evaluation."); @@ -216,13 +227,13 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con } else if (execution_result != lldb::eExpressionCompleted) { - error_stream.Printf("Couldn't execute function; result was %s\n", - Process::ExecutionResultAsCString(execution_result)); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't execute function; result was %s", + Process::ExecutionResultAsCString(execution_result)); return execution_result; } } - if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) + if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top)) { return lldb::eExpressionCompleted; } @@ -233,13 +244,14 @@ LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, con } else { - error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } } bool -LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, lldb::addr_t function_stack_top) { @@ -250,7 +262,8 @@ LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext if (!m_dematerializer_sp) { - error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present"); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't apply expression side effects : no dematerializer is present"); return false; } @@ -260,8 +273,8 @@ LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext if (!dematerialize_error.Success()) { - error_stream.Printf("Couldn't apply expression side effects : %s\n", - dematerialize_error.AsCString("unknown error")); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : %s", + dematerialize_error.AsCString("unknown error")); return false; } @@ -276,7 +289,7 @@ LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext } bool -LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::addr_t &struct_address) { lldb::TargetSP target; @@ -285,7 +298,8 @@ LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, Executio if (!LockAndCheckContext(exe_ctx, target, process, frame)) { - error_stream.Printf("The context has changed before we could JIT the expression!\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "The context has changed before we could JIT the expression!"); return false; } @@ -309,7 +323,9 @@ LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, Executio if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't allocate space for materialized struct: %s", + alloc_error.AsCString()); return false; } } @@ -335,7 +351,8 @@ LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, Executio if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't allocate space for the stack frame: %s", + alloc_error.AsCString()); return false; } } @@ -347,7 +364,8 @@ LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, Executio if (!materialize_error.Success()) { - error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't materialize: %s", + materialize_error.AsCString()); return false; } } diff --git a/source/Expression/Makefile b/source/Expression/Makefile deleted file mode 100644 index 495f094d39006..0000000000000 --- a/source/Expression/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Expression/Makefile --------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../.. -LIBRARYNAME := lldbExpression -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp index 8d68b4f79819d..3575f5436d921 100644 --- a/source/Expression/Materializer.cpp +++ b/source/Expression/Materializer.cpp @@ -34,19 +34,19 @@ Materializer::AddStructMember (Entity &entity) { uint32_t size = entity.GetSize(); uint32_t alignment = entity.GetAlignment(); - + uint32_t ret; - + if (m_current_offset == 0) m_struct_alignment = alignment; - + if (m_current_offset % alignment) m_current_offset += (alignment - (m_current_offset % alignment)); - + ret = m_current_offset; - + m_current_offset += size; - + return ret; } @@ -54,15 +54,15 @@ void Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type) { m_size = type.GetByteSize(nullptr); - + uint32_t bit_alignment = type.GetTypeBitAlign(); - + if (bit_alignment % 8) { bit_alignment += 8; bit_alignment &= ~((uint32_t)0x111u); } - + m_alignment = bit_alignment / 8; } @@ -79,59 +79,59 @@ public: m_size = 8; m_alignment = 8; } - + void MakeAllocation (IRMemoryMap &map, Error &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); // Allocate a spare memory area to store the persistent variable's contents. - + Error allocate_error; const bool zero_memory = false; - + lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(), 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error); - + if (!allocate_error.Success()) { err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString()); return; } - + if (log) log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem); - + // Put the location of the spare memory into the live data of the ValueObject. - + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(), m_persistent_variable_sp->GetCompilerType(), m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, map.GetAddressByteSize()); - + // Clear the flag if the variable will never be deallocated. - + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) { Error leak_error; map.Leak(mem, leak_error); m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation; } - + // Write the contents of the variable to the area. - + Error write_error; - + map.WriteMemory (mem, m_persistent_variable_sp->GetValueBytes(), m_persistent_variable_sp->GetByteSize(), write_error); - + if (!write_error.Success()) { err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(), @@ -139,21 +139,21 @@ public: return; } } - + void DestroyAllocation (IRMemoryMap &map, Error &err) { Error deallocate_error; - + map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error); - + m_persistent_variable_sp->m_live_sp.reset(); - + if (!deallocate_error.Success()) { err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString()); } } - + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -162,7 +162,7 @@ public: Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; - + if (log) { log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]", @@ -170,26 +170,26 @@ public: m_persistent_variable_sp->GetName().AsCString(), m_persistent_variable_sp->m_flags); } - + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation) { MakeAllocation(map, err); m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated; - + if (!err.Success()) return; } - + if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) || m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) { Error write_error; - + map.WriteScalarToMemory(load_addr, m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(), map.GetAddressByteSize(), write_error); - + if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString()); @@ -201,7 +201,7 @@ public: return; } } - + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -210,7 +210,7 @@ public: Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + const lldb::addr_t load_addr = process_address + m_offset; if (log) @@ -220,7 +220,7 @@ public: m_persistent_variable_sp->GetName().AsCString(), m_persistent_variable_sp->m_flags); } - + if (m_delegate) { m_delegate->DidDematerialize(m_persistent_variable_sp); @@ -234,25 +234,25 @@ public: { // If the reference comes from the program, then the ClangExpressionVariable's // live variable data hasn't been set up yet. Do this now. - + lldb::addr_t location; Error read_error; - + map.ReadPointerFromMemory(&location, load_addr, read_error); - + if (!read_error.Success()) { err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); return; } - + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (), m_persistent_variable_sp.get()->GetCompilerType(), m_persistent_variable_sp->GetName(), location, eAddressTypeLoad, m_persistent_variable_sp->GetByteSize()); - + if (frame_top != LLDB_INVALID_ADDRESS && frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom && @@ -267,44 +267,44 @@ public: m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference; } } - + lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(); - + if (!m_persistent_variable_sp->m_live_sp) { err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString()); return; } - + if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad) { err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString()); return; } - + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry || m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) - { + { if (log) log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize()); - + // Read the contents of the spare memory area - + m_persistent_variable_sp->ValueUpdated (); - + Error read_error; - + map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem, m_persistent_variable_sp->GetByteSize(), read_error); - + if (!read_error.Success()) { err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); return; } - + m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry; } } @@ -313,13 +313,13 @@ public: err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString()); return; } - + lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); if (!process_sp || !process_sp->CanJIT()) { // Allocations are not persistent so persistent variables cannot stay materialized. - + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation; DestroyAllocation(map, err); @@ -334,24 +334,24 @@ public: return; } } - + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; - + Error err; - + const lldb::addr_t load_addr = process_address + m_offset; dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", load_addr, m_persistent_variable_sp->GetName().AsCString()); - + { dump_stream.Printf("Pointer:\n"); - + DataBufferHeap data (m_size, 0); - + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -359,20 +359,20 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + dump_stream.PutChar('\n'); } } - + { dump_stream.Printf("Target:\n"); - + lldb::addr_t target_address; - + map.ReadPointerFromMemory (&target_address, load_addr, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -380,9 +380,9 @@ public: else { DataBufferHeap data (m_persistent_variable_sp->GetByteSize(), 0); - + map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -390,17 +390,17 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address); - + dump_stream.PutChar('\n'); } } } - + log->PutCString(dump_stream.GetData()); } - + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } @@ -437,14 +437,14 @@ public: m_alignment = 8; m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType(); } - + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + const lldb::addr_t load_addr = process_address + m_offset; if (log) { @@ -452,46 +452,46 @@ public: (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } - + ExecutionContextScope *scope = frame_sp.get(); - + if (!scope) scope = map.GetBestExecutionContextScope(); - + lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); - + if (!valobj_sp) { err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); return; } - + Error valobj_error = valobj_sp->GetError(); - + if (valobj_error.Fail()) { err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString()); return; } - + if (m_is_reference) { DataExtractor valobj_extractor; Error extract_error; valobj_sp->GetData(valobj_extractor, extract_error); - + if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } - + lldb::offset_t offset = 0; lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); - + Error write_error; map.WritePointerToMemory(load_addr, reference_addr, write_error); - + if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); @@ -507,7 +507,7 @@ public: { Error write_error; map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); - + if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); @@ -524,14 +524,14 @@ public: err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } - + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); return; } - - if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize()) + + if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) { @@ -539,20 +539,20 @@ public: } else { - err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")", + err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", m_variable_sp->GetName().AsCString(), m_variable_sp->GetType()->GetByteSize(), data.GetByteSize()); } return; } - + size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; - + if (!byte_align) byte_align = 1; - + Error alloc_error; const bool zero_memory = false; @@ -562,31 +562,31 @@ public: IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); - + m_temporary_allocation_size = data.GetByteSize(); - + m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); - + if (!alloc_error.Success()) { err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); return; } - + Error write_error; - + map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); - + if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } - + Error pointer_write_error; - + map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); - + if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); @@ -594,7 +594,7 @@ public: } } } - + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -611,36 +611,36 @@ public: (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } - + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { ExecutionContextScope *scope = frame_sp.get(); - + if (!scope) scope = map.GetBestExecutionContextScope(); - + lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); - + if (!valobj_sp) { err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); return; } - + lldb_private::DataExtractor data; - + Error extract_error; - + map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error); - + if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString()); return; } - + bool actually_write = true; - + if (m_original_data) { if ((data.GetByteSize() == m_original_data->GetByteSize()) && @@ -649,54 +649,54 @@ public: actually_write = false; } } - + Error set_error; - + if (actually_write) { valobj_sp->SetData(data, set_error); - + if (!set_error.Success()) { err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); return; } } - + Error free_error; - + map.Free(m_temporary_allocation, free_error); - + if (!free_error.Success()) { err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString()); return; } - + m_original_data.reset(); m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } } - + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; const lldb::addr_t load_addr = process_address + m_offset; dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); - + Error err; - + lldb::addr_t ptr = LLDB_INVALID_ADDRESS; - + { dump_stream.Printf("Pointer:\n"); - + DataBufferHeap data (m_size, 0); - + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -704,17 +704,17 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + lldb::offset_t offset; - + ptr = extractor.GetPointer(&offset); - + dump_stream.PutChar('\n'); } } - + if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { dump_stream.Printf("Points to process memory:\n"); @@ -723,7 +723,7 @@ public: { dump_stream.Printf("Temporary allocation:\n"); } - + if (ptr == LLDB_INVALID_ADDRESS) { dump_stream.Printf(" <could not be be found>\n"); @@ -731,9 +731,9 @@ public: else { DataBufferHeap data (m_temporary_allocation_size, 0); - + map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -741,24 +741,24 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + dump_stream.PutChar('\n'); } } - + log->PutCString(dump_stream.GetData()); } - + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { Error free_error; - + map.Free(m_temporary_allocation, free_error); - + m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } @@ -802,7 +802,7 @@ public: m_size = 8; m_alignment = 8; } - + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -815,16 +815,16 @@ public: err.SetErrorString("Trying to create a temporary region for the result but one exists"); return; } - + const lldb::addr_t load_addr = process_address + m_offset; size_t byte_size = m_type.GetByteSize(nullptr); size_t bit_align = m_type.GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; - + if (!byte_align) byte_align = 1; - + Error alloc_error; const bool zero_memory = true; @@ -835,24 +835,24 @@ public: zero_memory, alloc_error); m_temporary_allocation_size = byte_size; - + if (!alloc_error.Success()) { err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString()); return; } - + Error pointer_write_error; - + map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); - + if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString()); } } } - + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -861,73 +861,73 @@ public: Error &err) override { err.Clear(); - + ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); - + if (!exe_scope) { err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope"); return; } - + lldb::addr_t address; Error read_error; const lldb::addr_t load_addr = process_address + m_offset; - + map.ReadPointerFromMemory (&address, load_addr, read_error); - + if (!read_error.Success()) { err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address"); return; } - + lldb::TargetSP target_sp = exe_scope->CalculateTarget(); - + if (!target_sp) { err.SetErrorString("Couldn't dematerialize a result variable: no target"); return; } - + Error type_system_error; TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage()); - + if (!type_system) { err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString()); return; } - + PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState(); - + if (!persistent_state) { err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables"); return; } - + ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName(); - + lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize()); - + if (!ret) { err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString()); return; } - + lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); - + if (m_delegate) { m_delegate->DidDematerialize(ret); } - + bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); if (can_persist && m_keep_in_memory) @@ -939,24 +939,24 @@ public: eAddressTypeLoad, map.GetAddressByteSize()); } - + ret->ValueUpdated(); - + const size_t pvar_byte_size = ret->GetByteSize(); uint8_t *pvar_data = ret->GetValueBytes(); - + map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); - + if (!read_error.Success()) { err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); return; } - + if (!can_persist || !m_keep_in_memory) { ret->m_flags |= ExpressionVariable::EVNeedsAllocation; - + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { Error free_error; @@ -967,30 +967,30 @@ public: { ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; } - + m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } - + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; - + const lldb::addr_t load_addr = process_address + m_offset; dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); - + Error err; - + lldb::addr_t ptr = LLDB_INVALID_ADDRESS; - + { dump_stream.Printf("Pointer:\n"); - + DataBufferHeap data (m_size, 0); - + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -998,17 +998,17 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + lldb::offset_t offset; - + ptr = extractor.GetPointer(&offset); - + dump_stream.PutChar('\n'); } } - + if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { dump_stream.Printf("Points to process memory:\n"); @@ -1017,7 +1017,7 @@ public: { dump_stream.Printf("Temporary allocation:\n"); } - + if (ptr == LLDB_INVALID_ADDRESS) { dump_stream.Printf(" <could not be be found>\n"); @@ -1025,9 +1025,9 @@ public: else { DataBufferHeap data (m_temporary_allocation_size, 0); - + map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -1035,25 +1035,25 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + dump_stream.PutChar('\n'); } } - + log->PutCString(dump_stream.GetData()); } - + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) { Error free_error; - + map.Free(m_temporary_allocation, free_error); } - + m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } @@ -1062,7 +1062,7 @@ private: CompilerType m_type; bool m_is_program_reference; bool m_keep_in_memory; - + lldb::addr_t m_temporary_allocation; size_t m_temporary_allocation_size; Materializer::PersistentVariableDelegate *m_delegate; @@ -1093,7 +1093,7 @@ public: m_size = 8; m_alignment = 8; } - + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -1109,38 +1109,38 @@ public: (uint64_t)load_addr, m_symbol.GetName().AsCString()); } - + const Address sym_address = m_symbol.GetAddress(); ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); - + lldb::TargetSP target_sp; - + if (exe_scope) target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); - + if (!target_sp) { err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString()); return; } - + lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); - + if (resolved_address == LLDB_INVALID_ADDRESS) resolved_address = sym_address.GetFileAddress(); - + Error pointer_write_error; - + map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); - + if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); return; } } - + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -1158,27 +1158,27 @@ public: (uint64_t)load_addr, m_symbol.GetName().AsCString()); } - + // no work needs to be done } - + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; - + Error err; - + const lldb::addr_t load_addr = process_address + m_offset; dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString()); - + { dump_stream.Printf("Pointer:\n"); - + DataBufferHeap data (m_size, 0); - + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -1186,16 +1186,16 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + dump_stream.PutChar('\n'); } } - + log->PutCString(dump_stream.GetData()); } - + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } @@ -1225,14 +1225,14 @@ public: m_size = m_register_info.byte_size; m_alignment = m_register_info.byte_size; } - + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + const lldb::addr_t load_addr = process_address + m_offset; if (log) @@ -1243,37 +1243,37 @@ public: } RegisterValue reg_value; - + if (!frame_sp.get()) { err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name); return; } - + lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); - + if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) { err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); return; } - + DataExtractor register_data; - + if (!reg_value.GetData(register_data)) { err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); return; } - + if (register_data.GetByteSize() != m_register_info.byte_size) { err.SetErrorStringWithFormat("data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size); return; } - + m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); - + Error write_error; map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); @@ -1284,7 +1284,7 @@ public: return; } } - + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, @@ -1293,7 +1293,7 @@ public: Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + const lldb::addr_t load_addr = process_address + m_offset; if (log) @@ -1302,64 +1302,64 @@ public: (uint64_t)load_addr, m_register_info.name); } - + Error extract_error; - + DataExtractor register_data; - + if (!frame_sp.get()) { err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name); return; } - + lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); - + map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); - + if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); return; } - + if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) { // No write required, and in particular we avoid errors if the register wasn't writable - + m_register_contents.reset(); return; } - + m_register_contents.reset(); - + RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); - + if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) { err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); return; } } - + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; - + Error err; - + const lldb::addr_t load_addr = process_address + m_offset; - + dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name); - + { dump_stream.Printf("Value:\n"); - + DataBufferHeap data (m_size, 0); - + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - + if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -1367,16 +1367,16 @@ public: else { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); - + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); - + dump_stream.PutChar('\n'); } } - + log->PutCString(dump_stream.GetData()); } - + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } @@ -1406,7 +1406,7 @@ Materializer::Materializer () : Materializer::~Materializer () { DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); - + if (dematerializer_sp) dematerializer_sp->Wipe(); } @@ -1507,7 +1507,7 @@ Materializer::Dematerializer::Wipe () { if (!IsValid()) return; - + for (EntityUP &entity_up : m_materializer->m_entities) { entity_up->Wipe (*m_map, m_process_address); diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp index 1727a13abd063..30f256002fc87 100644 --- a/source/Expression/REPL.cpp +++ b/source/Expression/REPL.cpp @@ -363,6 +363,7 @@ REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code) result_valobj_sp, error, 0, // Line offset + nullptr, // Fixed Expression &jit_module_sp); //CommandInterpreter &ci = debugger.GetCommandInterpreter(); @@ -410,7 +411,7 @@ REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code) case lldb::eExpressionSetupError: case lldb::eExpressionParseError: add_to_code = false; - // Fall through + LLVM_FALLTHROUGH; case lldb::eExpressionDiscarded: error_sp->Printf("%s\n", error.AsCString()); break; diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp index 70f004ba25c9e..3e2e07e9cb22c 100644 --- a/source/Expression/UserExpression.cpp +++ b/source/Expression/UserExpression.cpp @@ -16,18 +16,19 @@ #include <string> #include <map> +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" #include "lldb/Expression/UserExpression.h" -#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" @@ -159,6 +160,7 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, + std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -193,6 +195,11 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; + + // We need to set the expression execution thread here, turns out parse can call functions in the process of + // looking up symbols, which will escape the context set by exe_ctx passed to Execute. + lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); + ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp); const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); @@ -232,8 +239,6 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } - - StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); @@ -244,23 +249,75 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } - if (!user_expression_sp->Parse (error_stream, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info)) + DiagnosticManager diagnostic_manager; + + bool parse_success = user_expression_sp->Parse(diagnostic_manager, + exe_ctx, + execution_policy, + keep_expression_in_memory, + generate_debug_info); + + // Calculate the fixed expression always, since we need it for errors. + std::string tmp_fixed_expression; + if (fixed_expression == nullptr) + fixed_expression = &tmp_fixed_expression; + + const char *fixed_text = user_expression_sp->GetFixedText(); + if (fixed_text != nullptr) + fixed_expression->append(fixed_text); + + // If there is a fixed expression, try to parse it: + if (!parse_success) { execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) + { + lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(), + full_prefix, + language, + desired_type, + options, + error)); + DiagnosticManager fixed_diagnostic_manager; + parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager, + exe_ctx, + execution_policy, + keep_expression_in_memory, + generate_debug_info); + if (parse_success) + { + diagnostic_manager.Clear(); + user_expression_sp = fixed_expression_sp; + } + else + { + // If the fixed expression failed to parse, don't tell the user about, that won't help. + fixed_expression->clear(); + } + } + + if (!parse_success) + { + if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) + { + error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s", + fixed_expression->c_str()); + } + else + { + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); + else + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); + } + } } - else + + if (parse_success) { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) @@ -274,8 +331,13 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); + } + else if (execution_policy == eExecutionPolicyTopLevel) + { + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); + return lldb::eExpressionCompleted; } else { @@ -286,31 +348,23 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, return lldb::eExpressionInterrupted; } - error_stream.GetString().clear(); + diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); - execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - options, - user_expression_sp, - expr_result); - - if (options.GetResultIsInternal() && expr_result && process) - { - process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); - } + execution_results = + user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { @@ -346,3 +400,21 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx, return execution_results; } + +lldb::ExpressionResults +UserExpression::Execute(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result_var) +{ + lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); + Target *target = exe_ctx.GetTargetPtr(); + if (options.GetResultIsInternal() && result_var && target) + { + target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var); + } + return expr_result; +} + + diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp index f93e358d35dfa..2ff77f093db20 100644 --- a/source/Expression/UtilityFunction.cpp +++ b/source/Expression/UtilityFunction.cpp @@ -20,10 +20,11 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/Host.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -69,14 +70,17 @@ UtilityFunction::~UtilityFunction () // FIXME: We should check that every time this is called it is called with the same return type & arguments... FunctionCaller * -UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error) +UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, lldb::ThreadSP thread_to_use_sp, Error &error) { if (m_caller_up) return m_caller_up.get(); ProcessSP process_sp = m_jit_process_wp.lock(); if (!process_sp) + { + error.SetErrorString("Can't make a function caller without a process."); return nullptr; + } Address impl_code_address; impl_code_address.SetOffset(StartAddress()); @@ -96,26 +100,24 @@ UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const Valu } if (m_caller_up) { - StreamString errors; - errors.Clear(); - unsigned num_errors = m_caller_up->CompileFunction(errors); + DiagnosticManager diagnostics; + + unsigned num_errors = m_caller_up->CompileFunction(thread_to_use_sp, diagnostics); if (num_errors) { - error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".", - m_function_name.c_str(), - errors.GetData()); + error.SetErrorStringWithFormat("Error compiling %s caller function: \"%s\".", m_function_name.c_str(), + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } - - errors.Clear(); + + diagnostics.Clear(); ExecutionContext exe_ctx(process_sp); - - if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors)) + + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) { - error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".", - m_function_name.c_str(), - errors.GetData()); + error.SetErrorStringWithFormat("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(), + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } |