forked from OSchip/llvm-project
Fixed a bug in which expression-local variables were
treated as being permanently resident in target memory. In fact, since the expression's stack frame is deleted and potentially re-used after the expression completes, the variables need to be treated as being freeze-dried. llvm-svn: 131104
This commit is contained in:
parent
7adbed6b4d
commit
e359d9b771
|
@ -425,6 +425,12 @@ public:
|
|||
/// A ClangExpressionVariable containing the result of the
|
||||
/// expression, for potential re-use.
|
||||
///
|
||||
/// @param[in] stack_frame_top, stack_frame_bottom
|
||||
/// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame
|
||||
/// in which the expression ran. A result whose address falls
|
||||
/// inside this stack frame is dematerialized as a value
|
||||
/// requiring rematerialization.
|
||||
///
|
||||
/// @param[in] error
|
||||
/// An Error to populate with any messages related to
|
||||
/// dematerializing the struct.
|
||||
|
@ -435,6 +441,8 @@ public:
|
|||
bool
|
||||
Dematerialize (ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &result_sp,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
Error &error);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -817,6 +825,12 @@ private:
|
|||
/// @param[in] exe_ctx
|
||||
/// The execution context to use.
|
||||
///
|
||||
/// @param[in] stack_frame_top, stack_frame_bottom
|
||||
/// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame
|
||||
/// in which the expression ran. A result whose address falls
|
||||
/// inside this stack frame is dematerialized as a value
|
||||
/// requiring rematerialization.
|
||||
///
|
||||
/// @param[out] result
|
||||
/// If the struct is being dematerialized, a pointer into which the
|
||||
/// location of the result persistent variable is placed. If not,
|
||||
|
@ -832,6 +846,8 @@ private:
|
|||
bool
|
||||
DoMaterialize (bool dematerialize,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
lldb::ClangExpressionVariableSP *result_sp_ptr,
|
||||
Error &err);
|
||||
|
||||
|
@ -858,6 +874,12 @@ private:
|
|||
/// @param[in] addr
|
||||
/// The address at which to materialize the variable.
|
||||
///
|
||||
/// @param[in] stack_frame_top, stack_frame_bottom
|
||||
/// If not LLDB_INVALID_ADDRESS, the bounds for the stack frame
|
||||
/// in which the expression ran. A result whose address falls
|
||||
/// inside this stack frame is dematerialized as a value
|
||||
/// requiring rematerialization.
|
||||
///
|
||||
/// @param[in] err
|
||||
/// An Error to populate with any messages related to
|
||||
/// (de)materializing the persistent variable.
|
||||
|
@ -870,6 +892,8 @@ private:
|
|||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &var_sp,
|
||||
lldb::addr_t addr,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
Error &err);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -134,10 +134,34 @@ public:
|
|||
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Apply the side effects of the function to program state.
|
||||
///
|
||||
/// @param[in] error_stream
|
||||
/// A stream to print errors to.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to use when looking up entities that
|
||||
/// are needed for parsing (locations of variables, etc.)
|
||||
///
|
||||
/// @param[in] result
|
||||
/// A pointer to direct at the persistent variable in which the
|
||||
/// expression's result is stored.
|
||||
///
|
||||
/// @param[in] function_stack_pointer
|
||||
/// A pointer to the base of the function's stack frame. This
|
||||
/// is used to determine whether the expession result resides in
|
||||
/// memory that will still be valid, or whether it needs to be
|
||||
/// treated as homeless for the purpose of future expressions.
|
||||
///
|
||||
/// @return
|
||||
/// A Process::Execution results value.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
FinalizeJITExecution (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &result);
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
lldb::addr_t function_stack_pointer = LLDB_INVALID_ADDRESS);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the string that the parser should parse. Must be a full
|
||||
|
|
|
@ -70,6 +70,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
// Return the stack pointer that the function received
|
||||
// on entry. Any stack address below this should be
|
||||
// considered invalid after the function has been
|
||||
// cleaned up.
|
||||
lldb::addr_t
|
||||
GetFunctionStackPointer()
|
||||
{
|
||||
return m_function_sp;
|
||||
}
|
||||
|
||||
// Classes that derive from ClangFunction, and implement
|
||||
// their own WillPop methods should call this so that the
|
||||
// thread state gets restored if the plan gets discarded.
|
||||
|
@ -97,6 +107,7 @@ private:
|
|||
Address m_function_addr;
|
||||
Address m_start_addr;
|
||||
lldb::addr_t m_arg_addr;
|
||||
lldb::addr_t m_function_sp;
|
||||
ValueList *m_args;
|
||||
Process &m_process;
|
||||
Thread &m_thread;
|
||||
|
|
|
@ -588,7 +588,12 @@ ClangExpressionDeclMap::Materialize
|
|||
|
||||
m_material_vars->m_process = exe_ctx.process;
|
||||
|
||||
bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err);
|
||||
bool result = DoMaterialize(false /* dematerialize */,
|
||||
exe_ctx,
|
||||
LLDB_INVALID_ADDRESS /* top of stack frame */,
|
||||
LLDB_INVALID_ADDRESS /* bottom of stack frame */,
|
||||
NULL, /* result SP */
|
||||
err);
|
||||
|
||||
if (result)
|
||||
struct_address = m_material_vars->m_materialized_location;
|
||||
|
@ -717,10 +722,12 @@ ClangExpressionDeclMap::Dematerialize
|
|||
(
|
||||
ExecutionContext &exe_ctx,
|
||||
ClangExpressionVariableSP &result_sp,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
Error &err
|
||||
)
|
||||
{
|
||||
return DoMaterialize(true, exe_ctx, &result_sp, err);
|
||||
return DoMaterialize(true, exe_ctx, stack_frame_top, stack_frame_bottom, &result_sp, err);
|
||||
|
||||
DidDematerialize();
|
||||
}
|
||||
|
@ -825,6 +832,8 @@ ClangExpressionDeclMap::DoMaterialize
|
|||
(
|
||||
bool dematerialize,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
lldb::ClangExpressionVariableSP *result_sp_ptr,
|
||||
Error &err
|
||||
)
|
||||
|
@ -948,7 +957,9 @@ ClangExpressionDeclMap::DoMaterialize
|
|||
if (!DoMaterializeOnePersistentVariable (dematerialize,
|
||||
exe_ctx,
|
||||
member_sp,
|
||||
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
|
||||
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
|
||||
stack_frame_top,
|
||||
stack_frame_bottom,
|
||||
err))
|
||||
return false;
|
||||
}
|
||||
|
@ -1027,6 +1038,8 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
ExecutionContext &exe_ctx,
|
||||
ClangExpressionVariableSP &var_sp,
|
||||
lldb::addr_t addr,
|
||||
lldb::addr_t stack_frame_top,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
Error &err
|
||||
)
|
||||
{
|
||||
|
@ -1103,10 +1116,7 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
|
||||
|
||||
// Read the contents of the spare memory area
|
||||
|
||||
if (log)
|
||||
log->Printf("Read");
|
||||
|
||||
|
||||
var_sp->ValueUpdated ();
|
||||
if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
|
||||
{
|
||||
|
@ -1114,6 +1124,20 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
return false;
|
||||
}
|
||||
|
||||
if (stack_frame_top != LLDB_INVALID_ADDRESS &&
|
||||
stack_frame_bottom != LLDB_INVALID_ADDRESS &&
|
||||
mem >= stack_frame_bottom &&
|
||||
mem <= stack_frame_top)
|
||||
{
|
||||
// If the variable is resident in the stack frame created by the expression,
|
||||
// then it cannot be relied upon to stay around. We treat it as needing
|
||||
// reallocation.
|
||||
|
||||
var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
|
||||
var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
|
||||
var_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference;
|
||||
}
|
||||
|
||||
var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
|
||||
}
|
||||
|
||||
|
|
|
@ -421,7 +421,8 @@ ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
|
|||
bool
|
||||
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &result)
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
lldb::addr_t function_stack_pointer)
|
||||
{
|
||||
Error expr_error;
|
||||
|
||||
|
@ -444,8 +445,11 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
|||
log->Printf(" Structure contents:\n%s", args.GetData());
|
||||
}
|
||||
}
|
||||
|
||||
lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
|
||||
|
||||
|
||||
if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
|
||||
if (!m_expr_decl_map->Dematerialize(exe_ctx, result, function_stack_pointer, function_stack_bottom, expr_error))
|
||||
{
|
||||
error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
|
||||
return false;
|
||||
|
@ -497,6 +501,8 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
|
||||
if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
|
||||
return eExecutionSetupError;
|
||||
|
||||
lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
|
||||
|
||||
call_plan_sp->SetPrivate(true);
|
||||
|
||||
|
@ -506,12 +512,12 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
|
||||
|
||||
ExecutionResults execution_result = exe_ctx.process->RunThreadPlan (exe_ctx,
|
||||
call_plan_sp,
|
||||
stop_others,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
error_stream);
|
||||
call_plan_sp,
|
||||
stop_others,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
error_stream);
|
||||
|
||||
if (log)
|
||||
log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
|
||||
|
@ -531,7 +537,7 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
return execution_result;
|
||||
}
|
||||
|
||||
if (FinalizeJITExecution (error_stream, exe_ctx, result))
|
||||
if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
|
||||
return eExecutionCompleted;
|
||||
else
|
||||
return eExecutionSetupError;
|
||||
|
|
|
@ -49,7 +49,8 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
|
|||
m_args (NULL),
|
||||
m_process (thread.GetProcess()),
|
||||
m_thread (thread),
|
||||
m_takedown_done (false)
|
||||
m_takedown_done (false),
|
||||
m_function_sp(NULL)
|
||||
{
|
||||
SetOkayToDiscard (discard_on_error);
|
||||
|
||||
|
@ -64,7 +65,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
|
|||
|
||||
SetBreakpoints();
|
||||
|
||||
lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
|
||||
m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
|
||||
|
||||
ModuleSP executableModuleSP (target.GetExecutableModule());
|
||||
|
||||
|
@ -110,7 +111,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
|
|||
lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
|
||||
|
||||
if (!abi->PrepareTrivialCall(thread,
|
||||
spBelowRedZone,
|
||||
m_function_sp,
|
||||
FunctionLoadAddr,
|
||||
StartLoadAddr,
|
||||
m_arg_addr,
|
||||
|
|
Loading…
Reference in New Issue