blob: 232bf287f63c9a7e78003b32df0f1745472c784e [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"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Host/Host.h"
18#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
96 return GetPrivateStopReason ();
Chris Lattner24943d22010-06-08 16:52:24 +000097}
98
Jim Ingham15dcb7c2011-01-20 02:03:18 +000099void
100Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
101{
102 m_actual_stop_info_sp = stop_info_sp;
103 m_thread_stop_reason_stop_id = GetProcess().GetStopID();
104}
105
106void
107Thread::SetStopInfoToNothing()
108{
109 // Note, we can't just NULL out the private reason, or the native thread implementation will try to
110 // go calculate it again. For now, just set it to a Unix Signal with an invalid signal number.
111 SetStopInfo (StopInfo::CreateStopReasonWithSignal (*this, LLDB_INVALID_SIGNAL_NUMBER));
112}
113
Chris Lattner24943d22010-06-08 16:52:24 +0000114bool
115Thread::ThreadStoppedForAReason (void)
116{
Greg Clayton643ee732010-08-04 01:40:35 +0000117 return GetPrivateStopReason () != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000118}
119
Jim Ingham15dcb7c2011-01-20 02:03:18 +0000120bool
121Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state)
122{
123 if (!SaveFrameZeroState(saved_state.register_backup))
124 return false;
125
126 saved_state.stop_info_sp = GetStopInfo();
127 saved_state.orig_stop_id = GetProcess().GetStopID();
128
129 return true;
130}
131
132bool
133Thread::RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state)
134{
135 RestoreSaveFrameZero(saved_state.register_backup);
136 saved_state.stop_info_sp->MakeStopInfoValid();
137 SetStopInfo(saved_state.stop_info_sp);
138 return true;
139}
140
Chris Lattner24943d22010-06-08 16:52:24 +0000141StateType
142Thread::GetState() const
143{
144 // If any other threads access this we will need a mutex for it
145 Mutex::Locker locker(m_state_mutex);
146 return m_state;
147}
148
149void
150Thread::SetState(StateType state)
151{
152 Mutex::Locker locker(m_state_mutex);
153 m_state = state;
154}
155
156void
157Thread::WillStop()
158{
159 ThreadPlan *current_plan = GetCurrentPlan();
160
161 // FIXME: I may decide to disallow threads with no plans. In which
162 // case this should go to an assert.
163
164 if (!current_plan)
165 return;
166
167 current_plan->WillStop();
168}
169
170void
171Thread::SetupForResume ()
172{
173 if (GetResumeState() != eStateSuspended)
174 {
175
176 // If we're at a breakpoint push the step-over breakpoint plan. Do this before
177 // telling the current plan it will resume, since we might change what the current
178 // plan is.
179
180 lldb::addr_t pc = GetRegisterContext()->GetPC();
181 BreakpointSiteSP bp_site_sp = GetProcess().GetBreakpointSiteList().FindByAddress(pc);
182 if (bp_site_sp && bp_site_sp->IsEnabled())
183 {
184 // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
185 // special to step over a breakpoint.
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000186
187 ThreadPlan *cur_plan = GetCurrentPlan();
Chris Lattner24943d22010-06-08 16:52:24 +0000188
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000189 if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
190 {
191 ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
192 if (step_bp_plan)
Chris Lattner24943d22010-06-08 16:52:24 +0000193 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000194 ThreadPlanSP step_bp_plan_sp;
195 step_bp_plan->SetPrivate (true);
196
Chris Lattner24943d22010-06-08 16:52:24 +0000197 if (GetCurrentPlan()->RunState() != eStateStepping)
198 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000199 step_bp_plan->SetAutoContinue(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000200 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000201 step_bp_plan_sp.reset (step_bp_plan);
Chris Lattner24943d22010-06-08 16:52:24 +0000202 QueueThreadPlan (step_bp_plan_sp, false);
203 }
204 }
205 }
206 }
207}
208
209bool
210Thread::WillResume (StateType resume_state)
211{
212 // At this point clear the completed plan stack.
213 m_completed_plan_stack.clear();
214 m_discarded_plan_stack.clear();
215
Greg Clayton643ee732010-08-04 01:40:35 +0000216 StopInfo *stop_info = GetPrivateStopReason().get();
217 if (stop_info)
218 stop_info->WillResume (resume_state);
Chris Lattner24943d22010-06-08 16:52:24 +0000219
220 // Tell all the plans that we are about to resume in case they need to clear any state.
221 // We distinguish between the plan on the top of the stack and the lower
222 // plans in case a plan needs to do any special business before it runs.
223
224 ThreadPlan *plan_ptr = GetCurrentPlan();
225 plan_ptr->WillResume(resume_state, true);
226
227 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
228 {
229 plan_ptr->WillResume (resume_state, false);
230 }
Greg Clayton643ee732010-08-04 01:40:35 +0000231
Greg Clayton643ee732010-08-04 01:40:35 +0000232 m_actual_stop_info_sp.reset();
Chris Lattner24943d22010-06-08 16:52:24 +0000233 return true;
234}
235
236void
237Thread::DidResume ()
238{
239 SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
240}
241
242bool
243Thread::ShouldStop (Event* event_ptr)
244{
245 ThreadPlan *current_plan = GetCurrentPlan();
246 bool should_stop = true;
247
Greg Claytone005f2c2010-11-06 01:53:30 +0000248 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000249 if (log)
250 {
251 StreamString s;
252 DumpThreadPlans(&s);
253 log->PutCString (s.GetData());
254 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000255
256 // The top most plan always gets to do the trace log...
257 current_plan->DoTraceLog ();
Chris Lattner24943d22010-06-08 16:52:24 +0000258
259 if (current_plan->PlanExplainsStop())
260 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000261 bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000262 while (1)
263 {
264 should_stop = current_plan->ShouldStop(event_ptr);
265 if (current_plan->MischiefManaged())
266 {
267 if (should_stop)
268 current_plan->WillStop();
269
270 // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
271 // Otherwise, see if the plan's parent wants to stop.
272
273 if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
274 {
275 PopPlan();
276 break;
277 }
278 else
279 {
280
281 PopPlan();
282
283 current_plan = GetCurrentPlan();
284 if (current_plan == NULL)
285 {
286 break;
287 }
288 }
289
290 }
291 else
292 {
293 break;
294 }
295 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000296 if (over_ride_stop)
297 should_stop = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000298 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000299 else if (current_plan->TracerExplainsStop())
300 {
301 return false;
302 }
Chris Lattner24943d22010-06-08 16:52:24 +0000303 else
304 {
305 // If the current plan doesn't explain the stop, then, find one that
306 // does and let it handle the situation.
307 ThreadPlan *plan_ptr = current_plan;
308 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
309 {
310 if (plan_ptr->PlanExplainsStop())
311 {
312 should_stop = plan_ptr->ShouldStop (event_ptr);
313 break;
314 }
315
316 }
317 }
318
319 return should_stop;
320}
321
322Vote
323Thread::ShouldReportStop (Event* event_ptr)
324{
325 StateType thread_state = GetResumeState ();
Greg Claytone005f2c2010-11-06 01:53:30 +0000326 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +0000327
328 if (thread_state == eStateSuspended || thread_state == eStateInvalid)
329 {
330 if (log)
331 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 +0000332 return eVoteNoOpinion;
Greg Clayton5205f0b2010-09-03 17:10:42 +0000333 }
Chris Lattner24943d22010-06-08 16:52:24 +0000334
335 if (m_completed_plan_stack.size() > 0)
336 {
337 // Don't use GetCompletedPlan here, since that suppresses private plans.
Greg Clayton5205f0b2010-09-03 17:10:42 +0000338 if (log)
339 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 +0000340 return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
341 }
342 else
Greg Clayton5205f0b2010-09-03 17:10:42 +0000343 {
344 if (log)
345 log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4x: returning vote for current plan\n", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000346 return GetCurrentPlan()->ShouldReportStop (event_ptr);
Greg Clayton5205f0b2010-09-03 17:10:42 +0000347 }
Chris Lattner24943d22010-06-08 16:52:24 +0000348}
349
350Vote
351Thread::ShouldReportRun (Event* event_ptr)
352{
353 StateType thread_state = GetResumeState ();
Jim Inghamac959662011-01-24 06:34:17 +0000354
Chris Lattner24943d22010-06-08 16:52:24 +0000355 if (thread_state == eStateSuspended
356 || thread_state == eStateInvalid)
Jim Inghamac959662011-01-24 06:34:17 +0000357 {
Chris Lattner24943d22010-06-08 16:52:24 +0000358 return eVoteNoOpinion;
Jim Inghamac959662011-01-24 06:34:17 +0000359 }
360
361 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000362 if (m_completed_plan_stack.size() > 0)
363 {
364 // Don't use GetCompletedPlan here, since that suppresses private plans.
Jim Inghamac959662011-01-24 06:34:17 +0000365 if (log)
366 log->Printf ("Current Plan for thread %d (0x%4.4x): %s being asked whether we should report run.",
367 GetIndexID(),
368 GetID(),
369 m_completed_plan_stack.back()->GetName());
370
Chris Lattner24943d22010-06-08 16:52:24 +0000371 return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
372 }
373 else
Jim Inghamac959662011-01-24 06:34:17 +0000374 {
375 if (log)
376 log->Printf ("Current Plan for thread %d (0x%4.4x): %s being asked whether we should report run.",
377 GetIndexID(),
378 GetID(),
379 GetCurrentPlan()->GetName());
380
Chris Lattner24943d22010-06-08 16:52:24 +0000381 return GetCurrentPlan()->ShouldReportRun (event_ptr);
Jim Inghamac959662011-01-24 06:34:17 +0000382 }
Chris Lattner24943d22010-06-08 16:52:24 +0000383}
384
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000385bool
386Thread::MatchesSpec (const ThreadSpec *spec)
387{
388 if (spec == NULL)
389 return true;
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000390
Jim Ingham649492b2010-06-18 01:00:58 +0000391 return spec->ThreadPassesBasicTests(this);
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000392}
393
Chris Lattner24943d22010-06-08 16:52:24 +0000394void
395Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
396{
397 if (thread_plan_sp)
398 {
Jim Ingham745ac7a2010-11-11 19:26:09 +0000399 // If the thread plan doesn't already have a tracer, give it its parent's tracer:
400 if (!thread_plan_sp->GetThreadPlanTracer())
401 thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
Jim Ingham6297a3a2010-10-20 00:39:53 +0000402 m_plan_stack.push_back (thread_plan_sp);
Jim Ingham745ac7a2010-11-11 19:26:09 +0000403
Chris Lattner24943d22010-06-08 16:52:24 +0000404 thread_plan_sp->DidPush();
405
Greg Claytone005f2c2010-11-06 01:53:30 +0000406 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000407 if (log)
408 {
409 StreamString s;
410 thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
Jim Ingham6297a3a2010-10-20 00:39:53 +0000411 log->Printf("Pushing plan: \"%s\", tid = 0x%4.4x.",
Chris Lattner24943d22010-06-08 16:52:24 +0000412 s.GetData(),
Jim Ingham6297a3a2010-10-20 00:39:53 +0000413 thread_plan_sp->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000414 }
415 }
416}
417
418void
419Thread::PopPlan ()
420{
Greg Claytone005f2c2010-11-06 01:53:30 +0000421 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000422
Jim Ingham6297a3a2010-10-20 00:39:53 +0000423 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000424 return;
425 else
426 {
427 ThreadPlanSP &plan = m_plan_stack.back();
428 if (log)
429 {
Jim Ingham83e8b9d2010-11-10 18:17:03 +0000430 log->Printf("Popping plan: \"%s\", tid = 0x%4.4x.", plan->GetName(), plan->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000431 }
432 m_completed_plan_stack.push_back (plan);
433 plan->WillPop();
434 m_plan_stack.pop_back();
435 }
436}
437
438void
439Thread::DiscardPlan ()
440{
441 if (m_plan_stack.size() > 1)
442 {
443 ThreadPlanSP &plan = m_plan_stack.back();
444 m_discarded_plan_stack.push_back (plan);
445 plan->WillPop();
446 m_plan_stack.pop_back();
447 }
448}
449
450ThreadPlan *
451Thread::GetCurrentPlan ()
452{
Jim Ingham6297a3a2010-10-20 00:39:53 +0000453 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000454 return NULL;
455 else
456 return m_plan_stack.back().get();
457}
458
459ThreadPlanSP
460Thread::GetCompletedPlan ()
461{
462 ThreadPlanSP empty_plan_sp;
463 if (!m_completed_plan_stack.empty())
464 {
465 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
466 {
467 ThreadPlanSP completed_plan_sp;
468 completed_plan_sp = m_completed_plan_stack[i];
469 if (!completed_plan_sp->GetPrivate ())
470 return completed_plan_sp;
471 }
472 }
473 return empty_plan_sp;
474}
475
476bool
477Thread::IsThreadPlanDone (ThreadPlan *plan)
478{
479 ThreadPlanSP empty_plan_sp;
480 if (!m_completed_plan_stack.empty())
481 {
482 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
483 {
484 if (m_completed_plan_stack[i].get() == plan)
485 return true;
486 }
487 }
488 return false;
489}
490
491bool
492Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
493{
494 ThreadPlanSP empty_plan_sp;
495 if (!m_discarded_plan_stack.empty())
496 {
497 for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
498 {
499 if (m_discarded_plan_stack[i].get() == plan)
500 return true;
501 }
502 }
503 return false;
504}
505
506ThreadPlan *
507Thread::GetPreviousPlan (ThreadPlan *current_plan)
508{
509 if (current_plan == NULL)
510 return NULL;
511
512 int stack_size = m_completed_plan_stack.size();
513 for (int i = stack_size - 1; i > 0; i--)
514 {
515 if (current_plan == m_completed_plan_stack[i].get())
516 return m_completed_plan_stack[i-1].get();
517 }
518
519 if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
520 {
Chris Lattner24943d22010-06-08 16:52:24 +0000521 if (m_plan_stack.size() > 0)
522 return m_plan_stack.back().get();
523 else
524 return NULL;
525 }
526
527 stack_size = m_plan_stack.size();
528 for (int i = stack_size - 1; i > 0; i--)
529 {
530 if (current_plan == m_plan_stack[i].get())
531 return m_plan_stack[i-1].get();
532 }
533 return NULL;
534}
535
536void
537Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
538{
539 if (abort_other_plans)
540 DiscardThreadPlans(true);
541
542 PushPlan (thread_plan_sp);
543}
544
Jim Ingham745ac7a2010-11-11 19:26:09 +0000545
546void
547Thread::EnableTracer (bool value, bool single_stepping)
548{
549 int stack_size = m_plan_stack.size();
550 for (int i = 0; i < stack_size; i++)
551 {
552 if (m_plan_stack[i]->GetThreadPlanTracer())
553 {
554 m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
555 m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
556 }
557 }
558}
559
560void
561Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
562{
563 int stack_size = m_plan_stack.size();
564 for (int i = 0; i < stack_size; i++)
565 m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
566}
567
Chris Lattner24943d22010-06-08 16:52:24 +0000568void
Jim Inghamea9d4262010-11-05 19:25:48 +0000569Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
570{
Greg Claytone005f2c2010-11-06 01:53:30 +0000571 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamea9d4262010-11-05 19:25:48 +0000572 if (log)
573 {
574 log->Printf("Discarding thread plans for thread tid = 0x%4.4x, up to %p", GetID(), up_to_plan_sp.get());
575 }
576
577 int stack_size = m_plan_stack.size();
578
579 // If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
580 // stack, and if so discard up to and including it.
581
582 if (up_to_plan_sp.get() == NULL)
583 {
584 for (int i = stack_size - 1; i > 0; i--)
585 DiscardPlan();
586 }
587 else
588 {
589 bool found_it = false;
590 for (int i = stack_size - 1; i > 0; i--)
591 {
592 if (m_plan_stack[i] == up_to_plan_sp)
593 found_it = true;
594 }
595 if (found_it)
596 {
597 bool last_one = false;
598 for (int i = stack_size - 1; i > 0 && !last_one ; i--)
599 {
600 if (GetCurrentPlan() == up_to_plan_sp.get())
601 last_one = true;
602 DiscardPlan();
603 }
604 }
605 }
606 return;
607}
608
609void
Chris Lattner24943d22010-06-08 16:52:24 +0000610Thread::DiscardThreadPlans(bool force)
611{
Greg Claytone005f2c2010-11-06 01:53:30 +0000612 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000613 if (log)
614 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000615 log->Printf("Discarding thread plans for thread (tid = 0x%4.4x, force %d)", GetID(), force);
Chris Lattner24943d22010-06-08 16:52:24 +0000616 }
617
618 if (force)
619 {
620 int stack_size = m_plan_stack.size();
621 for (int i = stack_size - 1; i > 0; i--)
622 {
623 DiscardPlan();
624 }
625 return;
626 }
627
628 while (1)
629 {
630
631 int master_plan_idx;
632 bool discard;
633
634 // Find the first master plan, see if it wants discarding, and if yes discard up to it.
635 for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
636 {
637 if (m_plan_stack[master_plan_idx]->IsMasterPlan())
638 {
639 discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
640 break;
641 }
642 }
643
644 if (discard)
645 {
646 // First pop all the dependent plans:
647 for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
648 {
649
650 // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
651 // for the plan leaves it in a state that it is safe to pop the plan
652 // with no more notice?
653 DiscardPlan();
654 }
655
656 // Now discard the master plan itself.
657 // The bottom-most plan never gets discarded. "OkayToDiscard" for it means
658 // discard it's dependent plans, but not it...
659 if (master_plan_idx > 0)
660 {
661 DiscardPlan();
662 }
663 }
664 else
665 {
666 // If the master plan doesn't want to get discarded, then we're done.
667 break;
668 }
669
670 }
Chris Lattner24943d22010-06-08 16:52:24 +0000671}
672
673ThreadPlan *
674Thread::QueueFundamentalPlan (bool abort_other_plans)
675{
676 ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
677 QueueThreadPlan (thread_plan_sp, abort_other_plans);
678 return thread_plan_sp.get();
679}
680
681ThreadPlan *
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000682Thread::QueueThreadPlanForStepSingleInstruction
683(
684 bool step_over,
685 bool abort_other_plans,
686 bool stop_other_threads
687)
Chris Lattner24943d22010-06-08 16:52:24 +0000688{
689 ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
690 QueueThreadPlan (thread_plan_sp, abort_other_plans);
691 return thread_plan_sp.get();
692}
693
694ThreadPlan *
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000695Thread::QueueThreadPlanForStepRange
696(
697 bool abort_other_plans,
698 StepType type,
699 const AddressRange &range,
700 const SymbolContext &addr_context,
701 lldb::RunMode stop_other_threads,
702 bool avoid_code_without_debug_info
703)
Chris Lattner24943d22010-06-08 16:52:24 +0000704{
705 ThreadPlanSP thread_plan_sp;
706 if (type == eStepTypeInto)
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000707 {
708 ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
709 if (avoid_code_without_debug_info)
710 plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
711 else
712 plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
713 thread_plan_sp.reset (plan);
714 }
Chris Lattner24943d22010-06-08 16:52:24 +0000715 else
716 thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
717
718 QueueThreadPlan (thread_plan_sp, abort_other_plans);
719 return thread_plan_sp.get();
720}
721
722
723ThreadPlan *
724Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
725{
726 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
727 QueueThreadPlan (thread_plan_sp, abort_other_plans);
728 return thread_plan_sp.get();
729}
730
731ThreadPlan *
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000732Thread::QueueThreadPlanForStepOut
733(
734 bool abort_other_plans,
735 SymbolContext *addr_context,
736 bool first_insn,
737 bool stop_other_threads,
738 Vote stop_vote,
739 Vote run_vote,
740 uint32_t frame_idx
741)
Chris Lattner24943d22010-06-08 16:52:24 +0000742{
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000743 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this,
744 addr_context,
745 first_insn,
746 stop_other_threads,
747 stop_vote,
748 run_vote,
749 frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000750 QueueThreadPlan (thread_plan_sp, abort_other_plans);
751 return thread_plan_sp.get();
752}
753
754ThreadPlan *
755Thread::QueueThreadPlanForStepThrough (bool abort_other_plans, bool stop_other_threads)
756{
Jim Inghamb66cd072010-09-28 01:25:32 +0000757 // Try the dynamic loader first:
Chris Lattner24943d22010-06-08 16:52:24 +0000758 ThreadPlanSP thread_plan_sp(GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (*this, stop_other_threads));
Jim Inghamb66cd072010-09-28 01:25:32 +0000759 // If that didn't come up with anything, try the ObjC runtime plugin:
760 if (thread_plan_sp.get() == NULL)
761 {
762 ObjCLanguageRuntime *objc_runtime = GetProcess().GetObjCLanguageRuntime();
763 if (objc_runtime)
764 thread_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (*this, stop_other_threads);
765 }
766
Chris Lattner24943d22010-06-08 16:52:24 +0000767 if (thread_plan_sp.get() == NULL)
768 {
769 thread_plan_sp.reset(new ThreadPlanStepThrough (*this, stop_other_threads));
770 if (thread_plan_sp && !thread_plan_sp->ValidatePlan (NULL))
Greg Claytonf8e98a62010-07-23 15:37:46 +0000771 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000772 }
773 QueueThreadPlan (thread_plan_sp, abort_other_plans);
774 return thread_plan_sp.get();
775}
776
777ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000778Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
779 Address& function,
780 lldb::addr_t arg,
781 bool stop_other_threads,
782 bool discard_on_error)
783{
784 ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
785 QueueThreadPlan (thread_plan_sp, abort_other_plans);
786 return thread_plan_sp.get();
787}
788
789ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000790Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
791 Address &target_addr,
792 bool stop_other_threads)
793{
794 ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
795 QueueThreadPlan (thread_plan_sp, abort_other_plans);
796 return thread_plan_sp.get();
797}
798
799ThreadPlan *
800Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000801 lldb::addr_t *address_list,
802 size_t num_addresses,
803 bool stop_other_threads,
804 uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000805{
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000806 ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads, frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000807 QueueThreadPlan (thread_plan_sp, abort_other_plans);
808 return thread_plan_sp.get();
809
810}
811
812uint32_t
813Thread::GetIndexID () const
814{
815 return m_index_id;
816}
817
818void
819Thread::DumpThreadPlans (lldb_private::Stream *s) const
820{
821 uint32_t stack_size = m_plan_stack.size();
Greg Claytonf04d6612010-09-03 22:45:01 +0000822 int i;
823 s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4x, stack_size = %d\n", GetIndexID(), GetID(), stack_size);
824 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000825 {
826 s->Printf ("Element %d: ", i);
827 s->IndentMore();
828 m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
829 s->IndentLess();
830 s->EOL();
831 }
832
Chris Lattner24943d22010-06-08 16:52:24 +0000833 stack_size = m_completed_plan_stack.size();
834 s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
Greg Claytonf04d6612010-09-03 22:45:01 +0000835 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000836 {
837 s->Printf ("Element %d: ", i);
838 s->IndentMore();
839 m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
840 s->IndentLess();
841 s->EOL();
842 }
843
844 stack_size = m_discarded_plan_stack.size();
845 s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
Greg Claytonf04d6612010-09-03 22:45:01 +0000846 for (int i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000847 {
848 s->Printf ("Element %d: ", i);
849 s->IndentMore();
850 m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
851 s->IndentLess();
852 s->EOL();
853 }
854
855}
856
857Target *
858Thread::CalculateTarget ()
859{
860 return m_process.CalculateTarget();
861}
862
863Process *
864Thread::CalculateProcess ()
865{
866 return &m_process;
867}
868
869Thread *
870Thread::CalculateThread ()
871{
872 return this;
873}
874
875StackFrame *
876Thread::CalculateStackFrame ()
877{
878 return NULL;
879}
880
881void
Greg Claytona830adb2010-10-04 01:05:56 +0000882Thread::CalculateExecutionContext (ExecutionContext &exe_ctx)
Chris Lattner24943d22010-06-08 16:52:24 +0000883{
Greg Claytona830adb2010-10-04 01:05:56 +0000884 m_process.CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000885 exe_ctx.thread = this;
886 exe_ctx.frame = NULL;
887}
888
Greg Clayton782b9cc2010-08-25 00:35:26 +0000889
890StackFrameList &
891Thread::GetStackFrameList ()
892{
Greg Claytonf40e3082010-08-26 02:28:22 +0000893 if (m_curr_frames_ap.get() == NULL)
Greg Clayton5205f0b2010-09-03 17:10:42 +0000894 m_curr_frames_ap.reset (new StackFrameList (*this, m_prev_frames_sp, true));
Greg Claytonf40e3082010-08-26 02:28:22 +0000895 return *m_curr_frames_ap;
Greg Clayton782b9cc2010-08-25 00:35:26 +0000896}
897
898
899
Jim Ingham71219082010-08-12 02:14:28 +0000900uint32_t
901Thread::GetStackFrameCount()
902{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000903 return GetStackFrameList().GetNumFrames();
904}
Greg Clayton33ed1702010-08-24 00:45:41 +0000905
Greg Clayton33ed1702010-08-24 00:45:41 +0000906
Greg Clayton782b9cc2010-08-25 00:35:26 +0000907void
908Thread::ClearStackFrames ()
909{
Greg Clayton5205f0b2010-09-03 17:10:42 +0000910 if (m_curr_frames_ap.get() && m_curr_frames_ap->GetNumFrames (false) > 1)
911 m_prev_frames_sp.reset (m_curr_frames_ap.release());
912 else
913 m_curr_frames_ap.release();
914
915// StackFrameList::Merge (m_curr_frames_ap, m_prev_frames_sp);
916// assert (m_curr_frames_ap.get() == NULL);
Jim Ingham71219082010-08-12 02:14:28 +0000917}
918
919lldb::StackFrameSP
920Thread::GetStackFrameAtIndex (uint32_t idx)
921{
Greg Clayton72b71582010-09-02 21:44:10 +0000922 return GetStackFrameList().GetFrameAtIndex(idx);
Jim Ingham71219082010-08-12 02:14:28 +0000923}
924
Greg Claytonc12b6b42010-10-10 22:28:11 +0000925uint32_t
926Thread::GetSelectedFrameIndex ()
927{
928 return GetStackFrameList().GetSelectedFrameIndex();
929}
930
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000931lldb::StackFrameSP
932Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
933{
934 return GetStackFrameList().GetFrameWithConcreteFrameIndex (unwind_idx);
935}
936
937
Greg Claytonc12b6b42010-10-10 22:28:11 +0000938
Chris Lattner24943d22010-06-08 16:52:24 +0000939lldb::StackFrameSP
Jim Inghamc8332952010-08-26 21:32:51 +0000940Thread::GetSelectedFrame ()
Chris Lattner24943d22010-06-08 16:52:24 +0000941{
Jim Inghamc8332952010-08-26 21:32:51 +0000942 return GetStackFrameAtIndex (GetStackFrameList().GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000943}
944
945uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000946Thread::SetSelectedFrame (lldb_private::StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000947{
Jim Inghamc8332952010-08-26 21:32:51 +0000948 return GetStackFrameList().SetSelectedFrame(frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000949}
950
951void
Jim Inghamc8332952010-08-26 21:32:51 +0000952Thread::SetSelectedFrameByIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000953{
Jim Inghamc8332952010-08-26 21:32:51 +0000954 GetStackFrameList().SetSelectedFrameByIndex(idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000955}
956
957void
Greg Claytona830adb2010-10-04 01:05:56 +0000958Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000959{
Greg Claytona830adb2010-10-04 01:05:56 +0000960 ExecutionContext exe_ctx;
961 SymbolContext frame_sc;
962 CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000963
Greg Claytona830adb2010-10-04 01:05:56 +0000964 if (frame_idx != LLDB_INVALID_INDEX32)
Chris Lattner24943d22010-06-08 16:52:24 +0000965 {
Greg Claytona830adb2010-10-04 01:05:56 +0000966 StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000967 if (frame_sp)
968 {
Greg Claytona830adb2010-10-04 01:05:56 +0000969 exe_ctx.frame = frame_sp.get();
970 frame_sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
Chris Lattner24943d22010-06-08 16:52:24 +0000971 }
972 }
973
Greg Claytona830adb2010-10-04 01:05:56 +0000974 const char *thread_format = GetProcess().GetTarget().GetDebugger().GetThreadFormat();
975 assert (thread_format);
976 const char *end = NULL;
977 Debugger::FormatPrompt (thread_format,
978 exe_ctx.frame ? &frame_sc : NULL,
979 &exe_ctx,
980 NULL,
981 strm,
982 &end);
Chris Lattner24943d22010-06-08 16:52:24 +0000983}
984
985lldb::ThreadSP
986Thread::GetSP ()
987{
988 return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
989}
Jim Ingham20594b12010-09-08 03:14:33 +0000990
Greg Clayton990de7b2010-11-18 23:32:35 +0000991
992void
993Thread::Initialize ()
Jim Ingham20594b12010-09-08 03:14:33 +0000994{
Greg Clayton990de7b2010-11-18 23:32:35 +0000995 UserSettingsControllerSP &usc = GetSettingsController();
996 usc.reset (new SettingsController);
997 UserSettingsController::InitializeSettingsController (usc,
998 SettingsController::global_settings_table,
999 SettingsController::instance_settings_table);
1000}
Jim Ingham20594b12010-09-08 03:14:33 +00001001
Greg Clayton990de7b2010-11-18 23:32:35 +00001002void
1003Thread::Terminate ()
1004{
1005 UserSettingsControllerSP &usc = GetSettingsController();
1006 UserSettingsController::FinalizeSettingsController (usc);
1007 usc.reset();
1008}
Jim Ingham20594b12010-09-08 03:14:33 +00001009
Greg Clayton990de7b2010-11-18 23:32:35 +00001010UserSettingsControllerSP &
1011Thread::GetSettingsController ()
1012{
1013 static UserSettingsControllerSP g_settings_controller;
Jim Ingham20594b12010-09-08 03:14:33 +00001014 return g_settings_controller;
1015}
1016
Caroline Tice1ebef442010-09-27 00:30:10 +00001017void
1018Thread::UpdateInstanceName ()
1019{
1020 StreamString sstr;
1021 const char *name = GetName();
1022
1023 if (name && name[0] != '\0')
1024 sstr.Printf ("%s", name);
1025 else if ((GetIndexID() != 0) || (GetID() != 0))
1026 sstr.Printf ("0x%4.4x", GetIndexID(), GetID());
1027
1028 if (sstr.GetSize() > 0)
1029 Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
1030}
1031
Jim Inghamccd584d2010-09-23 17:40:12 +00001032lldb::StackFrameSP
1033Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
1034{
1035 return GetStackFrameList().GetStackFrameSPForStackFramePtr (stack_frame_ptr);
1036}
Caroline Tice7826c882010-10-26 03:11:13 +00001037
1038const char *
1039Thread::StopReasonAsCString (lldb::StopReason reason)
1040{
1041 switch (reason)
1042 {
1043 case eStopReasonInvalid: return "invalid";
1044 case eStopReasonNone: return "none";
1045 case eStopReasonTrace: return "trace";
1046 case eStopReasonBreakpoint: return "breakpoint";
1047 case eStopReasonWatchpoint: return "watchpoint";
1048 case eStopReasonSignal: return "signal";
1049 case eStopReasonException: return "exception";
1050 case eStopReasonPlanComplete: return "plan complete";
1051 }
1052
1053
1054 static char unknown_state_string[64];
1055 snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
1056 return unknown_state_string;
1057}
1058
1059const char *
1060Thread::RunModeAsCString (lldb::RunMode mode)
1061{
1062 switch (mode)
1063 {
1064 case eOnlyThisThread: return "only this thread";
1065 case eAllThreads: return "all threads";
1066 case eOnlyDuringStepping: return "only during stepping";
1067 }
1068
1069 static char unknown_state_string[64];
1070 snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
1071 return unknown_state_string;
1072}
Jim Ingham745ac7a2010-11-11 19:26:09 +00001073
Greg Clayton990de7b2010-11-18 23:32:35 +00001074#pragma mark "Thread::SettingsController"
Jim Ingham745ac7a2010-11-11 19:26:09 +00001075//--------------------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001076// class Thread::SettingsController
Jim Ingham745ac7a2010-11-11 19:26:09 +00001077//--------------------------------------------------------------
1078
Greg Clayton990de7b2010-11-18 23:32:35 +00001079Thread::SettingsController::SettingsController () :
Jim Ingham745ac7a2010-11-11 19:26:09 +00001080 UserSettingsController ("thread", Process::GetSettingsController())
1081{
1082 m_default_settings.reset (new ThreadInstanceSettings (*this, false,
1083 InstanceSettings::GetDefaultName().AsCString()));
1084}
1085
Greg Clayton990de7b2010-11-18 23:32:35 +00001086Thread::SettingsController::~SettingsController ()
Jim Ingham745ac7a2010-11-11 19:26:09 +00001087{
1088}
1089
1090lldb::InstanceSettingsSP
Greg Clayton990de7b2010-11-18 23:32:35 +00001091Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
Jim Ingham745ac7a2010-11-11 19:26:09 +00001092{
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001093 ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*GetSettingsController(),
1094 false,
1095 instance_name);
Jim Ingham745ac7a2010-11-11 19:26:09 +00001096 lldb::InstanceSettingsSP new_settings_sp (new_settings);
1097 return new_settings_sp;
1098}
1099
1100#pragma mark "ThreadInstanceSettings"
1101//--------------------------------------------------------------
1102// class ThreadInstanceSettings
1103//--------------------------------------------------------------
1104
1105ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
Greg Clayton638351a2010-12-04 00:10:17 +00001106 InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001107 m_avoid_regexp_ap (),
1108 m_trace_enabled (false)
1109{
1110 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
1111 // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
1112 // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
1113 // This is true for CreateInstanceName() too.
1114
1115 if (GetInstanceName() == InstanceSettings::InvalidName())
1116 {
1117 ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
1118 m_owner.RegisterInstanceSettings (this);
1119 }
1120
1121 if (live_instance)
1122 {
1123 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1124 CopyInstanceSettings (pending_settings,false);
1125 //m_owner.RemovePendingSettings (m_instance_name);
1126 }
1127}
1128
1129ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001130 InstanceSettings (*Thread::GetSettingsController(), CreateInstanceName().AsCString()),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001131 m_avoid_regexp_ap (),
1132 m_trace_enabled (rhs.m_trace_enabled)
1133{
1134 if (m_instance_name != InstanceSettings::GetDefaultName())
1135 {
1136 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1137 CopyInstanceSettings (pending_settings,false);
1138 m_owner.RemovePendingSettings (m_instance_name);
1139 }
1140 if (rhs.m_avoid_regexp_ap.get() != NULL)
1141 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1142}
1143
1144ThreadInstanceSettings::~ThreadInstanceSettings ()
1145{
1146}
1147
1148ThreadInstanceSettings&
1149ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
1150{
1151 if (this != &rhs)
1152 {
1153 if (rhs.m_avoid_regexp_ap.get() != NULL)
1154 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1155 else
1156 m_avoid_regexp_ap.reset(NULL);
1157 }
1158 m_trace_enabled = rhs.m_trace_enabled;
1159 return *this;
1160}
1161
1162
1163void
1164ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
1165 const char *index_value,
1166 const char *value,
1167 const ConstString &instance_name,
1168 const SettingEntry &entry,
1169 lldb::VarSetOperationType op,
1170 Error &err,
1171 bool pending)
1172{
1173 if (var_name == StepAvoidRegexpVarName())
1174 {
1175 std::string regexp_text;
1176 if (m_avoid_regexp_ap.get() != NULL)
1177 regexp_text.append (m_avoid_regexp_ap->GetText());
1178 UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
1179 if (regexp_text.empty())
1180 m_avoid_regexp_ap.reset();
1181 else
1182 {
1183 m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
1184
1185 }
1186 }
1187 else if (var_name == GetTraceThreadVarName())
1188 {
1189 bool success;
1190 bool result = Args::StringToBoolean(value, false, &success);
1191
1192 if (success)
1193 {
1194 m_trace_enabled = result;
1195 if (!pending)
1196 {
1197 Thread *myself = static_cast<Thread *> (this);
1198 myself->EnableTracer(m_trace_enabled, true);
1199 }
1200 }
1201 else
1202 {
1203 err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
1204 }
1205
1206 }
1207}
1208
1209void
1210ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
1211 bool pending)
1212{
1213 if (new_settings.get() == NULL)
1214 return;
1215
1216 ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
1217 if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
1218 m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
1219 else
1220 m_avoid_regexp_ap.reset ();
1221}
1222
1223bool
1224ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
1225 const ConstString &var_name,
1226 StringList &value,
1227 Error *err)
1228{
1229 if (var_name == StepAvoidRegexpVarName())
1230 {
1231 if (m_avoid_regexp_ap.get() != NULL)
1232 {
1233 std::string regexp_text("\"");
1234 regexp_text.append(m_avoid_regexp_ap->GetText());
1235 regexp_text.append ("\"");
1236 value.AppendString (regexp_text.c_str());
1237 }
1238
1239 }
1240 else if (var_name == GetTraceThreadVarName())
1241 {
1242 value.AppendString(m_trace_enabled ? "true" : "false");
1243 }
1244 else
1245 {
1246 if (err)
1247 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
1248 return false;
1249 }
1250 return true;
1251}
1252
1253const ConstString
1254ThreadInstanceSettings::CreateInstanceName ()
1255{
1256 static int instance_count = 1;
1257 StreamString sstr;
1258
1259 sstr.Printf ("thread_%d", instance_count);
1260 ++instance_count;
1261
1262 const ConstString ret_val (sstr.GetData());
1263 return ret_val;
1264}
1265
1266const ConstString &
1267ThreadInstanceSettings::StepAvoidRegexpVarName ()
1268{
1269 static ConstString step_avoid_var_name ("step-avoid-regexp");
1270
1271 return step_avoid_var_name;
1272}
1273
1274const ConstString &
1275ThreadInstanceSettings::GetTraceThreadVarName ()
1276{
1277 static ConstString trace_thread_var_name ("trace-thread");
1278
1279 return trace_thread_var_name;
1280}
1281
1282//--------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001283// SettingsController Variable Tables
Jim Ingham745ac7a2010-11-11 19:26:09 +00001284//--------------------------------------------------
1285
1286SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001287Thread::SettingsController::global_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001288{
1289 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
1290 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1291};
1292
1293
1294SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001295Thread::SettingsController::instance_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001296{
1297 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
1298 { "step-avoid-regexp", eSetVarTypeString, "", NULL, false, false, "A regular expression defining functions step-in won't stop in." },
1299 { "trace-thread", eSetVarTypeBoolean, "false", NULL, false, false, "If true, this thread will single-step and log execution." },
1300 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1301};