summaryrefslogtreecommitdiff
path: root/source/Expression
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:50:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:50:09 +0000
commitf3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch)
tree48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Expression
parent2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff)
Notes
Diffstat (limited to 'source/Expression')
-rw-r--r--source/Expression/CMakeLists.txt1
-rw-r--r--source/Expression/DWARFExpression.cpp165
-rw-r--r--source/Expression/DiagnosticManager.cpp91
-rw-r--r--source/Expression/ExpressionSourceCode.cpp113
-rw-r--r--source/Expression/ExpressionVariable.cpp54
-rw-r--r--source/Expression/FunctionCaller.cpp89
-rw-r--r--source/Expression/IRDynamicChecks.cpp68
-rw-r--r--source/Expression/IRExecutionUnit.cpp655
-rw-r--r--source/Expression/IRInterpreter.cpp242
-rw-r--r--source/Expression/IRMemoryMap.cpp127
-rw-r--r--source/Expression/LLVMUserExpression.cpp90
-rw-r--r--source/Expression/Makefile14
-rw-r--r--source/Expression/Materializer.cpp516
-rw-r--r--source/Expression/REPL.cpp3
-rw-r--r--source/Expression/UserExpression.cpp132
-rw-r--r--source/Expression/UtilityFunction.cpp34
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;
}