summaryrefslogtreecommitdiffstats
path: root/lldb/source/Expression
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Expression')
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp65
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp67
-rw-r--r--lldb/source/Expression/ClangFunction.cpp9
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp328
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp9
-rw-r--r--lldb/source/Expression/IRForTarget.cpp139
-rw-r--r--lldb/source/Expression/IRInterpreter.cpp277
-rw-r--r--lldb/source/Expression/IRMemoryMap.cpp3
-rw-r--r--lldb/source/Expression/Materializer.cpp272
9 files changed, 747 insertions, 422 deletions
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index ec2dbf6b8a0..ca7da77f719 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -459,6 +459,51 @@ ClangExpressionDeclMap::AddPersistentVariable
{
assert (m_parser_vars.get());
+ if (m_parser_vars->m_materializer && is_result)
+ {
+ Error err;
+
+ ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target == NULL)
+ return false;
+
+ ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
+
+ TypeFromUser user_type(m_ast_importer->DeportType(context,
+ parser_type.GetASTContext(),
+ parser_type.GetOpaqueQualType()),
+ context);
+
+ uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err);
+
+ m_found_entities.CreateVariable(exe_ctx.GetBestExecutionContextScope(),
+ name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size);
+
+ ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(name));
+
+ if (!var_sp)
+ return false;
+
+ var_sp->EnableParserVars(GetParserID());
+
+ ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
+
+ parser_vars->m_named_decl = decl;
+ parser_vars->m_parser_type = parser_type;
+
+ var_sp->EnableJITVars(GetParserID());
+
+ ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
+
+ jit_vars->m_offset = offset;
+
+ return true;
+ }
+
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Target *target = exe_ctx.GetTargetPtr();
@@ -526,12 +571,6 @@ ClangExpressionDeclMap::AddPersistentVariable
parser_vars->m_named_decl = decl;
parser_vars->m_parser_type = parser_type;
- if (m_parser_vars->m_materializer)
- {
- Error err;
- m_parser_vars->m_materializer->AddResultVariable(user_type, m_keep_result_in_memory, err);
- }
-
return true;
}
@@ -581,6 +620,14 @@ ClangExpressionDeclMap::AddValueToStruct
parser_vars->m_llvm_value = value;
+ if (ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()))
+ {
+ // We already laid this out; do not touch
+
+ if (log)
+ log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset);
+ }
+
var_sp->EnableJITVars(GetParserID());
ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
@@ -1593,7 +1640,9 @@ ClangExpressionDeclMap::DoMaterialize
bool ret = true;
- m_material_vars->m_dematerializer_sp->Dematerialize(dematerialize_error, stack_frame_top, stack_frame_bottom);
+ ClangExpressionVariableSP result;
+
+ m_material_vars->m_dematerializer_sp->Dematerialize(dematerialize_error, result, stack_frame_top, stack_frame_bottom);
m_material_vars->m_dematerializer_sp.reset();
if (!dematerialize_error.Success())
@@ -1663,7 +1712,7 @@ ClangExpressionDeclMap::DoMaterialize
Error materialize_error;
- m_material_vars->m_dematerializer_sp = m_parser_vars->m_materializer->Materialize(frame_sp, result_sp, map, m_material_vars->m_materialized_location, materialize_error);
+ m_material_vars->m_dematerializer_sp = m_parser_vars->m_materializer->Materialize(frame_sp, map, m_material_vars->m_materialized_location, materialize_error);
if (!materialize_error.Success())
{
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 2922898a0ca..5e4b934822b 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -22,6 +22,7 @@
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRDynamicChecks.h"
+#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -464,8 +465,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
lldb::addr_t &func_end,
STD_UNIQUE_PTR(IRExecutionUnit) &execution_unit_ap,
ExecutionContext &exe_ctx,
- bool &evaluated_statically,
- lldb::ClangExpressionVariableSP &const_result,
+ bool &can_interpret,
ExecutionPolicy execution_policy)
{
func_addr = LLDB_INVALID_ADDRESS;
@@ -518,50 +518,39 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
IRForTarget ir_for_target(decl_map,
m_expr.NeedsVariableResolution(),
- execution_policy,
- const_result,
*m_execution_unit,
error_stream,
function_name.AsCString());
bool ir_can_run = ir_for_target.runOnModule(*m_execution_unit->GetModule());
- Error &interpreter_error(ir_for_target.getInterpreterError());
+ Error interpret_error;
- if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success())
+ can_interpret = IRInterpreter::CanInterpret(*m_execution_unit->GetModule(), *m_execution_unit->GetFunction(), interpret_error);
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (!ir_can_run)
{
- if (const_result)
- const_result->TransferAddress();
- evaluated_statically = true;
- err.Clear();
+ err.SetErrorString("The expression could not be prepared to run in the target");
return err;
}
- Process *process = exe_ctx.GetProcessPtr();
-
- if (!process || execution_policy == eExecutionPolicyNever)
+ if (!can_interpret && execution_policy == eExecutionPolicyNever)
{
- err.SetErrorToGenericError();
- if (execution_policy == eExecutionPolicyAlways)
- err.SetErrorString("Execution needed to run in the target, but the target can't be run");
- else
- err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString());
-
+ err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
return err;
}
- else if (!ir_can_run)
+
+ if (!process && execution_policy == eExecutionPolicyAlways)
{
- err.SetErrorToGenericError();
- err.SetErrorString("The expression could not be prepared to run in the target");
-
+ err.SetErrorString("Expression needed to run in the target, but the target can't be run");
return err;
}
- if (execution_policy != eExecutionPolicyNever &&
- m_expr.NeedsValidation() &&
- process)
+ if (execution_policy == eExecutionPolicyAlways || !can_interpret)
{
- if (!process->GetDynamicCheckers())
+ if (!process->GetDynamicCheckers() && m_expr.NeedsValidation())
{
DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
@@ -581,20 +570,24 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
+
+ IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
+
+ if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't add dynamic checks to the expression");
+ return err;
+ }
}
- IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
-
- if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Couldn't add dynamic checks to the expression");
- return err;
- }
+ m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
}
}
-
- m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+ else
+ {
+ m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+ }
execution_unit_ap.reset (m_execution_unit.release());
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index c0131b06a58..e37a16a4fb7 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -260,17 +260,14 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
if (m_JITted)
return true;
-
- lldb::ClangExpressionVariableSP const_result;
-
- bool evaluated_statically = false; // should stay that way
+
+ bool can_interpret = false; // should stay that way
Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
m_execution_unit_ap,
exe_ctx,
- evaluated_statically,
- const_result,
+ can_interpret,
eExecutionPolicyAlways));
if (!jit_error.Success())
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 6f65b11a686..083f67aa2cf 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -30,6 +30,7 @@
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
@@ -67,8 +68,7 @@ ClangUserExpression::ClangUserExpression (const char *expr,
m_needs_object_ptr (false),
m_const_object (false),
m_target (NULL),
- m_evaluated_statically (false),
- m_const_result ()
+ m_can_interpret (false)
{
switch (m_language)
{
@@ -469,8 +469,7 @@ ClangUserExpression::Parse (Stream &error_stream,
m_jit_end_addr,
m_execution_unit_ap,
exe_ctx,
- m_evaluated_statically,
- m_const_result,
+ m_can_interpret,
execution_policy);
if (jit_error.Success())
@@ -490,6 +489,46 @@ ClangUserExpression::Parse (Stream &error_stream,
}
}
+static lldb::addr_t
+GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err)
+{
+ err.Clear();
+
+ if (!frame_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::VariableSP var_sp;
+ lldb::ValueObjectSP valobj_sp;
+
+ valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
+ lldb::eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember ||
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess ||
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar ||
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren ||
+ StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+ var_sp,
+ err);
+
+ if (!err.Success())
+ return LLDB_INVALID_ADDRESS;
+
+ lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ret == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return ret;
+}
+
bool
ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx,
@@ -497,8 +536,6 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
lldb::addr_t &object_ptr,
lldb::addr_t &cmd_ptr)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
lldb::TargetSP target;
lldb::ProcessSP process;
lldb::StackFrameSP frame;
@@ -512,10 +549,8 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
return false;
}
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
- {
- Error materialize_error;
-
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
if (m_needs_object_ptr)
{
ConstString object_name;
@@ -534,9 +569,13 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
return false;
}
- if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, materialize_error)))
+ Error object_ptr_error;
+
+ object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
{
- error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", materialize_error.AsCString());
+ error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
object_ptr = 0;
}
@@ -544,52 +583,40 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
{
ConstString cmd_name("_cmd");
- if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, materialize_error, true)))
+ cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
{
- error_stream.Printf("warning: couldn't get object pointer (substituting NULL): %s\n", materialize_error.AsCString());
+ error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
cmd_ptr = 0;
}
}
}
-
- if (!m_expr_decl_map->Materialize(*m_execution_unit_ap, struct_address, materialize_error))
+
+ Error alloc_error;
+
+ struct_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
+ m_materializer_ap->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror,
+ alloc_error);
+
+ if (!alloc_error.Success())
{
- error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
+ error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
return false;
}
-
-#if 0
- // jingham: look here
- StreamFile logfile ("/tmp/exprs.txt", "a");
- logfile.Printf("0x%16.16" PRIx64 ": thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
-#endif
- if (log)
+ m_materialized_address = struct_address;
+
+ Error materialize_error;
+
+ m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error);
+
+ if (!materialize_error.Success())
{
- log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
-
- log->Printf(" Function address : 0x%" PRIx64, (uint64_t)m_jit_start_addr);
-
- if (m_needs_object_ptr)
- log->Printf(" Object pointer : 0x%" PRIx64, (uint64_t)object_ptr);
-
- log->Printf(" Structure address : 0x%" PRIx64, (uint64_t)struct_address);
-
- StreamString args;
-
- Error dump_error;
-
- if (struct_address)
- {
- if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
- {
- log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
- }
- else
- {
- log->Printf(" Structure contents:\n%s", args.GetData());
- }
- }
+ error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
+ return false;
}
}
return true;
@@ -635,35 +662,31 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
- {
log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
- StreamString args;
-
- Error dump_error;
-
- if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
- {
- log->Printf(" Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
- }
- else
- {
- log->Printf(" Structure contents:\n%s", args.GetData());
- }
+ lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
+
+ if (!m_dematerializer_sp)
+ {
+ error_stream.Printf ("Couldn't dematerialize struct : no dematerializer is present");
+ return false;
}
- lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
+ Error dematerialize_error;
-
- if (!m_expr_decl_map->Dematerialize(result, *m_execution_unit_ap, function_stack_pointer, function_stack_bottom, expr_error))
+ m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_pointer, function_stack_bottom);
+
+ if (!dematerialize_error.Success())
{
error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
return false;
}
-
+
if (result)
result->TransferAddress();
+ m_dematerializer_sp.reset();
+
return true;
}
@@ -681,7 +704,7 @@ ClangUserExpression::Execute (Stream &error_stream,
// expression, it's quite convenient to have these logs come out with the STEP log as well.
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
{
lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
@@ -694,73 +717,115 @@ ClangUserExpression::Execute (Stream &error_stream,
return eExecutionSetupError;
}
- const bool stop_others = true;
- const bool try_all_threads = run_others;
-
- Address wrapper_address (m_jit_start_addr);
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- struct_address,
- stop_others,
- unwind_on_error,
- ignore_breakpoints,
- (m_needs_object_ptr ? &object_ptr : NULL),
- ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
- shared_ptr_to_me));
-
- if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
- return eExecutionSetupError;
+ lldb::addr_t function_stack_pointer = NULL;
- lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
+ if (m_can_interpret)
+ {
+ llvm::Module *module = m_execution_unit_ap->GetModule();
+ llvm::Function *function = m_execution_unit_ap->GetFunction();
+
+ if (!module || !function)
+ {
+ error_stream.Printf("Supposed to interpret, but nothing is there");
+ return eExecutionSetupError;
+ }
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+ Error interpreter_error;
- ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
- call_plan_sp,
- stop_others,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
- error_stream);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+ llvm::SmallVector <lldb::addr_t, 3> args;
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
-
- if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
- {
- const char *error_desc = NULL;
+ if (m_needs_object_ptr)
+ {
+ args.push_back(object_ptr);
+
+ if (m_objectivec)
+ args.push_back(cmd_ptr);
+ }
+
+ args.push_back(struct_address);
+
+ IRInterpreter::Interpret (*module,
+ *function,
+ args,
+ *m_execution_unit_ap.get(),
+ interpreter_error);
- if (call_plan_sp)
+ if (!interpreter_error.Success())
{
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
+ error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+ return eExecutionDiscarded;
}
- if (error_desc)
- error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
- else
- error_stream.Printf ("Execution was interrupted.");
-
- if ((execution_result == eExecutionInterrupted && unwind_on_error)
- || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
- error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
- else
- error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
-
- return execution_result;
}
- else if (execution_result != eExecutionCompleted)
+ else
{
- error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
- return execution_result;
+ const bool stop_others = true;
+ const bool try_all_threads = run_others;
+
+ Address wrapper_address (m_jit_start_addr);
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
+ wrapper_address,
+ struct_address,
+ stop_others,
+ unwind_on_error,
+ ignore_breakpoints,
+ (m_needs_object_ptr ? &object_ptr : NULL),
+ ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
+ shared_ptr_to_me));
+
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
+ return eExecutionSetupError;
+
+ function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
+
+ if (log)
+ log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
+ call_plan_sp,
+ stop_others,
+ try_all_threads,
+ unwind_on_error,
+ ignore_breakpoints,
+ timeout_usec,
+ error_stream);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ if (log)
+ log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
+
+ if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
+ {
+ const char *error_desc = NULL;
+
+ if (call_plan_sp)
+ {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
+ else
+ error_stream.Printf ("Execution was interrupted.");
+
+ if ((execution_result == eExecutionInterrupted && unwind_on_error)
+ || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
+ error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
+ else
+ error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
+
+ return execution_result;
+ }
+ else if (execution_result != eExecutionCompleted)
+ {
+ error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
+ return execution_result;
+ }
}
if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
@@ -862,19 +927,8 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
{
lldb::ClangExpressionVariableSP expr_result;
- if (user_expression_sp->EvaluatedStatically())
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
-
- if (user_expression_sp->m_const_result)
- result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
- else
- error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
-
- execution_results = eExecutionCompleted;
- }
- else if (execution_policy == eExecutionPolicyNever)
+ if (execution_policy == eExecutionPolicyNever &&
+ !user_expression_sp->CanInterpret())
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index aed0e244e7f..c911c279993 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -125,17 +125,14 @@ ClangUtilityFunction::Install (Stream &error_stream,
//////////////////////////////////
// JIT the output of the parser
//
-
- lldb::ClangExpressionVariableSP const_result;
-
- bool evaluated_statically = false; // should stay that way
+
+ bool can_interpret = false; // should stay that way
Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
m_execution_unit_ap,
exe_ctx,
- evaluated_statically,
- const_result,
+ can_interpret,
eExecutionPolicyAlways);
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index 2b3618a53a7..1c1f120b86c 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -42,6 +42,7 @@ static char ID;
IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) :
m_execution_unit(execution_unit),
+ m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()),
m_allocation(LLDB_INVALID_ADDRESS)
{
}
@@ -63,15 +64,11 @@ lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::ClangExpressionVariableSP &const_result,
lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
m_resolve_vars(resolve_vars),
- m_execution_policy(execution_policy),
- m_interpret_success(false),
m_func_name(func_name),
m_module(NULL),
m_decl_map(decl_map),
@@ -79,7 +76,6 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
m_memory_map(execution_unit),
m_CFStringCreateWithBytes(NULL),
m_sel_registerName(NULL),
- m_const_result(const_result),
m_error_stream(error_stream),
m_has_side_effects(false),
m_result_store(NULL),
@@ -444,97 +440,6 @@ IRForTarget::DeclForGlobal (GlobalValue *global_val)
return DeclForGlobal(global_val, m_module);
}
-void
-IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
- const lldb_private::ConstString &name,
- lldb_private::TypeFromParser type)
-{
- if (llvm::ConstantExpr *init_expr = dyn_cast<llvm::ConstantExpr>(initializer))
- {
- switch (init_expr->getOpcode())
- {
- default:
- return;
- case Instruction::IntToPtr:
- MaybeSetConstantResult (init_expr->getOperand(0), name, type);
- return;
- }
- }
- else if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
- {
- m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
- }
-}
-
-void
-IRForTarget::MaybeSetCastResult (lldb_private::TypeFromParser type)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_result_store)
- return;
-
- LoadInst *original_load = NULL;
-
- for (llvm::Value *current_value = m_result_store->getValueOperand(), *next_value;
- current_value != NULL;
- current_value = next_value)
- {
- CastInst *cast_inst = dyn_cast<CastInst>(current_value);
- LoadInst *load_inst = dyn_cast<LoadInst>(current_value);
-
- if (cast_inst)
- {
- next_value = cast_inst->getOperand(0);
- }
- else if (load_inst)
- {
- if (isa<LoadInst>(load_inst->getPointerOperand()))
- {
- next_value = load_inst->getPointerOperand();
- }
- else
- {
- original_load = load_inst;
- break;
- }
- }
- else
- {
- return;
- }
- }
-
- if (!original_load)
- return;
-
- Value *loaded_value = original_load->getPointerOperand();
- GlobalVariable *loaded_global = dyn_cast<GlobalVariable>(loaded_value);
-
- if (!loaded_global)
- return;
-
- clang::NamedDecl *loaded_decl = DeclForGlobal(loaded_global);
-
- if (!loaded_decl)
- return;
-
- clang::VarDecl *loaded_var = dyn_cast<clang::VarDecl>(loaded_decl);
-
- if (!loaded_var)
- return;
-
- if (log)
- {
- lldb_private::StreamString type_desc_stream;
- type.DumpTypeDescription(&type_desc_stream);
-
- log->Printf("Type to cast variable to: \"%s\"", type_desc_stream.GetString().c_str());
- }
-
- m_const_result = m_decl_map->BuildCastVariable(m_result_name, loaded_var, type);
-}
-
bool
IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
@@ -714,7 +619,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
}
- m_result_name = m_decl_map->GetPersistentResultName();
+ m_result_name = lldb_private::ConstString("$RESULT_NAME");
if (log)
log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
@@ -806,15 +711,14 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
result_global->replaceAllUsesWith(new_result_global);
}
-
- if (!m_const_result)
- if (!m_decl_map->AddPersistentVariable(result_decl,
- m_result_name,
- m_result_type,
- true,
- m_result_is_pointer))
- return false;
+ if (!m_decl_map->AddPersistentVariable(result_decl,
+ m_result_name,
+ m_result_type,
+ true,
+ m_result_is_pointer))
+ return false;
+
result_global->eraseFromParent();
return true;
@@ -2138,10 +2042,11 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
llvm::Instruction *inst = *user_iter;
ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
- Type *operand_type = operand_constant_fp->getType();
if (operand_constant_fp)
{
+ Type *operand_type = operand_constant_fp->getType();
+
APFloat operand_apfloat = operand_constant_fp->getValueAPF();
APInt operand_apint = operand_apfloat.bitcastToAPInt();
@@ -2195,7 +2100,7 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
- Constant *new_pointer = BuildRelocation(fp_ptr_ty, offset);
+ Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset);
llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst);
@@ -2762,12 +2667,6 @@ IRForTarget::runOnModule (Module &llvm_module)
return false;
}
-
- if (m_const_result && m_execution_policy != lldb_private::eExecutionPolicyAlways)
- {
- m_interpret_success = true;
- return true;
- }
for (bbi = function->begin();
bbi != function->end();
@@ -2804,20 +2703,6 @@ IRForTarget::runOnModule (Module &llvm_module)
}
}
- if (m_decl_map && m_execution_policy != lldb_private::eExecutionPolicyAlways)
- {
- IRInterpreter::maybeRunOnFunction(m_decl_map, m_memory_map, m_error_stream,m_const_result, m_result_name, m_result_type, *function, llvm_module, m_interpreter_error);
-
- if (m_interpreter_error.Success())
- return true;
- }
-
- if (m_execution_policy == lldb_private::eExecutionPolicyNever) {
- if (m_result_name)
- m_decl_map->RemoveResultVariable(m_result_name);
- return false;
- }
-
if (log && log->GetVerbose())
{
std::string s;
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index 622156302ae..bfd8abe793a 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -89,6 +89,10 @@ public:
BasicBlock::const_iterator m_ii;
BasicBlock::const_iterator m_ie;
+ lldb::addr_t m_frame_process_address;
+ size_t m_frame_size;
+ lldb::addr_t m_stack_pointer;
+
lldb::ByteOrder m_byte_order;
size_t m_addr_byte_size;
@@ -101,6 +105,36 @@ public:
{
m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
m_addr_byte_size = (target_data.getPointerSize(0));
+
+ m_frame_size = 512 * 1024;
+
+ lldb_private::Error alloc_error;
+
+ m_frame_process_address = memory_map.Malloc(m_frame_size,
+ m_addr_byte_size,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ lldb_private::IRMemoryMap::eAllocationPolicyMirror,
+ alloc_error);
+
+ if (alloc_error.Success())
+ {
+ m_stack_pointer = m_frame_process_address + m_frame_size;
+ }
+ else
+ {
+ m_frame_process_address = LLDB_INVALID_ADDRESS;
+ m_stack_pointer = LLDB_INVALID_ADDRESS;
+ }
+ }
+
+ ~InterpreterStackFrame ()
+ {
+ if (m_frame_process_address != LLDB_INVALID_ADDRESS)
+ {
+ lldb_private::Error free_error;
+ m_memory_map.Free(m_frame_process_address, free_error);
+ m_frame_process_address = LLDB_INVALID_ADDRESS;
+ }
}
void Jump (const BasicBlock *bb)
@@ -216,59 +250,108 @@ public:
bool ResolveConstantValue (APInt &value, const Constant *constant)
{
- if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
- {
- value = constant_int->getValue();
- return true;
- }
- else if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
- {
- value = constant_fp->getValueAPF().bitcastToAPInt();
- return true;
- }
- else if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+ switch (constant->getValueID())
{
- switch (constant_expr->getOpcode())
+ default:
+ break;
+ case Value::ConstantIntVal:
+ if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
{
- default:
- return false;
- case Instruction::IntToPtr:
- case Instruction::PtrToInt:
- case Instruction::BitCast:
- return ResolveConstantValue(value, constant_expr->getOperand(0));
- case Instruction::GetElementPtr:
+ value = constant_int->getValue();
+ return true;
+ }
+ break;
+ case Value::ConstantFPVal:
+ if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
+ {
+ value = constant_fp->getValueAPF().bitcastToAPInt();
+ return true;
+ }
+ break;
+ case Value::ConstantExprVal:
+ if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+ {
+ switch (constant_expr->getOpcode())
{
- ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
- ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
-
- Constant *base = dyn_cast<Constant>(*op_cursor);
-
- if (!base)
- return false;
-
- if (!ResolveConstantValue(value, base))
+ default:
return false;
-
- op_cursor++;
-
- if (op_cursor == op_end)
- return true; // no offset to apply!
-
- SmallVector <Value *, 8> indices (op_cursor, op_end);
-
- uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices);
-
- const bool is_signed = true;
- value += APInt(value.getBitWidth(), offset, is_signed);
-
- return true;
+ case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
+ case Instruction::BitCast:
+ return ResolveConstantValue(value, constant_expr->getOperand(0));
+ case Instruction::GetElementPtr:
+ {
+ ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
+ ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
+
+ Constant *base = dyn_cast<Constant>(*op_cursor);
+
+ if (!base)
+ return false;
+
+ if (!ResolveConstantValue(value, base))
+ return false;
+
+ op_cursor++;
+
+ if (op_cursor == op_end)
+ return true; // no offset to apply!
+
+ SmallVector <Value *, 8> indices (op_cursor, op_end);
+
+ uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices);
+
+ const bool is_signed = true;
+ value += APInt(value.getBitWidth(), offset, is_signed);
+
+ return true;
+ }
}
}
+ break;
+ case Value::ConstantPointerNullVal:
+ if (isa<ConstantPointerNull>(constant))
+ {
+ value = APInt(m_target_data.getPointerSizeInBits(), 0);
+ return true;
+ }
+ break;
}
-
return false;
}
+ bool MakeArgument(const Argument *value, uint64_t address)
+ {
+ lldb::addr_t data_address = Malloc(value->getType());
+
+ if (data_address == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb_private::Error write_error;
+
+ m_memory_map.WritePointerToMemory(data_address, address, write_error);
+
+ if (!write_error.Success())
+ {
+ lldb_private::Error free_error;
+ m_memory_map.Free(data_address, free_error);
+ return false;
+ }
+
+ m_values[value] = data_address;
+
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ log->Printf("Made an allocation for argument %s", PrintValue(value).c_str());
+ log->Printf(" Data region : %llx", (unsigned long long)address);
+ log->Printf(" Ref region : %llx", (unsigned long long)data_address);
+ }
+
+ return true;
+ }
+
bool ResolveConstant (lldb::addr_t process_address, const Constant *constant)
{
APInt resolved_value;
@@ -287,31 +370,30 @@ public:
return write_error.Success();
}
- lldb::addr_t MallocPointer ()
+ lldb::addr_t Malloc (size_t size, uint8_t byte_alignment)
{
- lldb_private::Error alloc_error;
-
- lldb::addr_t ret = m_memory_map.Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment(), lldb::ePermissionsReadable | lldb::ePermissionsWritable, lldb_private::IRMemoryMap::eAllocationPolicyMirror, alloc_error);
+ lldb::addr_t ret = m_stack_pointer;
- if (alloc_error.Success())
- return ret;
- else
+ ret -= size;
+ ret -= (ret % byte_alignment);
+
+ if (ret < m_frame_process_address)
return LLDB_INVALID_ADDRESS;
+
+ m_stack_pointer = ret;
+ return ret;
+ }
+
+ lldb::addr_t MallocPointer ()
+ {
+ return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment());
}
- lldb::addr_t Malloc (llvm::Type *type, size_t override_byte_size = 0)
+ lldb::addr_t Malloc (llvm::Type *type)
{
lldb_private::Error alloc_error;
- if (!override_byte_size)
- override_byte_size = m_target_data.getTypeStoreSize(type);
-
- lldb::addr_t ret = m_memory_map.Malloc(override_byte_size, m_target_data.getPrefTypeAlignment(type), lldb::ePermissionsReadable | lldb::ePermissionsWritable, lldb_private::IRMemoryMap::eAllocationPolicyMirror, alloc_error);
-
- if (alloc_error.Success())
- return ret;
- else
- return LLDB_INVALID_ADDRESS;
+ return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type));
}
lldb::addr_t PlaceLLDBValue (const llvm::Value *value, lldb_private::Value lldb_value)
@@ -325,6 +407,7 @@ public:
lldb::addr_t ret;
size_t value_size = m_target_data.getTypeStoreSize(value->getType());
+ size_t value_align = m_target_data.getPrefTypeAlignment(value->getType());
if (reg_info && (reg_info->encoding == lldb::eEncodingVector))
value_size = reg_info->byte_size;
@@ -332,7 +415,7 @@ public:
if (!reg_info && (lldb_value.GetValueType() == lldb_private::Value::eValueTypeLoadAddress))
return lldb_value.GetScalar().ULongLong();
- ret = Malloc(value->getType(), value_size);
+ ret = Malloc(value_size, value_align);
if (ret == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
@@ -403,14 +486,28 @@ public:
lldb::addr_t ResolveValue (const Value *value, Module &module)
{
- if (!m_decl_map)
- return LLDB_INVALID_ADDRESS;
-
ValueMap::iterator i = m_values.find(value);
if (i != m_values.end())
return i->second;
+ // Fall back and allocate space [allocation type Alloca]
+
+ lldb::addr_t data_address = Malloc(value->getType());
+
+ if (const Constant *constant = dyn_cast<Constant>(value))
+ {
+ if (!ResolveConstant (data_address, constant))
+ {
+ lldb_private::Error free_error;
+ m_memory_map.Free(data_address, free_error);
+ return LLDB_INVALID_ADDRESS;
+ }
+ }
+
+ m_values[value] = data_address;
+ return data_address;
+
const GlobalValue *global_value = dyn_cast<GlobalValue>(value);
// If the variable is indirected through the argument
@@ -686,23 +783,6 @@ public:
}
}
while(0);
-
- // Fall back and allocate space [allocation type Alloca]
-
- lldb::addr_t data_address = Malloc(value->getType());
-
- if (const Constant *constant = dyn_cast<Constant>(value))
- {
- if (!ResolveConstant (data_address, constant))
- {
- lldb_private::Error free_error;
- m_memory_map.Free(data_address, free_error);
- return LLDB_INVALID_ADDRESS;
- }
- }
-
- m_values[value] = data_address;
- return data_address;
}
bool ConstructResult (lldb::ClangExpressionVariableSP &result,
@@ -1698,15 +1778,50 @@ IRInterpreter::CanInterpret (llvm::Module &module,
bool
IRInterpreter::Interpret (llvm::Module &module,
llvm::Function &function,
+ llvm::ArrayRef<lldb::addr_t> args,
lldb_private::IRMemoryMap &memory_map,
lldb_private::Error &error)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ if (log)
+ {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ module.print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str());
+ }
+
DataLayout data_layout(&module);
InterpreterStackFrame frame(data_layout, NULL, memory_map);
+ if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS)
+ {
+ error.SetErrorString("Couldn't allocate stack frame");
+ }
+
+ int arg_index = 0;
+
+ for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end();
+ ai != ae;
+ ++ai, ++arg_index)
+ {
+ if (args.size() < arg_index)
+ {
+ error.SetErrorString ("Not enough arguments passed in to function");
+ return false;
+ }
+
+ lldb::addr_t ptr = args[arg_index];
+
+ frame.MakeArgument(ai, ptr);
+ }
+
uint32_t num_insts = 0;
frame.Jump(function.begin());
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index fedbc249735..cd334cddac7 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -85,6 +85,9 @@ IRMemoryMap::ContainsHostOnlyAllocations ()
IRMemoryMap::AllocationMap::iterator
IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
{
+ if (addr == LLDB_INVALID_ADDRESS)
+ return m_allocations.end();
+
AllocationMap::iterator iter = m_allocations.lower_bound (addr);
if (iter == m_allocations.end() ||
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp
index 7f540017779..9cbc01c69c8 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -20,6 +20,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
using namespace lldb_private;
@@ -179,11 +180,8 @@ public:
}
else
{
- // This is the result variable
- /*
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("No materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
- */
return;
}
}
@@ -280,6 +278,7 @@ public:
if (!read_error.Success())
{
+ err.SetErrorToGenericError();
err.SetErrorStringWithFormat ("Couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
return;
}
@@ -468,7 +467,7 @@ public:
DataExtractor data;
valobj_sp->GetData(data);
- if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
@@ -580,7 +579,7 @@ public:
if (!free_error.Success())
{
err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("Couldn'tfree the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
+ err.SetErrorStringWithFormat("Couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
return;
}
@@ -593,9 +592,11 @@ public:
{
StreamString dump_stream;
- Error err;
+ dump_stream.Printf("0x%llx: EntityVariable\n", (unsigned long long)process_address + m_offset);
- dump_stream.Printf("0x%llx: EntityVariable (%s)\n", (unsigned long long)process_address + m_offset, m_variable_sp->GetName().AsCString());
+ Error err;
+
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
{
dump_stream.Printf("Pointer:\n");
@@ -614,18 +615,29 @@ public:
extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, process_address + m_offset);
+ 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");
+ dump_stream.Printf("Points to process memory:\n");
}
else
{
dump_stream.Printf("Temporary allocation:\n");
-
+ }
+
+ if (ptr == LLDB_INVALID_ADDRESS)
+ {
+ dump_stream.Printf(" <could not be be found>\n");
+ }
+ else
+ {
DataBufferHeap data (m_temporary_allocation_size, 0);
map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
@@ -680,21 +692,157 @@ Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
class EntityResultVariable : public Materializer::Entity
{
public:
- EntityResultVariable (const ClangASTType &type, bool keep_in_memory) :
+ EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
Entity(),
m_type(type),
- m_keep_in_memory(keep_in_memory)
+ m_is_program_reference(is_program_reference),
+ m_keep_in_memory(keep_in_memory),
+ m_temporary_allocation(LLDB_INVALID_ADDRESS),
+ m_temporary_allocation_size(0)
{
- SetSizeAndAlignmentFromType(m_type);
+ // Hard-coding to maximum size of a pointer since all results are materialized by reference
+ m_size = 8;
+ m_alignment = 8;
}
void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
{
+ if (!m_is_program_reference)
+ {
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Trying to create a temporary region for the result but one exists");
+ return;
+ }
+
+ size_t byte_size = m_type.GetTypeByteSize();
+ size_t bit_align = m_type.GetTypeBitAlign();
+ size_t byte_align = (bit_align + 7) / 8;
+
+ Error alloc_error;
+
+ m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
+ m_temporary_allocation_size = byte_size;
+
+ if (!alloc_error.Success())
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
+ return;
+ }
+
+ Error pointer_write_error;
+
+ map.WritePointerToMemory(process_address + m_offset, m_temporary_allocation, pointer_write_error);
+
+ if (!pointer_write_error.Success())
+ {
+ err.SetErrorToGenericError();
+ 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,
- lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
+ lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
{
+ err.SetErrorToGenericError();
+ err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
+ }
+
+ void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
+ lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
+ lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
+ {
+ err.Clear();
+
+ ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
+
+ if (!exe_scope)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
+ return;
+ }
+
+ lldb::addr_t address;
+ Error read_error;
+
+ map.ReadPointerFromMemory (&address, process_address + m_offset, read_error);
+
+ if (!read_error.Success())
+ {
+ err.SetErrorToGenericError();
+ 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.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: no target");
+ return;
+ }
+
+ ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
+
+ lldb::ClangExpressionVariableSP ret;
+
+ ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
+ name,
+ m_type,
+ map.GetByteOrder(),
+ map.GetAddressByteSize());
+
+ if (!ret)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
+ return;
+ }
+
+ ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
+ m_type.GetASTContext(),
+ m_type.GetOpaqueQualType(),
+ name,
+ address,
+ eAddressTypeLoad,
+ ret->GetByteSize());
+
+ 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.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
+ return;
+ }
+
+ result_variable_sp = ret;
+
+ if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
+ {
+ ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+
+ Error free_error;
+
+ map.Free(m_temporary_allocation, free_error);
+ }
+ else
+ {
+ ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ }
+
+ m_temporary_allocation = LLDB_INVALID_ADDRESS;
+ m_temporary_allocation_size = 0;
}
void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
@@ -703,24 +851,100 @@ public:
dump_stream.Printf("0x%llx: EntityResultVariable\n", (unsigned long long)process_address + m_offset);
+ Error err;
+
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
+
+ {
+ dump_stream.Printf("Pointer:\n");
+
+ DataBufferHeap data (m_size, 0);
+
+ map.ReadMemory(data.GetBytes(), process_address + m_offset, m_size, err);
+
+ if (!err.Success())
+ {
+ dump_stream.Printf(" <could not be read>\n");
+ }
+ else
+ {
+ DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, process_address + m_offset);
+
+ 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");
+ }
+ else
+ {
+ dump_stream.Printf("Temporary allocation:\n");
+ }
+
+ if (ptr == LLDB_INVALID_ADDRESS)
+ {
+ dump_stream.Printf(" <could not be be found>\n");
+ }
+ 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");
+ }
+ else
+ {
+ DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, process_address + m_offset);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
log->PutCString(dump_stream.GetData());
}
void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
{
+ 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;
}
private:
- ClangASTType m_type;
+ TypeFromUser m_type;
+ bool m_is_program_reference;
bool m_keep_in_memory;
+
+ lldb::addr_t m_temporary_allocation;
+ size_t m_temporary_allocation_size;
};
uint32_t
-Materializer::AddResultVariable (const ClangASTType &type, bool keep_in_memory, Error &err)
+Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityResultVariable (type, keep_in_memory));
+ iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
+ m_result_entity = iter->get();
return ret;
}
@@ -1008,6 +1232,7 @@ Materializer::AddRegister (const RegisterInfo &register_info, Error &err)
Materializer::Materializer () :
m_dematerializer_wp(),
+ m_result_entity(NULL),
m_current_offset(0),
m_struct_alignment(8)
{
@@ -1022,7 +1247,7 @@ Materializer::~Materializer ()
}
Materializer::DematerializerSP
-Materializer::Materialize (lldb::StackFrameSP &frame_sp, lldb::ClangExpressionVariableSP &result_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
+Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
{
ExecutionContextScope *exe_scope = frame_sp.get();
@@ -1066,7 +1291,7 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, lldb::ClangExpressionVa
}
void
-Materializer::Dematerializer::Dematerialize (Error &error, lldb::addr_t frame_top, lldb::addr_t frame_bottom)
+Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_top, lldb::addr_t frame_bottom)
{
lldb::StackFrameSP frame_sp = m_frame_wp.lock();
@@ -1094,8 +1319,15 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::addr_t frame_to
for (EntityUP &entity_up : m_materializer->m_entities)
{
- entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
-
+ if (entity_up.get() == m_materializer->m_result_entity)
+ {
+ static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
+ }
+ else
+ {
+ entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
+ }
+
if (!error.Success())
break;
}
OpenPOWER on IntegriCloud