diff options
Diffstat (limited to 'lldb/source/Target/ThreadPlanTestCondition.cpp')
-rw-r--r-- | lldb/source/Target/ThreadPlanTestCondition.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/lldb/source/Target/ThreadPlanTestCondition.cpp b/lldb/source/Target/ThreadPlanTestCondition.cpp new file mode 100644 index 00000000000..30fe739136f --- /dev/null +++ b/lldb/source/Target/ThreadPlanTestCondition.cpp @@ -0,0 +1,182 @@ +//===-- ThreadPlanTestCondition.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/ThreadPlanTestCondition.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private-log.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Thread.h" + +using namespace lldb; +using namespace lldb_private; + + +//---------------------------------------------------------------------- +// ThreadPlanTestCondition: Step through a stack range, either stepping over or into +// based on the value of \a type. +//---------------------------------------------------------------------- + +ThreadPlanTestCondition::ThreadPlanTestCondition ( + Thread& thread, + ExecutionContext &exe_ctx, + ClangUserExpression *expression, + lldb::BreakpointLocationSP break_loc_sp, + bool stop_others) : + ThreadPlan (ThreadPlan::eKindTestCondition, "test condition", thread, eVoteNoOpinion, eVoteNoOpinion), + m_exe_ctx (exe_ctx), + m_expression (expression), + m_break_loc_sp (break_loc_sp), + m_did_stop (false), + m_stop_others (stop_others) +{ +} + +ThreadPlanTestCondition::~ThreadPlanTestCondition () +{ +} + +bool +ThreadPlanTestCondition::ValidatePlan (Stream *error) +{ + return true; +} + +void +ThreadPlanTestCondition::GetDescription (Stream *s, lldb::DescriptionLevel level) +{ + +} + +bool +ThreadPlanTestCondition::ShouldStop (Event *event_ptr) +{ + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); + if (m_thread.IsThreadPlanDone(m_expression_plan_sp.get())) + { + ClangExpressionVariable *expr_result = NULL; + StreamString error_stream; + m_expression->FinalizeJITExecution(error_stream, m_exe_ctx, expr_result); + + ValueObjectSP result_sp (expr_result->GetExpressionResult(&m_exe_ctx)); + if (result_sp) + { + // FIXME: This is not the right answer, we should have a "GetValueAsBoolean..." + Scalar scalar_value = result_sp->GetValue().ResolveValue (&m_exe_ctx, result_sp->GetClangAST()); + if (scalar_value.IsValid()) + { + if (scalar_value.ULongLong(1) == 0) + m_did_stop = false; + else + m_did_stop = true; + } + if (log) + log->Printf("Condition successfully evaluated, result is %s.\n", m_did_stop ? "true" : "false"); + } + else + { + if (log) + log->Printf("Failed to get a result from the expression, error: \"%s\"\n", error_stream.GetData()); + m_did_stop = true; + } + } + else if (m_exe_ctx.thread->WasThreadPlanDiscarded (m_expression_plan_sp.get())) + { + if (log) + log->Printf("ExecuteExpression thread plan was discarded.\n"); + m_did_stop = true; + } + + // Now we have to change the event to a breakpoint event and mark it up appropriately: + Process::ProcessEventData *new_data = new Process::ProcessEventData (m_thread.GetProcess().GetSP(), eStateStopped); + event_ptr->SetData(new_data); + event_ptr->SetType(Process::eBroadcastBitStateChanged); + m_thread.SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID (m_thread, + m_break_loc_sp->GetBreakpointSite()->GetID(), + m_did_stop)); + if (m_did_stop) + { + Process::ProcessEventData::SetRestartedInEvent (event_ptr, false); + } + else + { + Process::ProcessEventData::SetRestartedInEvent (event_ptr, true); + } + + SetPlanComplete(); + return m_did_stop; +} + +bool +ThreadPlanTestCondition::PlanExplainsStop () +{ + // We explain all stops, and we just can the execution and return true if we stop for any + // reason other than that our expression execution is done. + return true; +} + +Vote +ThreadPlanTestCondition::ShouldReportStop (Event *event_ptr) +{ + if (m_did_stop) + { + return eVoteYes; + } + else + { + return eVoteNo; + } +} + +void +ThreadPlanTestCondition::DidPush() +{ + StreamString error_stream; + m_expression_plan_sp.reset(m_expression->GetThreadPlanToExecuteJITExpression (error_stream, m_exe_ctx)); + m_thread.QueueThreadPlan (m_expression_plan_sp, false); +} + +bool +ThreadPlanTestCondition::StopOthers () +{ + return m_stop_others; +} + +bool +ThreadPlanTestCondition::WillStop () +{ + return true; +} + +StateType +ThreadPlanTestCondition::RunState () +{ + return eStateRunning; +} + +bool +ThreadPlanTestCondition::MischiefManaged () +{ + // If we get a stop we're done, we don't puase in the middle of + // condition execution. + return true; +} |