blob: 5906d53e446f58abe885f6af879a50fd429c4f70 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Thread.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/lldb-private-log.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000011#include "lldb/Breakpoint/BreakpointLocation.h"
Greg Claytona830adb2010-10-04 01:05:56 +000012#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000013#include "lldb/Core/Log.h"
14#include "lldb/Core/Stream.h"
15#include "lldb/Core/StreamString.h"
Jim Ingham20594b12010-09-08 03:14:33 +000016#include "lldb/Core/RegularExpression.h"
Greg Claytonabe0fed2011-04-18 08:33:37 +000017#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Target/DynamicLoader.h"
19#include "lldb/Target/ExecutionContext.h"
Jim Inghamb66cd072010-09-28 01:25:32 +000020#include "lldb/Target/ObjCLanguageRuntime.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Target/Process.h"
22#include "lldb/Target/RegisterContext.h"
Greg Clayton643ee732010-08-04 01:40:35 +000023#include "lldb/Target/StopInfo.h"
Greg Clayton7661a982010-07-23 16:45:51 +000024#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "lldb/Target/Thread.h"
26#include "lldb/Target/ThreadPlan.h"
27#include "lldb/Target/ThreadPlanCallFunction.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028#include "lldb/Target/ThreadPlanBase.h"
29#include "lldb/Target/ThreadPlanStepInstruction.h"
30#include "lldb/Target/ThreadPlanStepOut.h"
31#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
32#include "lldb/Target/ThreadPlanStepThrough.h"
33#include "lldb/Target/ThreadPlanStepInRange.h"
34#include "lldb/Target/ThreadPlanStepOverRange.h"
35#include "lldb/Target/ThreadPlanRunToAddress.h"
36#include "lldb/Target/ThreadPlanStepUntil.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000037#include "lldb/Target/ThreadSpec.h"
Jim Ingham71219082010-08-12 02:14:28 +000038#include "lldb/Target/Unwind.h"
Chris Lattner24943d22010-06-08 16:52:24 +000039
40using namespace lldb;
41using namespace lldb_private;
42
43Thread::Thread (Process &process, lldb::tid_t tid) :
44 UserID (tid),
Greg Claytonc0c1b0c2010-11-19 03:46:01 +000045 ThreadInstanceSettings (*GetSettingsController()),
Benjamin Kramer36a08102010-07-16 12:32:33 +000046 m_process (process),
Greg Clayton643ee732010-08-04 01:40:35 +000047 m_actual_stop_info_sp (),
Chris Lattner24943d22010-06-08 16:52:24 +000048 m_index_id (process.GetNextThreadIndexID ()),
49 m_reg_context_sp (),
Chris Lattner24943d22010-06-08 16:52:24 +000050 m_state (eStateUnloaded),
Greg Clayton782b9cc2010-08-25 00:35:26 +000051 m_state_mutex (Mutex::eMutexTypeRecursive),
Chris Lattner24943d22010-06-08 16:52:24 +000052 m_plan_stack (),
Chris Lattner24943d22010-06-08 16:52:24 +000053 m_completed_plan_stack(),
Greg Claytonf40e3082010-08-26 02:28:22 +000054 m_curr_frames_ap (),
Chris Lattner24943d22010-06-08 16:52:24 +000055 m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
Jim Ingham71219082010-08-12 02:14:28 +000056 m_resume_state (eStateRunning),
Jim Inghamcdea2362010-11-18 02:47:07 +000057 m_unwinder_ap (),
Jim Ingham15dcb7c2011-01-20 02:03:18 +000058 m_destroy_called (false),
59 m_thread_stop_reason_stop_id (0)
Jim Ingham71219082010-08-12 02:14:28 +000060
Chris Lattner24943d22010-06-08 16:52:24 +000061{
Greg Claytone005f2c2010-11-06 01:53:30 +000062 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner24943d22010-06-08 16:52:24 +000063 if (log)
64 log->Printf ("%p Thread::Thread(tid = 0x%4.4x)", this, GetID());
65
66 QueueFundamentalPlan(true);
Caroline Tice1ebef442010-09-27 00:30:10 +000067 UpdateInstanceName();
Chris Lattner24943d22010-06-08 16:52:24 +000068}
69
70
71Thread::~Thread()
72{
Greg Claytone005f2c2010-11-06 01:53:30 +000073 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner24943d22010-06-08 16:52:24 +000074 if (log)
75 log->Printf ("%p Thread::~Thread(tid = 0x%4.4x)", this, GetID());
Jim Inghamcdea2362010-11-18 02:47:07 +000076 /// If you hit this assert, it means your derived class forgot to call DoDestroy in its destructor.
77 assert (m_destroy_called);
78}
79
80void
81Thread::DestroyThread ()
82{
83 m_plan_stack.clear();
84 m_discarded_plan_stack.clear();
85 m_completed_plan_stack.clear();
86 m_destroy_called = true;
Chris Lattner24943d22010-06-08 16:52:24 +000087}
88
Jim Ingham6297a3a2010-10-20 00:39:53 +000089lldb::StopInfoSP
Greg Clayton643ee732010-08-04 01:40:35 +000090Thread::GetStopInfo ()
Chris Lattner24943d22010-06-08 16:52:24 +000091{
Jim Ingham6297a3a2010-10-20 00:39:53 +000092 ThreadPlanSP plan_sp (GetCompletedPlan());
93 if (plan_sp)
94 return StopInfo::CreateStopReasonWithPlan (plan_sp);
95 else
Jim Ingham24e0d612011-08-09 00:32:52 +000096 {
97 if (m_actual_stop_info_sp
98 && m_actual_stop_info_sp->IsValid()
99 && m_thread_stop_reason_stop_id == m_process.GetStopID())
100 return m_actual_stop_info_sp;
101 else
102 return GetPrivateStopReason ();
103 }
Chris Lattner24943d22010-06-08 16:52:24 +0000104}
105
Jim Ingham15dcb7c2011-01-20 02:03:18 +0000106void
107Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
108{
109 m_actual_stop_info_sp = stop_info_sp;
Jim Ingham24e0d612011-08-09 00:32:52 +0000110 if (m_actual_stop_info_sp)
111 m_actual_stop_info_sp->MakeStopInfoValid();
Jim Ingham15dcb7c2011-01-20 02:03:18 +0000112 m_thread_stop_reason_stop_id = GetProcess().GetStopID();
113}
114
115void
116Thread::SetStopInfoToNothing()
117{
118 // Note, we can't just NULL out the private reason, or the native thread implementation will try to
119 // go calculate it again. For now, just set it to a Unix Signal with an invalid signal number.
120 SetStopInfo (StopInfo::CreateStopReasonWithSignal (*this, LLDB_INVALID_SIGNAL_NUMBER));
121}
122
Chris Lattner24943d22010-06-08 16:52:24 +0000123bool
124Thread::ThreadStoppedForAReason (void)
125{
Greg Clayton643ee732010-08-04 01:40:35 +0000126 return GetPrivateStopReason () != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000127}
128
Jim Ingham15dcb7c2011-01-20 02:03:18 +0000129bool
130Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state)
131{
132 if (!SaveFrameZeroState(saved_state.register_backup))
133 return false;
134
135 saved_state.stop_info_sp = GetStopInfo();
136 saved_state.orig_stop_id = GetProcess().GetStopID();
137
138 return true;
139}
140
141bool
142Thread::RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state)
143{
144 RestoreSaveFrameZero(saved_state.register_backup);
Jim Ingham11a837d2011-01-25 02:47:23 +0000145 if (saved_state.stop_info_sp)
146 saved_state.stop_info_sp->MakeStopInfoValid();
Jim Ingham15dcb7c2011-01-20 02:03:18 +0000147 SetStopInfo(saved_state.stop_info_sp);
148 return true;
149}
150
Chris Lattner24943d22010-06-08 16:52:24 +0000151StateType
152Thread::GetState() const
153{
154 // If any other threads access this we will need a mutex for it
155 Mutex::Locker locker(m_state_mutex);
156 return m_state;
157}
158
159void
160Thread::SetState(StateType state)
161{
162 Mutex::Locker locker(m_state_mutex);
163 m_state = state;
164}
165
166void
167Thread::WillStop()
168{
169 ThreadPlan *current_plan = GetCurrentPlan();
170
171 // FIXME: I may decide to disallow threads with no plans. In which
172 // case this should go to an assert.
173
174 if (!current_plan)
175 return;
176
177 current_plan->WillStop();
178}
179
180void
181Thread::SetupForResume ()
182{
183 if (GetResumeState() != eStateSuspended)
184 {
185
186 // If we're at a breakpoint push the step-over breakpoint plan. Do this before
187 // telling the current plan it will resume, since we might change what the current
188 // plan is.
189
190 lldb::addr_t pc = GetRegisterContext()->GetPC();
191 BreakpointSiteSP bp_site_sp = GetProcess().GetBreakpointSiteList().FindByAddress(pc);
192 if (bp_site_sp && bp_site_sp->IsEnabled())
193 {
194 // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
195 // special to step over a breakpoint.
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000196
197 ThreadPlan *cur_plan = GetCurrentPlan();
Chris Lattner24943d22010-06-08 16:52:24 +0000198
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000199 if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
200 {
201 ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
202 if (step_bp_plan)
Chris Lattner24943d22010-06-08 16:52:24 +0000203 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000204 ThreadPlanSP step_bp_plan_sp;
205 step_bp_plan->SetPrivate (true);
206
Chris Lattner24943d22010-06-08 16:52:24 +0000207 if (GetCurrentPlan()->RunState() != eStateStepping)
208 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000209 step_bp_plan->SetAutoContinue(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000210 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000211 step_bp_plan_sp.reset (step_bp_plan);
Chris Lattner24943d22010-06-08 16:52:24 +0000212 QueueThreadPlan (step_bp_plan_sp, false);
213 }
214 }
215 }
216 }
217}
218
219bool
220Thread::WillResume (StateType resume_state)
221{
222 // At this point clear the completed plan stack.
223 m_completed_plan_stack.clear();
224 m_discarded_plan_stack.clear();
225
Greg Clayton643ee732010-08-04 01:40:35 +0000226 StopInfo *stop_info = GetPrivateStopReason().get();
227 if (stop_info)
228 stop_info->WillResume (resume_state);
Chris Lattner24943d22010-06-08 16:52:24 +0000229
230 // Tell all the plans that we are about to resume in case they need to clear any state.
231 // We distinguish between the plan on the top of the stack and the lower
232 // plans in case a plan needs to do any special business before it runs.
233
234 ThreadPlan *plan_ptr = GetCurrentPlan();
235 plan_ptr->WillResume(resume_state, true);
236
237 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
238 {
239 plan_ptr->WillResume (resume_state, false);
240 }
Greg Clayton643ee732010-08-04 01:40:35 +0000241
Greg Clayton643ee732010-08-04 01:40:35 +0000242 m_actual_stop_info_sp.reset();
Chris Lattner24943d22010-06-08 16:52:24 +0000243 return true;
244}
245
246void
247Thread::DidResume ()
248{
249 SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
250}
251
252bool
253Thread::ShouldStop (Event* event_ptr)
254{
255 ThreadPlan *current_plan = GetCurrentPlan();
256 bool should_stop = true;
257
Greg Claytone005f2c2010-11-06 01:53:30 +0000258 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000259 if (log)
260 {
261 StreamString s;
262 DumpThreadPlans(&s);
263 log->PutCString (s.GetData());
264 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000265
266 // The top most plan always gets to do the trace log...
267 current_plan->DoTraceLog ();
Chris Lattner24943d22010-06-08 16:52:24 +0000268
269 if (current_plan->PlanExplainsStop())
270 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000271 bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
Jim Inghamf9f40c22011-02-08 05:20:59 +0000272
273 // We're starting from the base plan, so just let it decide;
274 if (PlanIsBasePlan(current_plan))
Chris Lattner24943d22010-06-08 16:52:24 +0000275 {
Jim Inghamf9f40c22011-02-08 05:20:59 +0000276 should_stop = current_plan->ShouldStop (event_ptr);
277 if (log)
Greg Clayton628cead2011-05-19 03:54:16 +0000278 log->Printf("Base plan says should stop: %i.", should_stop);
Jim Inghamf9f40c22011-02-08 05:20:59 +0000279 }
280 else
281 {
282 // Otherwise, don't let the base plan override what the other plans say to do, since
283 // presumably if there were other plans they would know what to do...
284 while (1)
Chris Lattner24943d22010-06-08 16:52:24 +0000285 {
Jim Inghamf9f40c22011-02-08 05:20:59 +0000286 if (PlanIsBasePlan(current_plan))
Chris Lattner24943d22010-06-08 16:52:24 +0000287 break;
Jim Inghamf9f40c22011-02-08 05:20:59 +0000288
289 should_stop = current_plan->ShouldStop(event_ptr);
290 if (log)
291 log->Printf("Plan %s should stop: %d.", current_plan->GetName(), should_stop);
292 if (current_plan->MischiefManaged())
293 {
294 if (should_stop)
295 current_plan->WillStop();
296
297 // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
298 // Otherwise, see if the plan's parent wants to stop.
299
300 if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
301 {
302 PopPlan();
303 break;
304 }
305 else
306 {
307
308 PopPlan();
309
310 current_plan = GetCurrentPlan();
311 if (current_plan == NULL)
312 {
313 break;
314 }
315 }
316
Chris Lattner24943d22010-06-08 16:52:24 +0000317 }
318 else
319 {
Jim Inghamf9f40c22011-02-08 05:20:59 +0000320 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000321 }
Chris Lattner24943d22010-06-08 16:52:24 +0000322 }
323 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000324 if (over_ride_stop)
325 should_stop = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000326 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000327 else if (current_plan->TracerExplainsStop())
328 {
329 return false;
330 }
Chris Lattner24943d22010-06-08 16:52:24 +0000331 else
332 {
333 // If the current plan doesn't explain the stop, then, find one that
334 // does and let it handle the situation.
335 ThreadPlan *plan_ptr = current_plan;
336 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
337 {
338 if (plan_ptr->PlanExplainsStop())
339 {
340 should_stop = plan_ptr->ShouldStop (event_ptr);
341 break;
342 }
343
344 }
345 }
346
347 return should_stop;
348}
349
350Vote
351Thread::ShouldReportStop (Event* event_ptr)
352{
353 StateType thread_state = GetResumeState ();
Greg Claytone005f2c2010-11-06 01:53:30 +0000354 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +0000355
356 if (thread_state == eStateSuspended || thread_state == eStateInvalid)
357 {
358 if (log)
359 log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4x: returning vote %i (state was suspended or invalid)\n", GetID(), eVoteNoOpinion);
Chris Lattner24943d22010-06-08 16:52:24 +0000360 return eVoteNoOpinion;
Greg Clayton5205f0b2010-09-03 17:10:42 +0000361 }
Chris Lattner24943d22010-06-08 16:52:24 +0000362
363 if (m_completed_plan_stack.size() > 0)
364 {
365 // Don't use GetCompletedPlan here, since that suppresses private plans.
Greg Clayton5205f0b2010-09-03 17:10:42 +0000366 if (log)
367 log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4x: returning vote for complete stack's back plan\n", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000368 return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
369 }
370 else
Greg Clayton5205f0b2010-09-03 17:10:42 +0000371 {
372 if (log)
373 log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4x: returning vote for current plan\n", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000374 return GetCurrentPlan()->ShouldReportStop (event_ptr);
Greg Clayton5205f0b2010-09-03 17:10:42 +0000375 }
Chris Lattner24943d22010-06-08 16:52:24 +0000376}
377
378Vote
379Thread::ShouldReportRun (Event* event_ptr)
380{
381 StateType thread_state = GetResumeState ();
Jim Inghamac959662011-01-24 06:34:17 +0000382
Chris Lattner24943d22010-06-08 16:52:24 +0000383 if (thread_state == eStateSuspended
384 || thread_state == eStateInvalid)
Jim Inghamac959662011-01-24 06:34:17 +0000385 {
Chris Lattner24943d22010-06-08 16:52:24 +0000386 return eVoteNoOpinion;
Jim Inghamac959662011-01-24 06:34:17 +0000387 }
388
389 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000390 if (m_completed_plan_stack.size() > 0)
391 {
392 // Don't use GetCompletedPlan here, since that suppresses private plans.
Jim Inghamac959662011-01-24 06:34:17 +0000393 if (log)
394 log->Printf ("Current Plan for thread %d (0x%4.4x): %s being asked whether we should report run.",
395 GetIndexID(),
396 GetID(),
397 m_completed_plan_stack.back()->GetName());
398
Chris Lattner24943d22010-06-08 16:52:24 +0000399 return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
400 }
401 else
Jim Inghamac959662011-01-24 06:34:17 +0000402 {
403 if (log)
404 log->Printf ("Current Plan for thread %d (0x%4.4x): %s being asked whether we should report run.",
405 GetIndexID(),
406 GetID(),
407 GetCurrentPlan()->GetName());
408
Chris Lattner24943d22010-06-08 16:52:24 +0000409 return GetCurrentPlan()->ShouldReportRun (event_ptr);
Jim Inghamac959662011-01-24 06:34:17 +0000410 }
Chris Lattner24943d22010-06-08 16:52:24 +0000411}
412
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000413bool
414Thread::MatchesSpec (const ThreadSpec *spec)
415{
416 if (spec == NULL)
417 return true;
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000418
Jim Ingham649492b2010-06-18 01:00:58 +0000419 return spec->ThreadPassesBasicTests(this);
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000420}
421
Chris Lattner24943d22010-06-08 16:52:24 +0000422void
423Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
424{
425 if (thread_plan_sp)
426 {
Jim Ingham745ac7a2010-11-11 19:26:09 +0000427 // If the thread plan doesn't already have a tracer, give it its parent's tracer:
428 if (!thread_plan_sp->GetThreadPlanTracer())
429 thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
Jim Ingham6297a3a2010-10-20 00:39:53 +0000430 m_plan_stack.push_back (thread_plan_sp);
Jim Ingham745ac7a2010-11-11 19:26:09 +0000431
Chris Lattner24943d22010-06-08 16:52:24 +0000432 thread_plan_sp->DidPush();
433
Greg Claytone005f2c2010-11-06 01:53:30 +0000434 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000435 if (log)
436 {
437 StreamString s;
438 thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
Jim Ingham6297a3a2010-10-20 00:39:53 +0000439 log->Printf("Pushing plan: \"%s\", tid = 0x%4.4x.",
Chris Lattner24943d22010-06-08 16:52:24 +0000440 s.GetData(),
Jim Ingham6297a3a2010-10-20 00:39:53 +0000441 thread_plan_sp->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000442 }
443 }
444}
445
446void
447Thread::PopPlan ()
448{
Greg Claytone005f2c2010-11-06 01:53:30 +0000449 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000450
Jim Ingham6297a3a2010-10-20 00:39:53 +0000451 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000452 return;
453 else
454 {
455 ThreadPlanSP &plan = m_plan_stack.back();
456 if (log)
457 {
Jim Ingham83e8b9d2010-11-10 18:17:03 +0000458 log->Printf("Popping plan: \"%s\", tid = 0x%4.4x.", plan->GetName(), plan->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000459 }
460 m_completed_plan_stack.push_back (plan);
461 plan->WillPop();
462 m_plan_stack.pop_back();
463 }
464}
465
466void
467Thread::DiscardPlan ()
468{
469 if (m_plan_stack.size() > 1)
470 {
471 ThreadPlanSP &plan = m_plan_stack.back();
472 m_discarded_plan_stack.push_back (plan);
473 plan->WillPop();
474 m_plan_stack.pop_back();
475 }
476}
477
478ThreadPlan *
479Thread::GetCurrentPlan ()
480{
Jim Ingham6297a3a2010-10-20 00:39:53 +0000481 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000482 return NULL;
483 else
484 return m_plan_stack.back().get();
485}
486
487ThreadPlanSP
488Thread::GetCompletedPlan ()
489{
490 ThreadPlanSP empty_plan_sp;
491 if (!m_completed_plan_stack.empty())
492 {
493 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
494 {
495 ThreadPlanSP completed_plan_sp;
496 completed_plan_sp = m_completed_plan_stack[i];
497 if (!completed_plan_sp->GetPrivate ())
498 return completed_plan_sp;
499 }
500 }
501 return empty_plan_sp;
502}
503
504bool
505Thread::IsThreadPlanDone (ThreadPlan *plan)
506{
Chris Lattner24943d22010-06-08 16:52:24 +0000507 if (!m_completed_plan_stack.empty())
508 {
509 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
510 {
511 if (m_completed_plan_stack[i].get() == plan)
512 return true;
513 }
514 }
515 return false;
516}
517
518bool
519Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
520{
Chris Lattner24943d22010-06-08 16:52:24 +0000521 if (!m_discarded_plan_stack.empty())
522 {
523 for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
524 {
525 if (m_discarded_plan_stack[i].get() == plan)
526 return true;
527 }
528 }
529 return false;
530}
531
532ThreadPlan *
533Thread::GetPreviousPlan (ThreadPlan *current_plan)
534{
535 if (current_plan == NULL)
536 return NULL;
537
538 int stack_size = m_completed_plan_stack.size();
539 for (int i = stack_size - 1; i > 0; i--)
540 {
541 if (current_plan == m_completed_plan_stack[i].get())
542 return m_completed_plan_stack[i-1].get();
543 }
544
545 if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
546 {
Chris Lattner24943d22010-06-08 16:52:24 +0000547 if (m_plan_stack.size() > 0)
548 return m_plan_stack.back().get();
549 else
550 return NULL;
551 }
552
553 stack_size = m_plan_stack.size();
554 for (int i = stack_size - 1; i > 0; i--)
555 {
556 if (current_plan == m_plan_stack[i].get())
557 return m_plan_stack[i-1].get();
558 }
559 return NULL;
560}
561
562void
563Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
564{
565 if (abort_other_plans)
566 DiscardThreadPlans(true);
567
568 PushPlan (thread_plan_sp);
569}
570
Jim Ingham745ac7a2010-11-11 19:26:09 +0000571
572void
573Thread::EnableTracer (bool value, bool single_stepping)
574{
575 int stack_size = m_plan_stack.size();
576 for (int i = 0; i < stack_size; i++)
577 {
578 if (m_plan_stack[i]->GetThreadPlanTracer())
579 {
580 m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
581 m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
582 }
583 }
584}
585
586void
587Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
588{
589 int stack_size = m_plan_stack.size();
590 for (int i = 0; i < stack_size; i++)
591 m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
592}
593
Chris Lattner24943d22010-06-08 16:52:24 +0000594void
Jim Inghamea9d4262010-11-05 19:25:48 +0000595Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
596{
Greg Claytone005f2c2010-11-06 01:53:30 +0000597 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamea9d4262010-11-05 19:25:48 +0000598 if (log)
599 {
600 log->Printf("Discarding thread plans for thread tid = 0x%4.4x, up to %p", GetID(), up_to_plan_sp.get());
601 }
602
603 int stack_size = m_plan_stack.size();
604
605 // If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
606 // stack, and if so discard up to and including it.
607
608 if (up_to_plan_sp.get() == NULL)
609 {
610 for (int i = stack_size - 1; i > 0; i--)
611 DiscardPlan();
612 }
613 else
614 {
615 bool found_it = false;
616 for (int i = stack_size - 1; i > 0; i--)
617 {
618 if (m_plan_stack[i] == up_to_plan_sp)
619 found_it = true;
620 }
621 if (found_it)
622 {
623 bool last_one = false;
624 for (int i = stack_size - 1; i > 0 && !last_one ; i--)
625 {
626 if (GetCurrentPlan() == up_to_plan_sp.get())
627 last_one = true;
628 DiscardPlan();
629 }
630 }
631 }
632 return;
633}
634
635void
Chris Lattner24943d22010-06-08 16:52:24 +0000636Thread::DiscardThreadPlans(bool force)
637{
Greg Claytone005f2c2010-11-06 01:53:30 +0000638 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000639 if (log)
640 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000641 log->Printf("Discarding thread plans for thread (tid = 0x%4.4x, force %d)", GetID(), force);
Chris Lattner24943d22010-06-08 16:52:24 +0000642 }
643
644 if (force)
645 {
646 int stack_size = m_plan_stack.size();
647 for (int i = stack_size - 1; i > 0; i--)
648 {
649 DiscardPlan();
650 }
651 return;
652 }
653
654 while (1)
655 {
656
657 int master_plan_idx;
658 bool discard;
659
660 // Find the first master plan, see if it wants discarding, and if yes discard up to it.
661 for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
662 {
663 if (m_plan_stack[master_plan_idx]->IsMasterPlan())
664 {
665 discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
666 break;
667 }
668 }
669
670 if (discard)
671 {
672 // First pop all the dependent plans:
673 for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
674 {
675
676 // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
677 // for the plan leaves it in a state that it is safe to pop the plan
678 // with no more notice?
679 DiscardPlan();
680 }
681
682 // Now discard the master plan itself.
683 // The bottom-most plan never gets discarded. "OkayToDiscard" for it means
684 // discard it's dependent plans, but not it...
685 if (master_plan_idx > 0)
686 {
687 DiscardPlan();
688 }
689 }
690 else
691 {
692 // If the master plan doesn't want to get discarded, then we're done.
693 break;
694 }
695
696 }
Chris Lattner24943d22010-06-08 16:52:24 +0000697}
698
699ThreadPlan *
700Thread::QueueFundamentalPlan (bool abort_other_plans)
701{
702 ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
703 QueueThreadPlan (thread_plan_sp, abort_other_plans);
704 return thread_plan_sp.get();
705}
706
707ThreadPlan *
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000708Thread::QueueThreadPlanForStepSingleInstruction
709(
710 bool step_over,
711 bool abort_other_plans,
712 bool stop_other_threads
713)
Chris Lattner24943d22010-06-08 16:52:24 +0000714{
715 ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
716 QueueThreadPlan (thread_plan_sp, abort_other_plans);
717 return thread_plan_sp.get();
718}
719
720ThreadPlan *
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000721Thread::QueueThreadPlanForStepRange
722(
723 bool abort_other_plans,
724 StepType type,
725 const AddressRange &range,
726 const SymbolContext &addr_context,
727 lldb::RunMode stop_other_threads,
728 bool avoid_code_without_debug_info
729)
Chris Lattner24943d22010-06-08 16:52:24 +0000730{
731 ThreadPlanSP thread_plan_sp;
732 if (type == eStepTypeInto)
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000733 {
734 ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
735 if (avoid_code_without_debug_info)
736 plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
737 else
738 plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
739 thread_plan_sp.reset (plan);
740 }
Chris Lattner24943d22010-06-08 16:52:24 +0000741 else
742 thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
743
744 QueueThreadPlan (thread_plan_sp, abort_other_plans);
745 return thread_plan_sp.get();
746}
747
748
749ThreadPlan *
750Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
751{
752 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
753 QueueThreadPlan (thread_plan_sp, abort_other_plans);
754 return thread_plan_sp.get();
755}
756
757ThreadPlan *
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000758Thread::QueueThreadPlanForStepOut
759(
760 bool abort_other_plans,
761 SymbolContext *addr_context,
762 bool first_insn,
763 bool stop_other_threads,
764 Vote stop_vote,
765 Vote run_vote,
766 uint32_t frame_idx
767)
Chris Lattner24943d22010-06-08 16:52:24 +0000768{
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000769 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this,
770 addr_context,
771 first_insn,
772 stop_other_threads,
773 stop_vote,
774 run_vote,
775 frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000776 QueueThreadPlan (thread_plan_sp, abort_other_plans);
777 return thread_plan_sp.get();
778}
779
780ThreadPlan *
781Thread::QueueThreadPlanForStepThrough (bool abort_other_plans, bool stop_other_threads)
782{
Jim Inghamb66cd072010-09-28 01:25:32 +0000783 // Try the dynamic loader first:
Chris Lattner24943d22010-06-08 16:52:24 +0000784 ThreadPlanSP thread_plan_sp(GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (*this, stop_other_threads));
Jim Inghamb66cd072010-09-28 01:25:32 +0000785 // If that didn't come up with anything, try the ObjC runtime plugin:
786 if (thread_plan_sp.get() == NULL)
787 {
788 ObjCLanguageRuntime *objc_runtime = GetProcess().GetObjCLanguageRuntime();
789 if (objc_runtime)
790 thread_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (*this, stop_other_threads);
791 }
792
Chris Lattner24943d22010-06-08 16:52:24 +0000793 if (thread_plan_sp.get() == NULL)
794 {
795 thread_plan_sp.reset(new ThreadPlanStepThrough (*this, stop_other_threads));
796 if (thread_plan_sp && !thread_plan_sp->ValidatePlan (NULL))
Greg Claytonf8e98a62010-07-23 15:37:46 +0000797 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000798 }
799 QueueThreadPlan (thread_plan_sp, abort_other_plans);
800 return thread_plan_sp.get();
801}
802
803ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000804Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
805 Address& function,
806 lldb::addr_t arg,
807 bool stop_other_threads,
808 bool discard_on_error)
809{
810 ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
811 QueueThreadPlan (thread_plan_sp, abort_other_plans);
812 return thread_plan_sp.get();
813}
814
815ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000816Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
817 Address &target_addr,
818 bool stop_other_threads)
819{
820 ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
821 QueueThreadPlan (thread_plan_sp, abort_other_plans);
822 return thread_plan_sp.get();
823}
824
825ThreadPlan *
826Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000827 lldb::addr_t *address_list,
828 size_t num_addresses,
829 bool stop_other_threads,
830 uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000831{
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000832 ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads, frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000833 QueueThreadPlan (thread_plan_sp, abort_other_plans);
834 return thread_plan_sp.get();
835
836}
837
838uint32_t
839Thread::GetIndexID () const
840{
841 return m_index_id;
842}
843
844void
845Thread::DumpThreadPlans (lldb_private::Stream *s) const
846{
847 uint32_t stack_size = m_plan_stack.size();
Greg Claytonf04d6612010-09-03 22:45:01 +0000848 int i;
849 s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4x, stack_size = %d\n", GetIndexID(), GetID(), stack_size);
850 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000851 {
852 s->Printf ("Element %d: ", i);
853 s->IndentMore();
854 m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
855 s->IndentLess();
856 s->EOL();
857 }
858
Chris Lattner24943d22010-06-08 16:52:24 +0000859 stack_size = m_completed_plan_stack.size();
860 s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
Greg Claytonf04d6612010-09-03 22:45:01 +0000861 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000862 {
863 s->Printf ("Element %d: ", i);
864 s->IndentMore();
865 m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
866 s->IndentLess();
867 s->EOL();
868 }
869
870 stack_size = m_discarded_plan_stack.size();
871 s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
Greg Claytonbdcb6ab2011-01-25 23:55:37 +0000872 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000873 {
874 s->Printf ("Element %d: ", i);
875 s->IndentMore();
876 m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
877 s->IndentLess();
878 s->EOL();
879 }
880
881}
882
883Target *
884Thread::CalculateTarget ()
885{
886 return m_process.CalculateTarget();
887}
888
889Process *
890Thread::CalculateProcess ()
891{
892 return &m_process;
893}
894
895Thread *
896Thread::CalculateThread ()
897{
898 return this;
899}
900
901StackFrame *
902Thread::CalculateStackFrame ()
903{
904 return NULL;
905}
906
907void
Greg Claytona830adb2010-10-04 01:05:56 +0000908Thread::CalculateExecutionContext (ExecutionContext &exe_ctx)
Chris Lattner24943d22010-06-08 16:52:24 +0000909{
Greg Claytona830adb2010-10-04 01:05:56 +0000910 m_process.CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000911 exe_ctx.thread = this;
912 exe_ctx.frame = NULL;
913}
914
Greg Clayton782b9cc2010-08-25 00:35:26 +0000915
916StackFrameList &
917Thread::GetStackFrameList ()
918{
Greg Claytonf40e3082010-08-26 02:28:22 +0000919 if (m_curr_frames_ap.get() == NULL)
Greg Clayton5205f0b2010-09-03 17:10:42 +0000920 m_curr_frames_ap.reset (new StackFrameList (*this, m_prev_frames_sp, true));
Greg Claytonf40e3082010-08-26 02:28:22 +0000921 return *m_curr_frames_ap;
Greg Clayton782b9cc2010-08-25 00:35:26 +0000922}
923
924
925
Jim Ingham71219082010-08-12 02:14:28 +0000926uint32_t
927Thread::GetStackFrameCount()
928{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000929 return GetStackFrameList().GetNumFrames();
930}
Greg Clayton33ed1702010-08-24 00:45:41 +0000931
Greg Clayton33ed1702010-08-24 00:45:41 +0000932
Greg Clayton782b9cc2010-08-25 00:35:26 +0000933void
934Thread::ClearStackFrames ()
935{
Greg Clayton5205f0b2010-09-03 17:10:42 +0000936 if (m_curr_frames_ap.get() && m_curr_frames_ap->GetNumFrames (false) > 1)
937 m_prev_frames_sp.reset (m_curr_frames_ap.release());
938 else
939 m_curr_frames_ap.release();
940
941// StackFrameList::Merge (m_curr_frames_ap, m_prev_frames_sp);
942// assert (m_curr_frames_ap.get() == NULL);
Jim Ingham71219082010-08-12 02:14:28 +0000943}
944
945lldb::StackFrameSP
946Thread::GetStackFrameAtIndex (uint32_t idx)
947{
Greg Clayton72b71582010-09-02 21:44:10 +0000948 return GetStackFrameList().GetFrameAtIndex(idx);
Jim Ingham71219082010-08-12 02:14:28 +0000949}
950
Greg Claytonc12b6b42010-10-10 22:28:11 +0000951uint32_t
952Thread::GetSelectedFrameIndex ()
953{
954 return GetStackFrameList().GetSelectedFrameIndex();
955}
956
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000957lldb::StackFrameSP
958Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
959{
960 return GetStackFrameList().GetFrameWithConcreteFrameIndex (unwind_idx);
961}
962
Jim Ingham5c4b1602011-03-31 00:15:49 +0000963lldb::StackFrameSP
964Thread::GetFrameWithStackID(StackID &stack_id)
965{
966 return GetStackFrameList().GetFrameWithStackID (stack_id);
967}
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000968
Greg Claytonc12b6b42010-10-10 22:28:11 +0000969
Chris Lattner24943d22010-06-08 16:52:24 +0000970lldb::StackFrameSP
Jim Inghamc8332952010-08-26 21:32:51 +0000971Thread::GetSelectedFrame ()
Chris Lattner24943d22010-06-08 16:52:24 +0000972{
Jim Inghamc8332952010-08-26 21:32:51 +0000973 return GetStackFrameAtIndex (GetStackFrameList().GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000974}
975
976uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000977Thread::SetSelectedFrame (lldb_private::StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000978{
Jim Inghamc8332952010-08-26 21:32:51 +0000979 return GetStackFrameList().SetSelectedFrame(frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000980}
981
982void
Jim Inghamc8332952010-08-26 21:32:51 +0000983Thread::SetSelectedFrameByIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000984{
Jim Inghamc8332952010-08-26 21:32:51 +0000985 GetStackFrameList().SetSelectedFrameByIndex(idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000986}
987
988void
Greg Claytona830adb2010-10-04 01:05:56 +0000989Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000990{
Greg Claytona830adb2010-10-04 01:05:56 +0000991 ExecutionContext exe_ctx;
992 SymbolContext frame_sc;
993 CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000994
Greg Claytona830adb2010-10-04 01:05:56 +0000995 if (frame_idx != LLDB_INVALID_INDEX32)
Chris Lattner24943d22010-06-08 16:52:24 +0000996 {
Greg Claytona830adb2010-10-04 01:05:56 +0000997 StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000998 if (frame_sp)
999 {
Greg Claytona830adb2010-10-04 01:05:56 +00001000 exe_ctx.frame = frame_sp.get();
1001 frame_sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
Chris Lattner24943d22010-06-08 16:52:24 +00001002 }
1003 }
1004
Greg Claytona830adb2010-10-04 01:05:56 +00001005 const char *thread_format = GetProcess().GetTarget().GetDebugger().GetThreadFormat();
1006 assert (thread_format);
1007 const char *end = NULL;
1008 Debugger::FormatPrompt (thread_format,
1009 exe_ctx.frame ? &frame_sc : NULL,
1010 &exe_ctx,
1011 NULL,
1012 strm,
1013 &end);
Chris Lattner24943d22010-06-08 16:52:24 +00001014}
1015
1016lldb::ThreadSP
1017Thread::GetSP ()
1018{
1019 return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
1020}
Jim Ingham20594b12010-09-08 03:14:33 +00001021
Greg Clayton990de7b2010-11-18 23:32:35 +00001022
1023void
Caroline Tice2a456812011-03-10 22:14:10 +00001024Thread::SettingsInitialize ()
Jim Ingham20594b12010-09-08 03:14:33 +00001025{
Greg Clayton990de7b2010-11-18 23:32:35 +00001026 UserSettingsControllerSP &usc = GetSettingsController();
1027 usc.reset (new SettingsController);
1028 UserSettingsController::InitializeSettingsController (usc,
1029 SettingsController::global_settings_table,
1030 SettingsController::instance_settings_table);
Caroline Tice2a456812011-03-10 22:14:10 +00001031
1032 // Now call SettingsInitialize() on each 'child' setting of Thread.
1033 // Currently there are none.
Greg Clayton990de7b2010-11-18 23:32:35 +00001034}
Jim Ingham20594b12010-09-08 03:14:33 +00001035
Greg Clayton990de7b2010-11-18 23:32:35 +00001036void
Caroline Tice2a456812011-03-10 22:14:10 +00001037Thread::SettingsTerminate ()
Greg Clayton990de7b2010-11-18 23:32:35 +00001038{
Caroline Tice2a456812011-03-10 22:14:10 +00001039 // Must call SettingsTerminate() on each 'child' setting of Thread before terminating Thread settings.
1040 // Currently there are none.
1041
1042 // Now terminate Thread Settings.
1043
Greg Clayton990de7b2010-11-18 23:32:35 +00001044 UserSettingsControllerSP &usc = GetSettingsController();
1045 UserSettingsController::FinalizeSettingsController (usc);
1046 usc.reset();
1047}
Jim Ingham20594b12010-09-08 03:14:33 +00001048
Greg Clayton990de7b2010-11-18 23:32:35 +00001049UserSettingsControllerSP &
1050Thread::GetSettingsController ()
1051{
1052 static UserSettingsControllerSP g_settings_controller;
Jim Ingham20594b12010-09-08 03:14:33 +00001053 return g_settings_controller;
1054}
1055
Caroline Tice1ebef442010-09-27 00:30:10 +00001056void
1057Thread::UpdateInstanceName ()
1058{
1059 StreamString sstr;
1060 const char *name = GetName();
1061
1062 if (name && name[0] != '\0')
1063 sstr.Printf ("%s", name);
1064 else if ((GetIndexID() != 0) || (GetID() != 0))
1065 sstr.Printf ("0x%4.4x", GetIndexID(), GetID());
1066
1067 if (sstr.GetSize() > 0)
1068 Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
1069}
1070
Jim Inghamccd584d2010-09-23 17:40:12 +00001071lldb::StackFrameSP
1072Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
1073{
1074 return GetStackFrameList().GetStackFrameSPForStackFramePtr (stack_frame_ptr);
1075}
Caroline Tice7826c882010-10-26 03:11:13 +00001076
1077const char *
1078Thread::StopReasonAsCString (lldb::StopReason reason)
1079{
1080 switch (reason)
1081 {
1082 case eStopReasonInvalid: return "invalid";
1083 case eStopReasonNone: return "none";
1084 case eStopReasonTrace: return "trace";
1085 case eStopReasonBreakpoint: return "breakpoint";
1086 case eStopReasonWatchpoint: return "watchpoint";
1087 case eStopReasonSignal: return "signal";
1088 case eStopReasonException: return "exception";
1089 case eStopReasonPlanComplete: return "plan complete";
1090 }
1091
1092
1093 static char unknown_state_string[64];
1094 snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
1095 return unknown_state_string;
1096}
1097
1098const char *
1099Thread::RunModeAsCString (lldb::RunMode mode)
1100{
1101 switch (mode)
1102 {
1103 case eOnlyThisThread: return "only this thread";
1104 case eAllThreads: return "all threads";
1105 case eOnlyDuringStepping: return "only during stepping";
1106 }
1107
1108 static char unknown_state_string[64];
1109 snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
1110 return unknown_state_string;
1111}
Jim Ingham745ac7a2010-11-11 19:26:09 +00001112
Greg Claytonabe0fed2011-04-18 08:33:37 +00001113size_t
1114Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint32_t num_frames_with_source)
1115{
1116 size_t num_frames_shown = 0;
1117 strm.Indent();
1118 strm.Printf("%c ", GetProcess().GetThreadList().GetSelectedThread().get() == this ? '*' : ' ');
Greg Claytonc5dca6c2011-08-12 06:47:54 +00001119 if (GetProcess().GetTarget().GetDebugger().GetUseExternalEditor())
Greg Claytonabe0fed2011-04-18 08:33:37 +00001120 {
Greg Claytonc5dca6c2011-08-12 06:47:54 +00001121 StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
1122 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
1123 if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file)
1124 {
1125 Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
1126 }
Greg Claytonabe0fed2011-04-18 08:33:37 +00001127 }
1128
1129 DumpUsingSettingsFormat (strm, start_frame);
1130
1131 if (num_frames > 0)
1132 {
1133 strm.IndentMore();
1134
1135 const bool show_frame_info = true;
1136 const uint32_t source_lines_before = 3;
1137 const uint32_t source_lines_after = 3;
Jim Ingham7868bcc2011-07-26 02:39:59 +00001138 strm.IndentMore ();
Greg Claytonabe0fed2011-04-18 08:33:37 +00001139 num_frames_shown = GetStackFrameList ().GetStatus (strm,
1140 start_frame,
1141 num_frames,
1142 show_frame_info,
1143 num_frames_with_source,
1144 source_lines_before,
1145 source_lines_after);
1146 strm.IndentLess();
Jim Ingham7868bcc2011-07-26 02:39:59 +00001147 strm.IndentLess();
Greg Claytonabe0fed2011-04-18 08:33:37 +00001148 }
1149 return num_frames_shown;
1150}
1151
1152size_t
1153Thread::GetStackFrameStatus (Stream& strm,
1154 uint32_t first_frame,
1155 uint32_t num_frames,
1156 bool show_frame_info,
1157 uint32_t num_frames_with_source,
1158 uint32_t source_lines_before,
1159 uint32_t source_lines_after)
1160{
1161 return GetStackFrameList().GetStatus (strm,
1162 first_frame,
1163 num_frames,
1164 show_frame_info,
1165 num_frames_with_source,
1166 source_lines_before,
1167 source_lines_after);
1168}
1169
Peter Collingbournee426d852011-06-03 20:40:54 +00001170bool
1171Thread::SaveFrameZeroState (RegisterCheckpoint &checkpoint)
1172{
1173 lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
1174 if (frame_sp)
1175 {
1176 checkpoint.SetStackID(frame_sp->GetStackID());
1177 return frame_sp->GetRegisterContext()->ReadAllRegisterValues (checkpoint.GetData());
1178 }
1179 return false;
1180}
Greg Claytonabe0fed2011-04-18 08:33:37 +00001181
Peter Collingbournee426d852011-06-03 20:40:54 +00001182bool
1183Thread::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
1184{
1185 lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
1186 if (frame_sp)
1187 {
1188 bool ret = frame_sp->GetRegisterContext()->WriteAllRegisterValues (checkpoint.GetData());
1189
1190 // Clear out all stack frames as our world just changed.
1191 ClearStackFrames();
1192 frame_sp->GetRegisterContext()->InvalidateIfNeeded(true);
1193
1194 return ret;
1195 }
1196 return false;
1197}
Greg Claytonabe0fed2011-04-18 08:33:37 +00001198
Greg Clayton990de7b2010-11-18 23:32:35 +00001199#pragma mark "Thread::SettingsController"
Jim Ingham745ac7a2010-11-11 19:26:09 +00001200//--------------------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001201// class Thread::SettingsController
Jim Ingham745ac7a2010-11-11 19:26:09 +00001202//--------------------------------------------------------------
1203
Greg Clayton990de7b2010-11-18 23:32:35 +00001204Thread::SettingsController::SettingsController () :
Jim Ingham745ac7a2010-11-11 19:26:09 +00001205 UserSettingsController ("thread", Process::GetSettingsController())
1206{
1207 m_default_settings.reset (new ThreadInstanceSettings (*this, false,
1208 InstanceSettings::GetDefaultName().AsCString()));
1209}
1210
Greg Clayton990de7b2010-11-18 23:32:35 +00001211Thread::SettingsController::~SettingsController ()
Jim Ingham745ac7a2010-11-11 19:26:09 +00001212{
1213}
1214
1215lldb::InstanceSettingsSP
Greg Clayton990de7b2010-11-18 23:32:35 +00001216Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
Jim Ingham745ac7a2010-11-11 19:26:09 +00001217{
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001218 ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*GetSettingsController(),
1219 false,
1220 instance_name);
Jim Ingham745ac7a2010-11-11 19:26:09 +00001221 lldb::InstanceSettingsSP new_settings_sp (new_settings);
1222 return new_settings_sp;
1223}
1224
1225#pragma mark "ThreadInstanceSettings"
1226//--------------------------------------------------------------
1227// class ThreadInstanceSettings
1228//--------------------------------------------------------------
1229
1230ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
Greg Clayton638351a2010-12-04 00:10:17 +00001231 InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001232 m_avoid_regexp_ap (),
1233 m_trace_enabled (false)
1234{
1235 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
1236 // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
1237 // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
1238 // This is true for CreateInstanceName() too.
1239
1240 if (GetInstanceName() == InstanceSettings::InvalidName())
1241 {
1242 ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
1243 m_owner.RegisterInstanceSettings (this);
1244 }
1245
1246 if (live_instance)
1247 {
1248 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1249 CopyInstanceSettings (pending_settings,false);
1250 //m_owner.RemovePendingSettings (m_instance_name);
1251 }
1252}
1253
1254ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001255 InstanceSettings (*Thread::GetSettingsController(), CreateInstanceName().AsCString()),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001256 m_avoid_regexp_ap (),
1257 m_trace_enabled (rhs.m_trace_enabled)
1258{
1259 if (m_instance_name != InstanceSettings::GetDefaultName())
1260 {
1261 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1262 CopyInstanceSettings (pending_settings,false);
1263 m_owner.RemovePendingSettings (m_instance_name);
1264 }
1265 if (rhs.m_avoid_regexp_ap.get() != NULL)
1266 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1267}
1268
1269ThreadInstanceSettings::~ThreadInstanceSettings ()
1270{
1271}
1272
1273ThreadInstanceSettings&
1274ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
1275{
1276 if (this != &rhs)
1277 {
1278 if (rhs.m_avoid_regexp_ap.get() != NULL)
1279 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1280 else
1281 m_avoid_regexp_ap.reset(NULL);
1282 }
1283 m_trace_enabled = rhs.m_trace_enabled;
1284 return *this;
1285}
1286
1287
1288void
1289ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
1290 const char *index_value,
1291 const char *value,
1292 const ConstString &instance_name,
1293 const SettingEntry &entry,
Greg Claytonb3448432011-03-24 21:19:54 +00001294 VarSetOperationType op,
Jim Ingham745ac7a2010-11-11 19:26:09 +00001295 Error &err,
1296 bool pending)
1297{
1298 if (var_name == StepAvoidRegexpVarName())
1299 {
1300 std::string regexp_text;
1301 if (m_avoid_regexp_ap.get() != NULL)
1302 regexp_text.append (m_avoid_regexp_ap->GetText());
1303 UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
1304 if (regexp_text.empty())
1305 m_avoid_regexp_ap.reset();
1306 else
1307 {
1308 m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
1309
1310 }
1311 }
1312 else if (var_name == GetTraceThreadVarName())
1313 {
1314 bool success;
1315 bool result = Args::StringToBoolean(value, false, &success);
1316
1317 if (success)
1318 {
1319 m_trace_enabled = result;
1320 if (!pending)
1321 {
1322 Thread *myself = static_cast<Thread *> (this);
1323 myself->EnableTracer(m_trace_enabled, true);
1324 }
1325 }
1326 else
1327 {
1328 err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
1329 }
1330
1331 }
1332}
1333
1334void
1335ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
1336 bool pending)
1337{
1338 if (new_settings.get() == NULL)
1339 return;
1340
1341 ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
1342 if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
1343 m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
1344 else
1345 m_avoid_regexp_ap.reset ();
1346}
1347
1348bool
1349ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
1350 const ConstString &var_name,
1351 StringList &value,
1352 Error *err)
1353{
1354 if (var_name == StepAvoidRegexpVarName())
1355 {
1356 if (m_avoid_regexp_ap.get() != NULL)
1357 {
1358 std::string regexp_text("\"");
1359 regexp_text.append(m_avoid_regexp_ap->GetText());
1360 regexp_text.append ("\"");
1361 value.AppendString (regexp_text.c_str());
1362 }
1363
1364 }
1365 else if (var_name == GetTraceThreadVarName())
1366 {
1367 value.AppendString(m_trace_enabled ? "true" : "false");
1368 }
1369 else
1370 {
1371 if (err)
1372 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
1373 return false;
1374 }
1375 return true;
1376}
1377
1378const ConstString
1379ThreadInstanceSettings::CreateInstanceName ()
1380{
1381 static int instance_count = 1;
1382 StreamString sstr;
1383
1384 sstr.Printf ("thread_%d", instance_count);
1385 ++instance_count;
1386
1387 const ConstString ret_val (sstr.GetData());
1388 return ret_val;
1389}
1390
1391const ConstString &
1392ThreadInstanceSettings::StepAvoidRegexpVarName ()
1393{
1394 static ConstString step_avoid_var_name ("step-avoid-regexp");
1395
1396 return step_avoid_var_name;
1397}
1398
1399const ConstString &
1400ThreadInstanceSettings::GetTraceThreadVarName ()
1401{
1402 static ConstString trace_thread_var_name ("trace-thread");
1403
1404 return trace_thread_var_name;
1405}
1406
1407//--------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001408// SettingsController Variable Tables
Jim Ingham745ac7a2010-11-11 19:26:09 +00001409//--------------------------------------------------
1410
1411SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001412Thread::SettingsController::global_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001413{
1414 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
1415 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1416};
1417
1418
1419SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001420Thread::SettingsController::instance_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001421{
1422 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
1423 { "step-avoid-regexp", eSetVarTypeString, "", NULL, false, false, "A regular expression defining functions step-in won't stop in." },
1424 { "trace-thread", eSetVarTypeBoolean, "false", NULL, false, false, "If true, this thread will single-step and log execution." },
1425 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1426};