[Lldb-commits] [lldb] r109454 - /lldb/trunk/source/Expression/ClangFunction.cpp
Sean Callanan
scallanan at apple.com
Mon Jul 26 15:14:36 PDT 2010
Author: spyffe
Date: Mon Jul 26 17:14:36 2010
New Revision: 109454
URL: http://llvm.org/viewvc/llvm-project?rev=109454&view=rev
Log:
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.
Modified:
lldb/trunk/source/Expression/ClangFunction.cpp
Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=109454&r1=109453&r2=109454&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Mon Jul 26 17:14:36 2010
@@ -247,9 +247,9 @@
}
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 @@
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 @@
}
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 @@
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 @@
// 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 @@
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 @@
}
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 @@
}
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 @@
// 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 @@
}
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 @@
}
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 @@
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 @@
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 @@
timeout_ptr = &real_timeout;
}
- exc_context.process->Resume ();
+ exe_ctx.process->Resume ();
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
@@ -521,7 +524,7 @@
// 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 @@
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 @@
{
// 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 @@
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 @@
}
}
+ // 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 @@
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 @@
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 @@
//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 @@
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;
More information about the lldb-commits
mailing list