blob: 589d97b74ad02a69da5a2a92a6a1dcebeea6dc72 [file] [log] [blame]
Jim Inghamd1686902010-10-14 23:45:03 +00001//===-- ThreadPlanTestCondition.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Target/ThreadPlanTestCondition.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
17#include "lldb/lldb-private-log.h"
Jim Inghama8a68712011-06-01 23:52:47 +000018#include "lldb/Breakpoint/Breakpoint.h"
Jim Inghamd1686902010-10-14 23:45:03 +000019#include "lldb/Breakpoint/BreakpointLocation.h"
20#include "lldb/Core/Log.h"
21#include "lldb/Core/Stream.h"
22#include "lldb/Core/Value.h"
23#include "lldb/Core/ValueObject.h"
24#include "lldb/Symbol/Function.h"
25#include "lldb/Symbol/Symbol.h"
26#include "lldb/Target/Process.h"
27#include "lldb/Target/RegisterContext.h"
28#include "lldb/Target/StopInfo.h"
29#include "lldb/Target/Thread.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34
35//----------------------------------------------------------------------
36// ThreadPlanTestCondition: Step through a stack range, either stepping over or into
37// based on the value of \a type.
38//----------------------------------------------------------------------
39
Greg Clayton987c7eb2011-09-17 08:33:22 +000040ThreadPlanTestCondition::ThreadPlanTestCondition (Thread& thread,
41 ExecutionContext &exe_ctx,
42 ClangUserExpression *expression,
43 const BreakpointLocationSP &break_loc_sp,
44 bool stop_others) :
Jim Inghamd1686902010-10-14 23:45:03 +000045 ThreadPlan (ThreadPlan::eKindTestCondition, "test condition", thread, eVoteNoOpinion, eVoteNoOpinion),
Jim Inghamd1686902010-10-14 23:45:03 +000046 m_expression (expression),
Stephen Wilsondbeb3e12011-04-11 19:41:40 +000047 m_exe_ctx (exe_ctx),
Jim Inghamd1686902010-10-14 23:45:03 +000048 m_break_loc_sp (break_loc_sp),
49 m_did_stop (false),
50 m_stop_others (stop_others)
51{
52}
53
54ThreadPlanTestCondition::~ThreadPlanTestCondition ()
55{
56}
57
58bool
59ThreadPlanTestCondition::ValidatePlan (Stream *error)
60{
61 return true;
62}
63
64void
65ThreadPlanTestCondition::GetDescription (Stream *s, lldb::DescriptionLevel level)
66{
Jim Ingham360f53f2010-11-30 02:22:11 +000067 if (m_expression)
68 s->Printf("Thread plan to test condition: \"%s\".", m_expression->GetUserText());
69 else
70 s->Printf("Thread plan to test unspecified condition.");
Jim Inghamd1686902010-10-14 23:45:03 +000071}
72
73bool
74ThreadPlanTestCondition::ShouldStop (Event *event_ptr)
75{
Greg Claytone005f2c2010-11-06 01:53:30 +000076 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamd1686902010-10-14 23:45:03 +000077 if (m_thread.IsThreadPlanDone(m_expression_plan_sp.get()))
78 {
Greg Clayton427f2902010-12-14 02:59:59 +000079 lldb::ClangExpressionVariableSP expr_result;
Jim Inghamd1686902010-10-14 23:45:03 +000080 StreamString error_stream;
81 m_expression->FinalizeJITExecution(error_stream, m_exe_ctx, expr_result);
82
Greg Clayton427f2902010-12-14 02:59:59 +000083 ValueObjectSP result_sp (expr_result->GetValueObject());
Jim Inghamd1686902010-10-14 23:45:03 +000084 if (result_sp)
85 {
86 // FIXME: This is not the right answer, we should have a "GetValueAsBoolean..."
Jim Inghame41494a2011-04-16 00:01:13 +000087 Scalar scalar_value;
88 if (result_sp->ResolveValue (scalar_value))
Jim Inghamd1686902010-10-14 23:45:03 +000089 {
90 if (scalar_value.ULongLong(1) == 0)
91 m_did_stop = false;
92 else
93 m_did_stop = true;
94 }
95 if (log)
96 log->Printf("Condition successfully evaluated, result is %s.\n", m_did_stop ? "true" : "false");
97 }
98 else
99 {
100 if (log)
101 log->Printf("Failed to get a result from the expression, error: \"%s\"\n", error_stream.GetData());
102 m_did_stop = true;
103 }
104 }
Greg Clayton567e7f32011-09-22 04:58:26 +0000105 else if (m_exe_ctx.GetThreadRef().WasThreadPlanDiscarded (m_expression_plan_sp.get()))
Jim Inghamd1686902010-10-14 23:45:03 +0000106 {
107 if (log)
108 log->Printf("ExecuteExpression thread plan was discarded.\n");
109 m_did_stop = true;
110 }
111
Jim Inghama8a68712011-06-01 23:52:47 +0000112 // One tricky bit, somebody might have disabled/deleted the breakpoint while we were running this condition, if so we
113 // should just continue. If the breakpoint gets disabled, then its "site" will be null'ed out, so we can't report
114 // this as a breakpoint event any more, since we can't reconstruct it's site. So just pass the event on.
115 if (!m_break_loc_sp->IsEnabled())
Jim Inghamd1686902010-10-14 23:45:03 +0000116 {
Jim Inghama8a68712011-06-01 23:52:47 +0000117 m_did_stop = false;
Jim Inghamd1686902010-10-14 23:45:03 +0000118 }
119 else
120 {
Jim Inghama8a68712011-06-01 23:52:47 +0000121 // Now we have to change the event to a breakpoint event and mark it up appropriately:
Greg Claytonf4124de2012-02-21 00:09:25 +0000122 Process::ProcessEventData *new_data = new Process::ProcessEventData (m_thread.GetProcess(), eStateStopped);
Jim Inghama8a68712011-06-01 23:52:47 +0000123 event_ptr->SetData(new_data);
124 event_ptr->SetType(Process::eBroadcastBitStateChanged);
125 SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID (m_thread,
126 m_break_loc_sp->GetBreakpointSite()->GetID(),
127 m_did_stop));
128 if (m_did_stop)
129 {
130 Process::ProcessEventData::SetRestartedInEvent (event_ptr, false);
131 }
132 else
133 {
134 Process::ProcessEventData::SetRestartedInEvent (event_ptr, true);
135 }
Jim Inghamd1686902010-10-14 23:45:03 +0000136 }
Jim Inghamd1686902010-10-14 23:45:03 +0000137 SetPlanComplete();
138 return m_did_stop;
139}
140
141bool
142ThreadPlanTestCondition::PlanExplainsStop ()
143{
144 // We explain all stops, and we just can the execution and return true if we stop for any
145 // reason other than that our expression execution is done.
146 return true;
147}
148
149Vote
150ThreadPlanTestCondition::ShouldReportStop (Event *event_ptr)
151{
152 if (m_did_stop)
153 {
154 return eVoteYes;
155 }
156 else
157 {
158 return eVoteNo;
159 }
160}
161
162void
163ThreadPlanTestCondition::DidPush()
164{
165 StreamString error_stream;
166 m_expression_plan_sp.reset(m_expression->GetThreadPlanToExecuteJITExpression (error_stream, m_exe_ctx));
167 m_thread.QueueThreadPlan (m_expression_plan_sp, false);
168}
169
170bool
171ThreadPlanTestCondition::StopOthers ()
172{
173 return m_stop_others;
174}
175
176bool
177ThreadPlanTestCondition::WillStop ()
178{
179 return true;
180}
181
182StateType
Jim Ingham745ac7a2010-11-11 19:26:09 +0000183ThreadPlanTestCondition::GetPlanRunState ()
Jim Inghamd1686902010-10-14 23:45:03 +0000184{
185 return eStateRunning;
186}
187
188bool
189ThreadPlanTestCondition::MischiefManaged ()
190{
191 // If we get a stop we're done, we don't puase in the middle of
192 // condition execution.
193 return true;
194}