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:
Sean Callanan 2011-05-09 22:04:36 +00:00
parent 7adbed6b4d
commit e359d9b771
6 changed files with 110 additions and 20 deletions

View File

@ -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);
//------------------------------------------------------------------

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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,