blob: e9b3b6dc60bbaa879ae9e475d366f23157b04e62 [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
Greg Clayton08d7d3a2011-01-06 22:15:06 +0000880lldb::StackFrameSP
881Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
882{
883 return GetStackFrameList().GetFrameWithConcreteFrameIndex (unwind_idx);
884}
885
886
Greg Claytonc12b6b42010-10-10 22:28:11 +0000887
Chris Lattner24943d22010-06-08 16:52:24 +0000888lldb::StackFrameSP
Jim Inghamc8332952010-08-26 21:32:51 +0000889Thread::GetSelectedFrame ()
Chris Lattner24943d22010-06-08 16:52:24 +0000890{
Jim Inghamc8332952010-08-26 21:32:51 +0000891 return GetStackFrameAtIndex (GetStackFrameList().GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000892}
893
894uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000895Thread::SetSelectedFrame (lldb_private::StackFrame *frame)
Chris Lattner24943d22010-06-08 16:52:24 +0000896{
Jim Inghamc8332952010-08-26 21:32:51 +0000897 return GetStackFrameList().SetSelectedFrame(frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000898}
899
900void
Jim Inghamc8332952010-08-26 21:32:51 +0000901Thread::SetSelectedFrameByIndex (uint32_t idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000902{
Jim Inghamc8332952010-08-26 21:32:51 +0000903 GetStackFrameList().SetSelectedFrameByIndex(idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000904}
905
906void
Greg Claytona830adb2010-10-04 01:05:56 +0000907Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000908{
Greg Claytona830adb2010-10-04 01:05:56 +0000909 ExecutionContext exe_ctx;
910 SymbolContext frame_sc;
911 CalculateExecutionContext (exe_ctx);
Chris Lattner24943d22010-06-08 16:52:24 +0000912
Greg Claytona830adb2010-10-04 01:05:56 +0000913 if (frame_idx != LLDB_INVALID_INDEX32)
Chris Lattner24943d22010-06-08 16:52:24 +0000914 {
Greg Claytona830adb2010-10-04 01:05:56 +0000915 StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000916 if (frame_sp)
917 {
Greg Claytona830adb2010-10-04 01:05:56 +0000918 exe_ctx.frame = frame_sp.get();
919 frame_sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything);
Chris Lattner24943d22010-06-08 16:52:24 +0000920 }
921 }
922
Greg Claytona830adb2010-10-04 01:05:56 +0000923 const char *thread_format = GetProcess().GetTarget().GetDebugger().GetThreadFormat();
924 assert (thread_format);
925 const char *end = NULL;
926 Debugger::FormatPrompt (thread_format,
927 exe_ctx.frame ? &frame_sc : NULL,
928 &exe_ctx,
929 NULL,
930 strm,
931 &end);
Chris Lattner24943d22010-06-08 16:52:24 +0000932}
933
934lldb::ThreadSP
935Thread::GetSP ()
936{
937 return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
938}
Jim Ingham20594b12010-09-08 03:14:33 +0000939
Greg Clayton990de7b2010-11-18 23:32:35 +0000940
941void
942Thread::Initialize ()
Jim Ingham20594b12010-09-08 03:14:33 +0000943{
Greg Clayton990de7b2010-11-18 23:32:35 +0000944 UserSettingsControllerSP &usc = GetSettingsController();
945 usc.reset (new SettingsController);
946 UserSettingsController::InitializeSettingsController (usc,
947 SettingsController::global_settings_table,
948 SettingsController::instance_settings_table);
949}
Jim Ingham20594b12010-09-08 03:14:33 +0000950
Greg Clayton990de7b2010-11-18 23:32:35 +0000951void
952Thread::Terminate ()
953{
954 UserSettingsControllerSP &usc = GetSettingsController();
955 UserSettingsController::FinalizeSettingsController (usc);
956 usc.reset();
957}
Jim Ingham20594b12010-09-08 03:14:33 +0000958
Greg Clayton990de7b2010-11-18 23:32:35 +0000959UserSettingsControllerSP &
960Thread::GetSettingsController ()
961{
962 static UserSettingsControllerSP g_settings_controller;
Jim Ingham20594b12010-09-08 03:14:33 +0000963 return g_settings_controller;
964}
965
Caroline Tice1ebef442010-09-27 00:30:10 +0000966void
967Thread::UpdateInstanceName ()
968{
969 StreamString sstr;
970 const char *name = GetName();
971
972 if (name && name[0] != '\0')
973 sstr.Printf ("%s", name);
974 else if ((GetIndexID() != 0) || (GetID() != 0))
975 sstr.Printf ("0x%4.4x", GetIndexID(), GetID());
976
977 if (sstr.GetSize() > 0)
978 Thread::GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(), sstr.GetData());
979}
980
Jim Inghamccd584d2010-09-23 17:40:12 +0000981lldb::StackFrameSP
982Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
983{
984 return GetStackFrameList().GetStackFrameSPForStackFramePtr (stack_frame_ptr);
985}
Caroline Tice7826c882010-10-26 03:11:13 +0000986
987const char *
988Thread::StopReasonAsCString (lldb::StopReason reason)
989{
990 switch (reason)
991 {
992 case eStopReasonInvalid: return "invalid";
993 case eStopReasonNone: return "none";
994 case eStopReasonTrace: return "trace";
995 case eStopReasonBreakpoint: return "breakpoint";
996 case eStopReasonWatchpoint: return "watchpoint";
997 case eStopReasonSignal: return "signal";
998 case eStopReasonException: return "exception";
999 case eStopReasonPlanComplete: return "plan complete";
1000 }
1001
1002
1003 static char unknown_state_string[64];
1004 snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
1005 return unknown_state_string;
1006}
1007
1008const char *
1009Thread::RunModeAsCString (lldb::RunMode mode)
1010{
1011 switch (mode)
1012 {
1013 case eOnlyThisThread: return "only this thread";
1014 case eAllThreads: return "all threads";
1015 case eOnlyDuringStepping: return "only during stepping";
1016 }
1017
1018 static char unknown_state_string[64];
1019 snprintf(unknown_state_string, sizeof (unknown_state_string), "RunMode = %i", mode);
1020 return unknown_state_string;
1021}
Jim Ingham745ac7a2010-11-11 19:26:09 +00001022
Greg Clayton990de7b2010-11-18 23:32:35 +00001023#pragma mark "Thread::SettingsController"
Jim Ingham745ac7a2010-11-11 19:26:09 +00001024//--------------------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001025// class Thread::SettingsController
Jim Ingham745ac7a2010-11-11 19:26:09 +00001026//--------------------------------------------------------------
1027
Greg Clayton990de7b2010-11-18 23:32:35 +00001028Thread::SettingsController::SettingsController () :
Jim Ingham745ac7a2010-11-11 19:26:09 +00001029 UserSettingsController ("thread", Process::GetSettingsController())
1030{
1031 m_default_settings.reset (new ThreadInstanceSettings (*this, false,
1032 InstanceSettings::GetDefaultName().AsCString()));
1033}
1034
Greg Clayton990de7b2010-11-18 23:32:35 +00001035Thread::SettingsController::~SettingsController ()
Jim Ingham745ac7a2010-11-11 19:26:09 +00001036{
1037}
1038
1039lldb::InstanceSettingsSP
Greg Clayton990de7b2010-11-18 23:32:35 +00001040Thread::SettingsController::CreateInstanceSettings (const char *instance_name)
Jim Ingham745ac7a2010-11-11 19:26:09 +00001041{
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001042 ThreadInstanceSettings *new_settings = new ThreadInstanceSettings (*GetSettingsController(),
1043 false,
1044 instance_name);
Jim Ingham745ac7a2010-11-11 19:26:09 +00001045 lldb::InstanceSettingsSP new_settings_sp (new_settings);
1046 return new_settings_sp;
1047}
1048
1049#pragma mark "ThreadInstanceSettings"
1050//--------------------------------------------------------------
1051// class ThreadInstanceSettings
1052//--------------------------------------------------------------
1053
1054ThreadInstanceSettings::ThreadInstanceSettings (UserSettingsController &owner, bool live_instance, const char *name) :
Greg Clayton638351a2010-12-04 00:10:17 +00001055 InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001056 m_avoid_regexp_ap (),
1057 m_trace_enabled (false)
1058{
1059 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
1060 // until the vtables for ThreadInstanceSettings are properly set up, i.e. AFTER all the initializers.
1061 // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
1062 // This is true for CreateInstanceName() too.
1063
1064 if (GetInstanceName() == InstanceSettings::InvalidName())
1065 {
1066 ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
1067 m_owner.RegisterInstanceSettings (this);
1068 }
1069
1070 if (live_instance)
1071 {
1072 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1073 CopyInstanceSettings (pending_settings,false);
1074 //m_owner.RemovePendingSettings (m_instance_name);
1075 }
1076}
1077
1078ThreadInstanceSettings::ThreadInstanceSettings (const ThreadInstanceSettings &rhs) :
Greg Claytonc0c1b0c2010-11-19 03:46:01 +00001079 InstanceSettings (*Thread::GetSettingsController(), CreateInstanceName().AsCString()),
Jim Ingham745ac7a2010-11-11 19:26:09 +00001080 m_avoid_regexp_ap (),
1081 m_trace_enabled (rhs.m_trace_enabled)
1082{
1083 if (m_instance_name != InstanceSettings::GetDefaultName())
1084 {
1085 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1086 CopyInstanceSettings (pending_settings,false);
1087 m_owner.RemovePendingSettings (m_instance_name);
1088 }
1089 if (rhs.m_avoid_regexp_ap.get() != NULL)
1090 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1091}
1092
1093ThreadInstanceSettings::~ThreadInstanceSettings ()
1094{
1095}
1096
1097ThreadInstanceSettings&
1098ThreadInstanceSettings::operator= (const ThreadInstanceSettings &rhs)
1099{
1100 if (this != &rhs)
1101 {
1102 if (rhs.m_avoid_regexp_ap.get() != NULL)
1103 m_avoid_regexp_ap.reset(new RegularExpression(rhs.m_avoid_regexp_ap->GetText()));
1104 else
1105 m_avoid_regexp_ap.reset(NULL);
1106 }
1107 m_trace_enabled = rhs.m_trace_enabled;
1108 return *this;
1109}
1110
1111
1112void
1113ThreadInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
1114 const char *index_value,
1115 const char *value,
1116 const ConstString &instance_name,
1117 const SettingEntry &entry,
1118 lldb::VarSetOperationType op,
1119 Error &err,
1120 bool pending)
1121{
1122 if (var_name == StepAvoidRegexpVarName())
1123 {
1124 std::string regexp_text;
1125 if (m_avoid_regexp_ap.get() != NULL)
1126 regexp_text.append (m_avoid_regexp_ap->GetText());
1127 UserSettingsController::UpdateStringVariable (op, regexp_text, value, err);
1128 if (regexp_text.empty())
1129 m_avoid_regexp_ap.reset();
1130 else
1131 {
1132 m_avoid_regexp_ap.reset(new RegularExpression(regexp_text.c_str()));
1133
1134 }
1135 }
1136 else if (var_name == GetTraceThreadVarName())
1137 {
1138 bool success;
1139 bool result = Args::StringToBoolean(value, false, &success);
1140
1141 if (success)
1142 {
1143 m_trace_enabled = result;
1144 if (!pending)
1145 {
1146 Thread *myself = static_cast<Thread *> (this);
1147 myself->EnableTracer(m_trace_enabled, true);
1148 }
1149 }
1150 else
1151 {
1152 err.SetErrorStringWithFormat ("Bad value \"%s\" for trace-thread, should be Boolean.", value);
1153 }
1154
1155 }
1156}
1157
1158void
1159ThreadInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
1160 bool pending)
1161{
1162 if (new_settings.get() == NULL)
1163 return;
1164
1165 ThreadInstanceSettings *new_process_settings = (ThreadInstanceSettings *) new_settings.get();
1166 if (new_process_settings->GetSymbolsToAvoidRegexp() != NULL)
1167 m_avoid_regexp_ap.reset (new RegularExpression (new_process_settings->GetSymbolsToAvoidRegexp()->GetText()));
1168 else
1169 m_avoid_regexp_ap.reset ();
1170}
1171
1172bool
1173ThreadInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
1174 const ConstString &var_name,
1175 StringList &value,
1176 Error *err)
1177{
1178 if (var_name == StepAvoidRegexpVarName())
1179 {
1180 if (m_avoid_regexp_ap.get() != NULL)
1181 {
1182 std::string regexp_text("\"");
1183 regexp_text.append(m_avoid_regexp_ap->GetText());
1184 regexp_text.append ("\"");
1185 value.AppendString (regexp_text.c_str());
1186 }
1187
1188 }
1189 else if (var_name == GetTraceThreadVarName())
1190 {
1191 value.AppendString(m_trace_enabled ? "true" : "false");
1192 }
1193 else
1194 {
1195 if (err)
1196 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
1197 return false;
1198 }
1199 return true;
1200}
1201
1202const ConstString
1203ThreadInstanceSettings::CreateInstanceName ()
1204{
1205 static int instance_count = 1;
1206 StreamString sstr;
1207
1208 sstr.Printf ("thread_%d", instance_count);
1209 ++instance_count;
1210
1211 const ConstString ret_val (sstr.GetData());
1212 return ret_val;
1213}
1214
1215const ConstString &
1216ThreadInstanceSettings::StepAvoidRegexpVarName ()
1217{
1218 static ConstString step_avoid_var_name ("step-avoid-regexp");
1219
1220 return step_avoid_var_name;
1221}
1222
1223const ConstString &
1224ThreadInstanceSettings::GetTraceThreadVarName ()
1225{
1226 static ConstString trace_thread_var_name ("trace-thread");
1227
1228 return trace_thread_var_name;
1229}
1230
1231//--------------------------------------------------
Greg Clayton990de7b2010-11-18 23:32:35 +00001232// SettingsController Variable Tables
Jim Ingham745ac7a2010-11-11 19:26:09 +00001233//--------------------------------------------------
1234
1235SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001236Thread::SettingsController::global_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001237{
1238 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
1239 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1240};
1241
1242
1243SettingEntry
Greg Clayton990de7b2010-11-18 23:32:35 +00001244Thread::SettingsController::instance_settings_table[] =
Jim Ingham745ac7a2010-11-11 19:26:09 +00001245{
1246 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
1247 { "step-avoid-regexp", eSetVarTypeString, "", NULL, false, false, "A regular expression defining functions step-in won't stop in." },
1248 { "trace-thread", eSetVarTypeBoolean, "false", NULL, false, false, "If true, this thread will single-step and log execution." },
1249 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1250};