Fixed a bug where we didn't restore thread and

frame state after running a function.  This
caused nondeterministic crashes in the expression
evaluation code.

llvm-svn: 109454
This commit is contained in:
Sean Callanan 2010-07-26 22:14:36 +00:00
parent e93c39045a
commit 138e74e347
1 changed files with 56 additions and 48 deletions

View File

@ -247,9 +247,9 @@ ClangFunction::CompileFunction (Stream &errors)
}
bool
ClangFunction::WriteFunctionWrapper (ExecutionContext &exc_context, Stream &errors)
ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
Process *process = exc_context.process;
Process *process = exe_ctx.process;
if (process == NULL)
return false;
@ -257,10 +257,10 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exc_context, Stream &erro
if (!m_JITted)
{
// Next we should JIT it and insert the result into the target program.
if (!JITFunction (exc_context, m_wrapper_function_name.c_str()))
if (!JITFunction (exe_ctx, m_wrapper_function_name.c_str()))
return false;
if (!WriteJITCode (exc_context))
if (!WriteJITCode (exe_ctx))
return false;
m_JITted = true;
@ -275,15 +275,15 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exc_context, Stream &erro
}
bool
ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors)
ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
return WriteFunctionArguments(exc_context, args_addr_ref, m_function_addr, m_arg_values, errors);
return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors);
}
// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
bool
ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors)
ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors)
{
// Otherwise, allocate space for the argument passing struct, and write it.
// We use the information in the expression parser AST to
@ -295,7 +295,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr
using namespace clang;
ExecutionResults return_value = eExecutionSetupError;
Process *process = exc_context.process;
Process *process = exe_ctx.process;
if (process == NULL)
return return_value;
@ -321,7 +321,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr
// FIXME: This is fake, and just assumes that it matches that architecture.
// Make a data extractor and put the address into the right byte order & size.
uint64_t fun_addr = function_address.GetLoadAddress(exc_context.process);
uint64_t fun_addr = function_address.GetLoadAddress(exe_ctx.process);
int first_offset = m_struct_layout->getFieldOffset(0)/8;
process->WriteMemory(args_addr_ref + first_offset, &fun_addr, 8, error);
@ -352,7 +352,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr
ClangASTContext::IsPointerType(arg_value->GetValueOpaqueClangQualType()))
continue;
const Scalar &arg_scalar = arg_value->ResolveValue(&exc_context, m_clang_ast_context->getASTContext());
const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext());
int byte_size = arg_scalar.GetByteSize();
std::vector<uint8_t> buffer;
@ -367,15 +367,15 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr
}
bool
ClangFunction::InsertFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors)
ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
using namespace clang;
if (CompileFunction(errors) != 0)
return false;
if (!WriteFunctionWrapper(exc_context, errors))
if (!WriteFunctionWrapper(exe_ctx, errors))
return false;
if (!WriteFunctionArguments(exc_context, args_addr_ref, errors))
if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors))
return false;
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
@ -386,11 +386,11 @@ ClangFunction::InsertFunction (ExecutionContext &exc_context, lldb::addr_t &args
}
ThreadPlan *
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t func_addr, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error)
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t func_addr, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error)
{
// FIXME: Use the errors Stream for better error reporting.
Process *process = exc_context.process;
Process *process = exe_ctx.process;
if (process == NULL)
{
@ -401,7 +401,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb:
// Okay, now run the function:
Address wrapper_address (NULL, func_addr);
ThreadPlan *new_plan = new ThreadPlanCallFunction (*exc_context.thread,
ThreadPlan *new_plan = new ThreadPlanCallFunction (*exe_ctx.thread,
wrapper_address,
args_addr,
stop_others, discard_on_error);
@ -409,14 +409,14 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb:
}
bool
ClangFunction::FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr, Value &ret_value)
ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
// Read the return value - it is the last field in the struct:
// FIXME: How does clang tell us there's no return value? We need to handle that case.
std::vector<uint8_t> data_buffer;
data_buffer.resize(m_return_size);
Process *process = exc_context.process;
Process *process = exe_ctx.process;
Error error;
size_t bytes_read = process->ReadMemory(args_addr + m_return_offset/8, &data_buffer.front(), m_return_size, error);
@ -441,43 +441,43 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t
}
void
ClangFunction::DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr)
ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
{
std::list<lldb::addr_t>::iterator pos;
pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
if (pos != m_wrapper_args_addrs.end())
m_wrapper_args_addrs.erase(pos);
exc_context.process->DeallocateMemory(args_addr);
exe_ctx.process->DeallocateMemory(args_addr);
}
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction(ExecutionContext &exc_context, Stream &errors, Value &results)
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, Value &results)
{
return ExecuteFunction (exc_context, errors, 1000, true, results);
return ExecuteFunction (exe_ctx, errors, 1000, true, results);
}
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction(ExecutionContext &exc_context, Stream &errors, bool stop_others, Value &results)
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
{
return ExecuteFunction (exc_context, NULL, errors, stop_others, NULL, false, results);
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, NULL, false, results);
}
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exc_context,
ExecutionContext &exe_ctx,
Stream &errors,
uint32_t single_thread_timeout_usec,
bool try_all_threads,
Value &results)
{
return ExecuteFunction (exc_context, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results);
return ExecuteFunction (exe_ctx, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results);
}
// This is the static function
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction (
ExecutionContext &exc_context,
ExecutionContext &exe_ctx,
lldb::addr_t function_address,
lldb::addr_t &void_arg,
bool stop_others,
@ -485,9 +485,12 @@ ClangFunction::ExecuteFunction (
uint32_t single_thread_timeout_usec,
Stream &errors)
{
// Save this value for restoration of the execution context after we run
uint32_t tid = exe_ctx.thread->GetID();
ClangFunction::ExecutionResults return_value = eExecutionSetupError;
lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exc_context, function_address, void_arg, errors, stop_others, false));
lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exe_ctx, function_address, void_arg, errors, stop_others, false));
ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get());
@ -495,7 +498,7 @@ ClangFunction::ExecuteFunction (
return eExecutionSetupError;
call_plan_sp->SetPrivate(true);
exc_context.thread->QueueThreadPlan(call_plan_sp, true);
exe_ctx.thread->QueueThreadPlan(call_plan_sp, true);
// We need to call the function synchronously, so spin waiting for it to return.
// If we get interrupted while executing, we're going to lose our context, and
@ -511,7 +514,7 @@ ClangFunction::ExecuteFunction (
timeout_ptr = &real_timeout;
}
exc_context.process->Resume ();
exe_ctx.process->Resume ();
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
@ -521,7 +524,7 @@ ClangFunction::ExecuteFunction (
// Now wait for the process to stop again:
// FIXME: Probably want a time out.
lldb::StateType stop_state = exc_context.process->WaitForStateChangedEvents (timeout_ptr, event_sp);
lldb::StateType stop_state = exe_ctx.process->WaitForStateChangedEvents (timeout_ptr, event_sp);
if (stop_state == lldb::eStateInvalid && timeout_ptr != NULL)
{
@ -531,11 +534,11 @@ ClangFunction::ExecuteFunction (
if (log)
log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.", single_thread_timeout_usec);
if (exc_context.process->Halt().Success())
if (exe_ctx.process->Halt().Success())
{
timeout_ptr = NULL;
stop_state = exc_context.process->WaitForStateChangedEvents (timeout_ptr, event_sp);
stop_state = exe_ctx.process->WaitForStateChangedEvents (timeout_ptr, event_sp);
if (stop_state == lldb::eStateInvalid)
{
errors.Printf ("Got an invalid stop state after halt.");
@ -552,14 +555,14 @@ ClangFunction::ExecuteFunction (
{
// Between the time that we got the timeout and the time we halted, but target
// might have actually completed the plan. If so, we're done.
if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get()))
if (exe_ctx.thread->IsThreadPlanDone (call_plan_sp.get()))
{
return_value = eExecutionCompleted;
break;
}
call_plan_ptr->SetStopOthers (false);
exc_context.process->Resume();
exe_ctx.process->Resume();
continue;
}
else
@ -569,12 +572,12 @@ ClangFunction::ExecuteFunction (
if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
continue;
if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get()))
if (exe_ctx.thread->IsThreadPlanDone (call_plan_sp.get()))
{
return_value = eExecutionCompleted;
break;
}
else if (exc_context.thread->WasThreadPlanDiscarded (call_plan_sp.get()))
else if (exe_ctx.thread->WasThreadPlanDiscarded (call_plan_sp.get()))
{
return_value = eExecutionDiscarded;
break;
@ -652,12 +655,17 @@ ClangFunction::ExecuteFunction (
}
}
// Thread we ran the function in may have gone away because we ran the target
// Check that it's still there.
exe_ctx.thread = exe_ctx.process->GetThreadList().FindThreadByID(tid, true).get();
exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex(0).get();
return return_value;
}
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exc_context,
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
Stream &errors,
bool stop_others,
@ -680,11 +688,11 @@ ClangFunction::ExecuteFunction(
if (args_addr == LLDB_INVALID_ADDRESS)
{
if (!InsertFunction(exc_context, args_addr, errors))
if (!InsertFunction(exe_ctx, args_addr, errors))
return eExecutionSetupError;
}
return_value = ClangFunction::ExecuteFunction(exc_context, m_wrapper_function_addr, args_addr, stop_others, try_all_threads, single_thread_timeout_usec, errors);
return_value = ClangFunction::ExecuteFunction(exe_ctx, m_wrapper_function_addr, args_addr, stop_others, try_all_threads, single_thread_timeout_usec, errors);
if (args_addr_ptr != NULL)
*args_addr_ptr = args_addr;
@ -692,22 +700,22 @@ ClangFunction::ExecuteFunction(
if (return_value != eExecutionCompleted)
return return_value;
FetchFunctionResults(exc_context, args_addr, results);
FetchFunctionResults(exe_ctx, args_addr, results);
if (args_addr_ptr == NULL)
DeallocateFunctionResults(exc_context, args_addr);
DeallocateFunctionResults(exe_ctx, args_addr);
return eExecutionCompleted;
}
ClangFunction::ExecutionResults
ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exc_context, Stream &errors, Value &results)
ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exe_ctx, Stream &errors, Value &results)
{
// FIXME: Use the errors Stream for better error reporting.
using namespace clang;
ExecutionResults return_value = eExecutionSetupError;
Process *process = exc_context.process;
Process *process = exe_ctx.process;
if (process == NULL)
{
@ -719,9 +727,9 @@ ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exc_context, Stream &err
//unsigned int arg_index;
//for (arg_index = 0; arg_index < num_args; ++arg_index)
// m_arg_values.GetValueAtIndex(arg_index)->ResolveValue(&exc_context, GetASTContext());
// m_arg_values.GetValueAtIndex(arg_index)->ResolveValue(&exe_ctx, GetASTContext());
ThreadPlan *call_plan = exc_context.thread->QueueThreadPlanForCallFunction (false,
ThreadPlan *call_plan = exe_ctx.thread->QueueThreadPlanForCallFunction (false,
m_function_addr,
m_arg_values,
true);
@ -746,12 +754,12 @@ ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exc_context, Stream &err
if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
continue;
if (exc_context.thread->IsThreadPlanDone (call_plan))
if (exe_ctx.thread->IsThreadPlanDone (call_plan))
{
return_value = eExecutionCompleted;
break;
}
else if (exc_context.thread->WasThreadPlanDiscarded (call_plan))
else if (exe_ctx.thread->WasThreadPlanDiscarded (call_plan))
{
return_value = eExecutionDiscarded;
break;