blob: ed747646209e7c6a2f3dca735ba6d04b8c66a54d [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 (),
58 m_destroy_called (false)
Jim Ingham71219082010-08-12 02:14:28 +000059
Chris Lattner24943d22010-06-08 16:52:24 +000060{
Greg Claytone005f2c2010-11-06 01:53:30 +000061 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner24943d22010-06-08 16:52:24 +000062 if (log)
63 log->Printf ("%p Thread::Thread(tid = 0x%4.4x)", this, GetID());
64
65 QueueFundamentalPlan(true);
Caroline Tice1ebef442010-09-27 00:30:10 +000066 UpdateInstanceName();
Chris Lattner24943d22010-06-08 16:52:24 +000067}
68
69
70Thread::~Thread()
71{
Greg Claytone005f2c2010-11-06 01:53:30 +000072 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner24943d22010-06-08 16:52:24 +000073 if (log)
74 log->Printf ("%p Thread::~Thread(tid = 0x%4.4x)", this, GetID());
Jim Inghamcdea2362010-11-18 02:47:07 +000075 /// If you hit this assert, it means your derived class forgot to call DoDestroy in its destructor.
76 assert (m_destroy_called);
77}
78
79void
80Thread::DestroyThread ()
81{
82 m_plan_stack.clear();
83 m_discarded_plan_stack.clear();
84 m_completed_plan_stack.clear();
85 m_destroy_called = true;
Chris Lattner24943d22010-06-08 16:52:24 +000086}
87
88int
89Thread::GetResumeSignal () const
90{
91 return m_resume_signal;
92}
93
94void
95Thread::SetResumeSignal (int signal)
96{
97 m_resume_signal = signal;
98}
99
100StateType
101Thread::GetResumeState () const
102{
103 return m_resume_state;
104}
105
106void
107Thread::SetResumeState (StateType state)
108{
109 m_resume_state = state;
110}
111
Jim Ingham6297a3a2010-10-20 00:39:53 +0000112lldb::StopInfoSP
Greg Clayton643ee732010-08-04 01:40:35 +0000113Thread::GetStopInfo ()
Chris Lattner24943d22010-06-08 16:52:24 +0000114{
Jim Ingham6297a3a2010-10-20 00:39:53 +0000115 ThreadPlanSP plan_sp (GetCompletedPlan());
116 if (plan_sp)
117 return StopInfo::CreateStopReasonWithPlan (plan_sp);
118 else
119 return GetPrivateStopReason ();
Chris Lattner24943d22010-06-08 16:52:24 +0000120}
121
122bool
123Thread::ThreadStoppedForAReason (void)
124{
Greg Clayton643ee732010-08-04 01:40:35 +0000125 return GetPrivateStopReason () != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000126}
127
128StateType
129Thread::GetState() const
130{
131 // If any other threads access this we will need a mutex for it
132 Mutex::Locker locker(m_state_mutex);
133 return m_state;
134}
135
136void
137Thread::SetState(StateType state)
138{
139 Mutex::Locker locker(m_state_mutex);
140 m_state = state;
141}
142
143void
144Thread::WillStop()
145{
146 ThreadPlan *current_plan = GetCurrentPlan();
147
148 // FIXME: I may decide to disallow threads with no plans. In which
149 // case this should go to an assert.
150
151 if (!current_plan)
152 return;
153
154 current_plan->WillStop();
155}
156
157void
158Thread::SetupForResume ()
159{
160 if (GetResumeState() != eStateSuspended)
161 {
162
163 // If we're at a breakpoint push the step-over breakpoint plan. Do this before
164 // telling the current plan it will resume, since we might change what the current
165 // plan is.
166
167 lldb::addr_t pc = GetRegisterContext()->GetPC();
168 BreakpointSiteSP bp_site_sp = GetProcess().GetBreakpointSiteList().FindByAddress(pc);
169 if (bp_site_sp && bp_site_sp->IsEnabled())
170 {
171 // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
172 // special to step over a breakpoint.
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000173
174 ThreadPlan *cur_plan = GetCurrentPlan();
Chris Lattner24943d22010-06-08 16:52:24 +0000175
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000176 if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
177 {
178 ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
179 if (step_bp_plan)
Chris Lattner24943d22010-06-08 16:52:24 +0000180 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000181 ThreadPlanSP step_bp_plan_sp;
182 step_bp_plan->SetPrivate (true);
183
Chris Lattner24943d22010-06-08 16:52:24 +0000184 if (GetCurrentPlan()->RunState() != eStateStepping)
185 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000186 step_bp_plan->SetAutoContinue(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000187 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000188 step_bp_plan_sp.reset (step_bp_plan);
Chris Lattner24943d22010-06-08 16:52:24 +0000189 QueueThreadPlan (step_bp_plan_sp, false);
190 }
191 }
192 }
193 }
194}
195
196bool
197Thread::WillResume (StateType resume_state)
198{
199 // At this point clear the completed plan stack.
200 m_completed_plan_stack.clear();
201 m_discarded_plan_stack.clear();
202
Greg Clayton643ee732010-08-04 01:40:35 +0000203 StopInfo *stop_info = GetPrivateStopReason().get();
204 if (stop_info)
205 stop_info->WillResume (resume_state);
Chris Lattner24943d22010-06-08 16:52:24 +0000206
207 // Tell all the plans that we are about to resume in case they need to clear any state.
208 // We distinguish between the plan on the top of the stack and the lower
209 // plans in case a plan needs to do any special business before it runs.
210
211 ThreadPlan *plan_ptr = GetCurrentPlan();
212 plan_ptr->WillResume(resume_state, true);
213
214 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
215 {
216 plan_ptr->WillResume (resume_state, false);
217 }
Greg Clayton643ee732010-08-04 01:40:35 +0000218
Greg Clayton643ee732010-08-04 01:40:35 +0000219 m_actual_stop_info_sp.reset();
Chris Lattner24943d22010-06-08 16:52:24 +0000220 return true;
221}
222
223void
224Thread::DidResume ()
225{
226 SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
227}
228
229bool
230Thread::ShouldStop (Event* event_ptr)
231{
232 ThreadPlan *current_plan = GetCurrentPlan();
233 bool should_stop = true;
234
Greg Claytone005f2c2010-11-06 01:53:30 +0000235 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000236 if (log)
237 {
238 StreamString s;
239 DumpThreadPlans(&s);
240 log->PutCString (s.GetData());
241 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000242
243 // The top most plan always gets to do the trace log...
244 current_plan->DoTraceLog ();
Chris Lattner24943d22010-06-08 16:52:24 +0000245
246 if (current_plan->PlanExplainsStop())
247 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000248 bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000249 while (1)
250 {
251 should_stop = current_plan->ShouldStop(event_ptr);
252 if (current_plan->MischiefManaged())
253 {
254 if (should_stop)
255 current_plan->WillStop();
256
257 // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
258 // Otherwise, see if the plan's parent wants to stop.
259
260 if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
261 {
262 PopPlan();
263 break;
264 }
265 else
266 {
267
268 PopPlan();
269
270 current_plan = GetCurrentPlan();
271 if (current_plan == NULL)
272 {
273 break;
274 }
275 }
276
277 }
278 else
279 {
280 break;
281 }
282 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000283 if (over_ride_stop)
284 should_stop = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000285 }
Jim Ingham745ac7a2010-11-11 19:26:09 +0000286 else if (current_plan->TracerExplainsStop())
287 {
288 return false;
289 }
Chris Lattner24943d22010-06-08 16:52:24 +0000290 else
291 {
292 // If the current plan doesn't explain the stop, then, find one that
293 // does and let it handle the situation.
294 ThreadPlan *plan_ptr = current_plan;
295 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
296 {
297 if (plan_ptr->PlanExplainsStop())
298 {
299 should_stop = plan_ptr->ShouldStop (event_ptr);
300 break;
301 }
302
303 }
304 }
305
306 return should_stop;
307}
308
309Vote
310Thread::ShouldReportStop (Event* event_ptr)
311{
312 StateType thread_state = GetResumeState ();
Greg Claytone005f2c2010-11-06 01:53:30 +0000313 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Greg Clayton5205f0b2010-09-03 17:10:42 +0000314
315 if (thread_state == eStateSuspended || thread_state == eStateInvalid)
316 {
317 if (log)
318 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 +0000319 return eVoteNoOpinion;
Greg Clayton5205f0b2010-09-03 17:10:42 +0000320 }
Chris Lattner24943d22010-06-08 16:52:24 +0000321
322 if (m_completed_plan_stack.size() > 0)
323 {
324 // Don't use GetCompletedPlan here, since that suppresses private plans.
Greg Clayton5205f0b2010-09-03 17:10:42 +0000325 if (log)
326 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 +0000327 return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
328 }
329 else
Greg Clayton5205f0b2010-09-03 17:10:42 +0000330 {
331 if (log)
332 log->Printf ("Thread::ShouldReportStop() tid = 0x%4.4x: returning vote for current plan\n", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000333 return GetCurrentPlan()->ShouldReportStop (event_ptr);
Greg Clayton5205f0b2010-09-03 17:10:42 +0000334 }
Chris Lattner24943d22010-06-08 16:52:24 +0000335}
336
337Vote
338Thread::ShouldReportRun (Event* event_ptr)
339{
340 StateType thread_state = GetResumeState ();
341 if (thread_state == eStateSuspended
342 || thread_state == eStateInvalid)
343 return eVoteNoOpinion;
344
345 if (m_completed_plan_stack.size() > 0)
346 {
347 // Don't use GetCompletedPlan here, since that suppresses private plans.
348 return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
349 }
350 else
351 return GetCurrentPlan()->ShouldReportRun (event_ptr);
352}
353
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000354bool
355Thread::MatchesSpec (const ThreadSpec *spec)
356{
357 if (spec == NULL)
358 return true;
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000359
Jim Ingham649492b2010-06-18 01:00:58 +0000360 return spec->ThreadPassesBasicTests(this);
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000361}
362
Chris Lattner24943d22010-06-08 16:52:24 +0000363void
364Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
365{
366 if (thread_plan_sp)
367 {
Jim Ingham745ac7a2010-11-11 19:26:09 +0000368 // If the thread plan doesn't already have a tracer, give it its parent's tracer:
369 if (!thread_plan_sp->GetThreadPlanTracer())
370 thread_plan_sp->SetThreadPlanTracer(m_plan_stack.back()->GetThreadPlanTracer());
Jim Ingham6297a3a2010-10-20 00:39:53 +0000371 m_plan_stack.push_back (thread_plan_sp);
Jim Ingham745ac7a2010-11-11 19:26:09 +0000372
Chris Lattner24943d22010-06-08 16:52:24 +0000373 thread_plan_sp->DidPush();
374
Greg Claytone005f2c2010-11-06 01:53:30 +0000375 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000376 if (log)
377 {
378 StreamString s;
379 thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
Jim Ingham6297a3a2010-10-20 00:39:53 +0000380 log->Printf("Pushing plan: \"%s\", tid = 0x%4.4x.",
Chris Lattner24943d22010-06-08 16:52:24 +0000381 s.GetData(),
Jim Ingham6297a3a2010-10-20 00:39:53 +0000382 thread_plan_sp->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000383 }
384 }
385}
386
387void
388Thread::PopPlan ()
389{
Greg Claytone005f2c2010-11-06 01:53:30 +0000390 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000391
Jim Ingham6297a3a2010-10-20 00:39:53 +0000392 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000393 return;
394 else
395 {
396 ThreadPlanSP &plan = m_plan_stack.back();
397 if (log)
398 {
Jim Ingham83e8b9d2010-11-10 18:17:03 +0000399 log->Printf("Popping plan: \"%s\", tid = 0x%4.4x.", plan->GetName(), plan->GetThread().GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000400 }
401 m_completed_plan_stack.push_back (plan);
402 plan->WillPop();
403 m_plan_stack.pop_back();
404 }
405}
406
407void
408Thread::DiscardPlan ()
409{
410 if (m_plan_stack.size() > 1)
411 {
412 ThreadPlanSP &plan = m_plan_stack.back();
413 m_discarded_plan_stack.push_back (plan);
414 plan->WillPop();
415 m_plan_stack.pop_back();
416 }
417}
418
419ThreadPlan *
420Thread::GetCurrentPlan ()
421{
Jim Ingham6297a3a2010-10-20 00:39:53 +0000422 if (m_plan_stack.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000423 return NULL;
424 else
425 return m_plan_stack.back().get();
426}
427
428ThreadPlanSP
429Thread::GetCompletedPlan ()
430{
431 ThreadPlanSP empty_plan_sp;
432 if (!m_completed_plan_stack.empty())
433 {
434 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
435 {
436 ThreadPlanSP completed_plan_sp;
437 completed_plan_sp = m_completed_plan_stack[i];
438 if (!completed_plan_sp->GetPrivate ())
439 return completed_plan_sp;
440 }
441 }
442 return empty_plan_sp;
443}
444
445bool
446Thread::IsThreadPlanDone (ThreadPlan *plan)
447{
448 ThreadPlanSP empty_plan_sp;
449 if (!m_completed_plan_stack.empty())
450 {
451 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
452 {
453 if (m_completed_plan_stack[i].get() == plan)
454 return true;
455 }
456 }
457 return false;
458}
459
460bool
461Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
462{
463 ThreadPlanSP empty_plan_sp;
464 if (!m_discarded_plan_stack.empty())
465 {
466 for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
467 {
468 if (m_discarded_plan_stack[i].get() == plan)
469 return true;
470 }
471 }
472 return false;
473}
474
475ThreadPlan *
476Thread::GetPreviousPlan (ThreadPlan *current_plan)
477{
478 if (current_plan == NULL)
479 return NULL;
480
481 int stack_size = m_completed_plan_stack.size();
482 for (int i = stack_size - 1; i > 0; i--)
483 {
484 if (current_plan == m_completed_plan_stack[i].get())
485 return m_completed_plan_stack[i-1].get();
486 }
487
488 if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
489 {
Chris Lattner24943d22010-06-08 16:52:24 +0000490 if (m_plan_stack.size() > 0)
491 return m_plan_stack.back().get();
492 else
493 return NULL;
494 }
495
496 stack_size = m_plan_stack.size();
497 for (int i = stack_size - 1; i > 0; i--)
498 {
499 if (current_plan == m_plan_stack[i].get())
500 return m_plan_stack[i-1].get();
501 }
502 return NULL;
503}
504
505void
506Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
507{
508 if (abort_other_plans)
509 DiscardThreadPlans(true);
510
511 PushPlan (thread_plan_sp);
512}
513
Jim Ingham745ac7a2010-11-11 19:26:09 +0000514
515void
516Thread::EnableTracer (bool value, bool single_stepping)
517{
518 int stack_size = m_plan_stack.size();
519 for (int i = 0; i < stack_size; i++)
520 {
521 if (m_plan_stack[i]->GetThreadPlanTracer())
522 {
523 m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
524 m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
525 }
526 }
527}
528
529void
530Thread::SetTracer (lldb::ThreadPlanTracerSP &tracer_sp)
531{
532 int stack_size = m_plan_stack.size();
533 for (int i = 0; i < stack_size; i++)
534 m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
535}
536
Chris Lattner24943d22010-06-08 16:52:24 +0000537void
Jim Inghamea9d4262010-11-05 19:25:48 +0000538Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
539{
Greg Claytone005f2c2010-11-06 01:53:30 +0000540 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamea9d4262010-11-05 19:25:48 +0000541 if (log)
542 {
543 log->Printf("Discarding thread plans for thread tid = 0x%4.4x, up to %p", GetID(), up_to_plan_sp.get());
544 }
545
546 int stack_size = m_plan_stack.size();
547
548 // If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
549 // stack, and if so discard up to and including it.
550
551 if (up_to_plan_sp.get() == NULL)
552 {
553 for (int i = stack_size - 1; i > 0; i--)
554 DiscardPlan();
555 }
556 else
557 {
558 bool found_it = false;
559 for (int i = stack_size - 1; i > 0; i--)
560 {
561 if (m_plan_stack[i] == up_to_plan_sp)
562 found_it = true;
563 }
564 if (found_it)
565 {
566 bool last_one = false;
567 for (int i = stack_size - 1; i > 0 && !last_one ; i--)
568 {
569 if (GetCurrentPlan() == up_to_plan_sp.get())
570 last_one = true;
571 DiscardPlan();
572 }
573 }
574 }
575 return;
576}
577
578void
Chris Lattner24943d22010-06-08 16:52:24 +0000579Thread::DiscardThreadPlans(bool force)
580{
Greg Claytone005f2c2010-11-06 01:53:30 +0000581 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +0000582 if (log)
583 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000584 log->Printf("Discarding thread plans for thread (tid = 0x%4.4x, force %d)", GetID(), force);
Chris Lattner24943d22010-06-08 16:52:24 +0000585 }
586
587 if (force)
588 {
589 int stack_size = m_plan_stack.size();
590 for (int i = stack_size - 1; i > 0; i--)
591 {
592 DiscardPlan();
593 }
594 return;
595 }
596
597 while (1)
598 {
599
600 int master_plan_idx;
601 bool discard;
602
603 // Find the first master plan, see if it wants discarding, and if yes discard up to it.
604 for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
605 {
606 if (m_plan_stack[master_plan_idx]->IsMasterPlan())
607 {
608 discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
609 break;
610 }
611 }
612
613 if (discard)
614 {
615 // First pop all the dependent plans:
616 for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
617 {
618
619 // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
620 // for the plan leaves it in a state that it is safe to pop the plan
621 // with no more notice?
622 DiscardPlan();
623 }
624
625 // Now discard the master plan itself.
626 // The bottom-most plan never gets discarded. "OkayToDiscard" for it means
627 // discard it's dependent plans, but not it...
628 if (master_plan_idx > 0)
629 {
630 DiscardPlan();
631 }
632 }
633 else
634 {
635 // If the master plan doesn't want to get discarded, then we're done.
636 break;
637 }
638
639 }
Chris Lattner24943d22010-06-08 16:52:24 +0000640}
641
642ThreadPlan *
643Thread::QueueFundamentalPlan (bool abort_other_plans)
644{
645 ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
646 QueueThreadPlan (thread_plan_sp, abort_other_plans);
647 return thread_plan_sp.get();
648}
649
650ThreadPlan *
651Thread::QueueThreadPlanForStepSingleInstruction (bool step_over, bool abort_other_plans, bool stop_other_threads)
652{
653 ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
654 QueueThreadPlan (thread_plan_sp, abort_other_plans);
655 return thread_plan_sp.get();
656}
657
658ThreadPlan *
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000659Thread::QueueThreadPlanForStepRange
660(
661 bool abort_other_plans,
662 StepType type,
663 const AddressRange &range,
664 const SymbolContext &addr_context,
665 lldb::RunMode stop_other_threads,
666 bool avoid_code_without_debug_info
667)
Chris Lattner24943d22010-06-08 16:52:24 +0000668{
669 ThreadPlanSP thread_plan_sp;
670 if (type == eStepTypeInto)
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000671 {
672 ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
673 if (avoid_code_without_debug_info)
674 plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
675 else
676 plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
677 thread_plan_sp.reset (plan);
678 }
Chris Lattner24943d22010-06-08 16:52:24 +0000679 else
680 thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
681
682 QueueThreadPlan (thread_plan_sp, abort_other_plans);
683 return thread_plan_sp.get();
684}
685
686
687ThreadPlan *
688Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
689{
690 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
691 QueueThreadPlan (thread_plan_sp, abort_other_plans);
692 return thread_plan_sp.get();
693}
694
695ThreadPlan *
696Thread::QueueThreadPlanForStepOut (bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
697 bool stop_other_threads, Vote stop_vote, Vote run_vote)
698{
699 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote));
700 QueueThreadPlan (thread_plan_sp, abort_other_plans);
701 return thread_plan_sp.get();
702}
703
704ThreadPlan *
705Thread::QueueThreadPlanForStepThrough (bool abort_other_plans, bool stop_other_threads)
706{
Jim Inghamb66cd072010-09-28 01:25:32 +0000707 // Try the dynamic loader first:
Chris Lattner24943d22010-06-08 16:52:24 +0000708 ThreadPlanSP thread_plan_sp(GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (*this, stop_other_threads));
Jim Inghamb66cd072010-09-28 01:25:32 +0000709 // If that didn't come up with anything, try the ObjC runtime plugin:
710 if (thread_plan_sp.get() == NULL)
711 {
712 ObjCLanguageRuntime *objc_runtime = GetProcess().GetObjCLanguageRuntime();
713 if (objc_runtime)
714 thread_plan_sp = objc_runtime->GetStepThroughTrampolinePlan (*this, stop_other_threads);
715 }
716
Chris Lattner24943d22010-06-08 16:52:24 +0000717 if (thread_plan_sp.get() == NULL)
718 {
719 thread_plan_sp.reset(new ThreadPlanStepThrough (*this, stop_other_threads));
720 if (thread_plan_sp && !thread_plan_sp->ValidatePlan (NULL))
Greg Claytonf8e98a62010-07-23 15:37:46 +0000721 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000722 }
723 QueueThreadPlan (thread_plan_sp, abort_other_plans);
724 return thread_plan_sp.get();
725}
726
727ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000728Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
729 Address& function,
730 lldb::addr_t arg,
731 bool stop_other_threads,
732 bool discard_on_error)
733{
734 ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
735 QueueThreadPlan (thread_plan_sp, abort_other_plans);
736 return thread_plan_sp.get();
737}
738
739ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000740Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
741 Address &target_addr,
742 bool stop_other_threads)
743{
744 ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
745 QueueThreadPlan (thread_plan_sp, abort_other_plans);
746 return thread_plan_sp.get();
747}
748
749ThreadPlan *
750Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
751 lldb::addr_t *address_list,
752 size_t num_addresses,
753 bool stop_other_threads)
754{
755 ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads));
756 QueueThreadPlan (thread_plan_sp, abort_other_plans);
757 return thread_plan_sp.get();
758
759}
760
761uint32_t
762Thread::GetIndexID () const
763{
764 return m_index_id;
765}
766
767void
768Thread::DumpThreadPlans (lldb_private::Stream *s) const
769{
770 uint32_t stack_size = m_plan_stack.size();
Greg Claytonf04d6612010-09-03 22:45:01 +0000771 int i;
772 s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4x, stack_size = %d\n", GetIndexID(), GetID(), stack_size);
773 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000774 {
775 s->Printf ("Element %d: ", i);
776 s->IndentMore();
777 m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
778 s->IndentLess();
779 s->EOL();
780 }
781
Chris Lattner24943d22010-06-08 16:52:24 +0000782 stack_size = m_completed_plan_stack.size();
783 s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
Greg Claytonf04d6612010-09-03 22:45:01 +0000784 for (i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000785 {
786 s->Printf ("Element %d: ", i);
787 s->IndentMore();
788 m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
789 s->IndentLess();
790 s->EOL();
791 }
792
793 stack_size = m_discarded_plan_stack.size();
794 s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
Greg Claytonf04d6612010-09-03 22:45:01 +0000795 for (int i = stack_size - 1; i >= 0; i--)
Chris Lattner24943d22010-06-08 16:52:24 +0000796 {
797 s->Printf ("Element %d: ", i);
798 s->IndentMore();
799 m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
800 s->IndentLess();
801 s->EOL();
802 }
803
804}
805
806Target *
807Thread::CalculateTarget ()
808{
809 return m_process.CalculateTarget();
810}
811
812Process *
813Thread::CalculateProcess ()
814{
815 return &m_process;
816}
817
818Thread *
819Thread::CalculateThread ()
820{
821 return this;
822}
823
824StackFrame *
825Thread::CalculateStackFrame ()
826{
827 return NULL;
828}
829
830void
Greg Claytona830adb2010-10-04 01:05:56 +0000831Thread::CalculateExecutionContext (ExecutionContext &exe_ctx)
Chris Lattner24943d22010-06-08 16:52:24 +0000832{
Greg Claytona830adb2010-10-04 01:05:56 +0000833 m_process.CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000834 exe_ctx.thread = this;
835 exe_ctx.frame = NULL;
836}
837
Greg Clayton782b9cc2010-08-25 00:35:26 +0000838
839StackFrameList &
840Thread::GetStackFrameList ()
841{
Greg Claytonf40e3082010-08-26 02:28:22 +0000842 if (m_curr_frames_ap.get() == NULL)
Greg Clayton5205f0b2010-09-03 17:10:42 +0000843 m_curr_frames_ap.reset (new StackFrameList (*this, m_prev_frames_sp, true));
Greg Claytonf40e3082010-08-26 02:28:22 +0000844 return *m_curr_frames_ap;
Greg Clayton782b9cc2010-08-25 00:35:26 +0000845}
846
847
848
Jim Ingham71219082010-08-12 02:14:28 +0000849uint32_t
850Thread::GetStackFrameCount()
851{
Greg Clayton782b9cc2010-08-25 00:35:26 +0000852 return GetStackFrameList().GetNumFrames();
853}
Greg Clayton33ed1702010-08-24 00:45:41 +0000854
Greg Clayton33ed1702010-08-24 00:45:41 +0000855
Greg Clayton782b9cc2010-08-25 00:35:26 +0000856void
857Thread::ClearStackFrames ()
858{
Greg Clayton5205f0b2010-09-03 17:10:42 +0000859 if (m_curr_frames_ap.get() && m_curr_frames_ap->GetNumFrames (false) > 1)
860 m_prev_frames_sp.reset (m_curr_frames_ap.release());
861 else
862 m_curr_frames_ap.release();
863
864// StackFrameList::Merge (m_curr_frames_ap, m_prev_frames_sp);
865// assert (m_curr_frames_ap.get() == NULL);
Jim Ingham71219082010-08-12 02:14:28 +0000866}
867
868lldb::StackFrameSP
869Thread::GetStackFrameAtIndex (uint32_t idx)
870{
Greg Clayton72b71582010-09-02 21:44:10 +0000871 return GetStackFrameList().GetFrameAtIndex(idx);
Jim Ingham71219082010-08-12 02:14:28 +0000872}
873
Greg Claytonc12b6b42010-10-10 22:28:11 +0000874uint32_t
875Thread::GetSelectedFrameIndex ()
876{
877 return GetStackFrameList().GetSelectedFrameIndex();
878}
879
880
Chris Lattner24943d22010-06-08 16:52:24 +0000881lldb::StackFrameSP
Jim Inghamc8332952010-08-26 21:32:51 +0000882Thread::GetSelectedFrame ()
Chris Lattner24943d22010-06-08 16:52:24 +0000883{
Jim Inghamc8332952010-08-26 21:32:51 +0000884 return GetStackFrameAtIndex (GetStackFrameList().GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000885}
886
887uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000888Thread::SetSelectedFrame (lldb_private::StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000889{
Jim Inghamc8332952010-08-26 21:32:51 +0000890 return GetStackFrameList().SetSelectedFrame(frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000891}
892
893void
Jim Inghamc8332952010-08-26 21:32:51 +0000894Thread::SetSelectedFrameByIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000895{
Jim Inghamc8332952010-08-26 21:32:51 +0000896 GetStackFrameList().SetSelectedFrameByIndex(idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000897}
898
899void
Greg Claytona830adb2010-10-04 01:05:56 +0000900Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000901{
Greg Claytona830adb2010-10-04 01:05:56 +0000902 ExecutionContext exe_ctx;
903 SymbolContext frame_sc;
904 CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000905
Greg Claytona830adb2010-10-04 01:05:56 +0000906 if (frame_idx != LLDB_INVALID_INDEX32)
Chris Lattner24943d22010-06-08 16:52:24 +0000907 {
Greg Claytona830adb2010-10-04 01:05:56 +0000908 StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000909 if (frame_sp)
910 {
Greg Claytona830adb2010-10-04 01:05:56 +0000911 exe_ctx.frame = frame_sp.get();
912 frame_sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
Chris Lattner24943d22010-06-08 16:52:24 +0000913 }
914 }
915
Greg Claytona830adb2010-10-04 01:05:56 +0000916 const char *thread_format = GetProcess().GetTarget().GetDebugger().GetThreadFormat();
917 assert (thread_format);
918 const char *end = NULL;
919 Debugger::FormatPrompt (thread_format,
920 exe_ctx.frame ? &frame_sc : NULL,
921 &exe_ctx,
922 NULL,
923 strm,
924 &end);
Chris Lattner24943d22010-06-08 16:52:24 +0000925}
926
927lldb::ThreadSP
928Thread::GetSP ()
929{
930 return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
931}
Jim Ingham20594b12010-09-08 03:14:33 +0000932
Greg Clayton990de7b2010-11-18 23:32:35 +0000933
934void
935Thread::Initialize ()
Jim Ingham20594b12010-09-08 03:14:33 +0000936{
Greg Clayton990de7b2010-11-18 23:32:35 +0000937 UserSettingsControllerSP &usc = GetSettingsController();
938 usc.reset (new SettingsController);
939 UserSettingsController::InitializeSettingsController (usc,
940 SettingsController::global_settings_table,
941 SettingsController::instance_settings_table);
942}
Jim Ingham20594b12010-09-08 03:14:33 +0000943
Greg Clayton990de7b2010-11-18 23:32:35 +0000944void
945Thread::Terminate ()
946{
947 UserSettingsControllerSP &usc = GetSettingsController();
948 UserSettingsController::FinalizeSettingsController (usc);
949 usc.reset();
950}
Jim Ingham20594b12010-09-08 03:14:33 +0000951
Greg Clayton990de7b2010-11-18 23:32:35 +0000952UserSettingsControllerSP &
953Thread::GetSettingsController ()
954{
955 static UserSettingsControllerSP g_settings_controller;
Jim Ingham20594b12010-09-08 03:14:33 +0000956 return g_settings_controller;
957}
958
Caroline Tice1ebef442010-09-27 00:30:10 +0000959void
960Thread::UpdateInstanceName ()
961{
962 StreamString sstr;
963 const char *name = GetName();
964
965 if (name && name[0] != '\0')
966 sstr.Printf ("%s", name);
967 else if ((GetIndexID() != 0) || (GetID() != 0))
968 sstr.Printf ("0x%4.4x", GetIndexID(), GetID());
969
970 if (sstr.GetSize() > 0)
971 Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
972}
973
Jim Inghamccd584d2010-09-23 17:40:12 +0000974lldb::StackFrameSP
975Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
976{
977 return GetStackFrameList().GetStackFrameSPForStackFramePtr (stack_frame_ptr);
978}
Caroline Tice7826c882010-10-26 03:11:13 +0000979
980const char *
981Thread::StopReasonAsCString (lldb::StopReason reason)
982{
983 switch (reason)
984 {
985 case eStopReasonInvalid: return "invalid";
986 case eStopReasonNone: return "none";
987 case eStopReasonTrace: return "trace";
988 case eStopReasonBreakpoint: return "breakpoint";
989 case eStopReasonWatchpoint: return "watchpoint";
990 case eStopReasonSignal: return "signal";
991 case eStopReasonException: return "exception";
992 case eStopReasonPlanComplete: return "plan complete";
993 }
994
995
996 static char unknown_state_string[64];
997 snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
998 return unknown_state_string;
999}
1000
1001const char *
1002Thread::RunModeAsCString (lldb::RunMode mode)
1003{
1004 switch (mode)
1005 {
1006 case eOnlyThisThread: return "only this thread";
1007 case eAllThreads: return "all threads";
1008 case eOnlyDuringStepping: return "only during stepping";
1009 }
1010
1011 static char unknown_state_string[64];
1012 snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
1013 return unknown_state_string;
1014}
Jim Ingham745ac7a2010-11-11 19:26:09 +00001015
Greg Clayton990de7b2010-11-18 23:32:35 +00001016#pragma mark "Thread::SettingsController"
Jim Ingham745ac7a2010-11-11 19:26:09 +00001017//--------------------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001018// class Thread::SettingsController
Jim Ingham745ac7a2010-11-11 19:26:09 +00001019//--------------------------------------------------------------
1020
Greg Clayton990de7b2010-11-18 23:32:35 +00001021Thread::SettingsController::SettingsController () :
Jim Ingham745ac7a2010-11-11 19:26:09 +00001022 UserSettingsController ("thread", Process::GetSettingsController())
1023{
1024 m_default_settings.reset (new ThreadInstanceSettings (*this, false,
1025 InstanceSettings::GetDefaultName().AsCString()));
1026}
1027
Greg Clayton990de7b2010-11-18 23:32:35 +00001028Thread::SettingsController::~SettingsController ()
Jim Ingham745ac7a2010-11-11 19:26:09 +00001029{
1030}
1031
1032lldb::InstanceSettingsSP
Greg Clayton990de7b2010-11-18 23:32:35 +00001033Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
Jim Ingham745ac7a2010-11-11 19:26:09 +00001034{
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001035 ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*GetSettingsController(),
1036 false,
1037 instance_name);
Jim Ingham745ac7a2010-11-11 19:26:09 +00001038 lldb::InstanceSettingsSP new_settings_sp (new_settings);
1039 return new_settings_sp;
1040}
1041
1042#pragma mark "ThreadInstanceSettings"
1043//--------------------------------------------------------------
1044// class ThreadInstanceSettings
1045//--------------------------------------------------------------
1046
1047ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
Greg Clayton638351a2010-12-04 00:10:17 +00001048 InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001049 m_avoid_regexp_ap (),
1050 m_trace_enabled (false)
1051{
1052 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
1053 // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
1054 // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
1055 // This is true for CreateInstanceName() too.
1056
1057 if (GetInstanceName() == InstanceSettings::InvalidName())
1058 {
1059 ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
1060 m_owner.RegisterInstanceSettings (this);
1061 }
1062
1063 if (live_instance)
1064 {
1065 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1066 CopyInstanceSettings (pending_settings,false);
1067 //m_owner.RemovePendingSettings (m_instance_name);
1068 }
1069}
1070
1071ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001072 InstanceSettings (*Thread::GetSettingsController(), CreateInstanceName().AsCString()),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001073 m_avoid_regexp_ap (),
1074 m_trace_enabled (rhs.m_trace_enabled)
1075{
1076 if (m_instance_name != InstanceSettings::GetDefaultName())
1077 {
1078 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1079 CopyInstanceSettings (pending_settings,false);
1080 m_owner.RemovePendingSettings (m_instance_name);
1081 }
1082 if (rhs.m_avoid_regexp_ap.get() != NULL)
1083 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1084}
1085
1086ThreadInstanceSettings::~ThreadInstanceSettings ()
1087{
1088}
1089
1090ThreadInstanceSettings&
1091ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
1092{
1093 if (this != &rhs)
1094 {
1095 if (rhs.m_avoid_regexp_ap.get() != NULL)
1096 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1097 else
1098 m_avoid_regexp_ap.reset(NULL);
1099 }
1100 m_trace_enabled = rhs.m_trace_enabled;
1101 return *this;
1102}
1103
1104
1105void
1106ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
1107 const char *index_value,
1108 const char *value,
1109 const ConstString &instance_name,
1110 const SettingEntry &entry,
1111 lldb::VarSetOperationType op,
1112 Error &err,
1113 bool pending)
1114{
1115 if (var_name == StepAvoidRegexpVarName())
1116 {
1117 std::string regexp_text;
1118 if (m_avoid_regexp_ap.get() != NULL)
1119 regexp_text.append (m_avoid_regexp_ap->GetText());
1120 UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
1121 if (regexp_text.empty())
1122 m_avoid_regexp_ap.reset();
1123 else
1124 {
1125 m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
1126
1127 }
1128 }
1129 else if (var_name == GetTraceThreadVarName())
1130 {
1131 bool success;
1132 bool result = Args::StringToBoolean(value, false, &success);
1133
1134 if (success)
1135 {
1136 m_trace_enabled = result;
1137 if (!pending)
1138 {
1139 Thread *myself = static_cast<Thread *> (this);
1140 myself->EnableTracer(m_trace_enabled, true);
1141 }
1142 }
1143 else
1144 {
1145 err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
1146 }
1147
1148 }
1149}
1150
1151void
1152ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
1153 bool pending)
1154{
1155 if (new_settings.get() == NULL)
1156 return;
1157
1158 ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
1159 if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
1160 m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
1161 else
1162 m_avoid_regexp_ap.reset ();
1163}
1164
1165bool
1166ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
1167 const ConstString &var_name,
1168 StringList &value,
1169 Error *err)
1170{
1171 if (var_name == StepAvoidRegexpVarName())
1172 {
1173 if (m_avoid_regexp_ap.get() != NULL)
1174 {
1175 std::string regexp_text("\"");
1176 regexp_text.append(m_avoid_regexp_ap->GetText());
1177 regexp_text.append ("\"");
1178 value.AppendString (regexp_text.c_str());
1179 }
1180
1181 }
1182 else if (var_name == GetTraceThreadVarName())
1183 {
1184 value.AppendString(m_trace_enabled ? "true" : "false");
1185 }
1186 else
1187 {
1188 if (err)
1189 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
1190 return false;
1191 }
1192 return true;
1193}
1194
1195const ConstString
1196ThreadInstanceSettings::CreateInstanceName ()
1197{
1198 static int instance_count = 1;
1199 StreamString sstr;
1200
1201 sstr.Printf ("thread_%d", instance_count);
1202 ++instance_count;
1203
1204 const ConstString ret_val (sstr.GetData());
1205 return ret_val;
1206}
1207
1208const ConstString &
1209ThreadInstanceSettings::StepAvoidRegexpVarName ()
1210{
1211 static ConstString step_avoid_var_name ("step-avoid-regexp");
1212
1213 return step_avoid_var_name;
1214}
1215
1216const ConstString &
1217ThreadInstanceSettings::GetTraceThreadVarName ()
1218{
1219 static ConstString trace_thread_var_name ("trace-thread");
1220
1221 return trace_thread_var_name;
1222}
1223
1224//--------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001225// SettingsController Variable Tables
Jim Ingham745ac7a2010-11-11 19:26:09 +00001226//--------------------------------------------------
1227
1228SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001229Thread::SettingsController::global_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001230{
1231 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
1232 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1233};
1234
1235
1236SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001237Thread::SettingsController::instance_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001238{
1239 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
1240 { "step-avoid-regexp", eSetVarTypeString, "", NULL, false, false, "A regular expression defining functions step-in won't stop in." },
1241 { "trace-thread", eSetVarTypeBoolean, "false", NULL, false, false, "If true, this thread will single-step and log execution." },
1242 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1243};