blob: 40ea4df14a594ca335d3bcedb6483e2e7302ad72 [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"
Chris Lattner24943d22010-06-08 16:52:24 +000012#include "lldb/Core/Log.h"
13#include "lldb/Core/Stream.h"
14#include "lldb/Core/StreamString.h"
15#include "lldb/Host/Host.h"
16#include "lldb/Target/DynamicLoader.h"
17#include "lldb/Target/ExecutionContext.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/Thread.h"
21#include "lldb/Target/ThreadPlan.h"
22#include "lldb/Target/ThreadPlanCallFunction.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/ThreadPlanBase.h"
24#include "lldb/Target/ThreadPlanStepInstruction.h"
25#include "lldb/Target/ThreadPlanStepOut.h"
26#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
27#include "lldb/Target/ThreadPlanStepThrough.h"
28#include "lldb/Target/ThreadPlanStepInRange.h"
29#include "lldb/Target/ThreadPlanStepOverRange.h"
30#include "lldb/Target/ThreadPlanRunToAddress.h"
31#include "lldb/Target/ThreadPlanStepUntil.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000032#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
37Thread::Thread (Process &process, lldb::tid_t tid) :
38 UserID (tid),
39 m_index_id (process.GetNextThreadIndexID ()),
40 m_reg_context_sp (),
41 m_process (process),
42 m_state (eStateUnloaded),
43 m_plan_stack (),
44 m_immediate_plan_stack(),
45 m_completed_plan_stack(),
46 m_state_mutex (Mutex::eMutexTypeRecursive),
47 m_frames (),
48 m_current_frame_idx (0),
49 m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
50 m_resume_state (eStateRunning)
51{
52 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
53 if (log)
54 log->Printf ("%p Thread::Thread(tid = 0x%4.4x)", this, GetID());
55
56 QueueFundamentalPlan(true);
57}
58
59
60Thread::~Thread()
61{
62 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
63 if (log)
64 log->Printf ("%p Thread::~Thread(tid = 0x%4.4x)", this, GetID());
65}
66
67int
68Thread::GetResumeSignal () const
69{
70 return m_resume_signal;
71}
72
73void
74Thread::SetResumeSignal (int signal)
75{
76 m_resume_signal = signal;
77}
78
79StateType
80Thread::GetResumeState () const
81{
82 return m_resume_state;
83}
84
85void
86Thread::SetResumeState (StateType state)
87{
88 m_resume_state = state;
89}
90
91Thread::StopInfo::StopInfo(Thread *thread) :
92 m_reason (eStopReasonInvalid),
93 m_description (),
94 m_thread (thread),
95 m_details ()
96{
97 m_description[0] = '\0';
98}
99
100Thread::StopInfo::~StopInfo()
101{
102}
103
104
105void
106Thread::StopInfo::Clear()
107{
108 m_reason = eStopReasonInvalid;
109 m_completed_plan_sp.reset();
110 m_description[0] = '\0';
111 ::bzero (&m_details, sizeof(m_details));
112}
113
114StopReason
115Thread::StopInfo::GetStopReason() const
116{
117 return m_reason;
118}
119
120const char *
121Thread::StopInfo::GetStopDescription() const
122{
123 if (m_description[0])
124 return m_description;
125 return NULL;
126}
127
128void
129Thread::StopInfo::SetStopDescription(const char *desc)
130{
131 if (desc && desc[0])
132 {
133 ::snprintf (m_description, sizeof(m_description), "%s", desc);
134 }
135 else
136 {
137 m_description[0] = '\0';
138 }
139}
140
141void
142Thread::StopInfo::SetThread (Thread* thread)
143{
144 m_thread = thread;
145}
146
147Thread *
148Thread::StopInfo::GetThread ()
149{
150 return m_thread;
151}
152
153lldb::user_id_t
154Thread::StopInfo::GetBreakpointSiteID() const
155{
156 if (m_reason == eStopReasonBreakpoint)
157 return m_details.breakpoint.bp_site_id;
158 return LLDB_INVALID_BREAK_ID;
159}
160
161void
162Thread::StopInfo::SetStopReasonWithBreakpointSiteID (lldb::user_id_t bp_site_id)
163{
164 m_reason = eStopReasonBreakpoint;
165 m_details.breakpoint.bp_site_id = bp_site_id;
166}
167
168lldb::user_id_t
169Thread::StopInfo::GetWatchpointID() const
170{
171 if (m_reason == eStopReasonWatchpoint)
172 return m_details.watchpoint.watch_id;
173 return LLDB_INVALID_WATCH_ID;
174}
175
176void
177Thread::StopInfo::SetStopReasonWithWatchpointID (lldb::user_id_t watch_id)
178{
179 m_reason = eStopReasonWatchpoint;
180 m_details.watchpoint.watch_id = watch_id;
181}
182
183
184int
185Thread::StopInfo::GetSignal() const
186{
187 if (m_reason == eStopReasonSignal)
188 return m_details.signal.signo;
189 return 0;
190}
191
192lldb::user_id_t
193Thread::StopInfo::GetPlanID() const
194{
195 if (m_reason == eStopReasonPlanComplete)
196 return m_completed_plan_sp->GetID();
197 return LLDB_INVALID_UID;
198}
199
200void
201Thread::StopInfo::SetStopReasonWithSignal (int signo)
202{
203 m_reason = eStopReasonSignal;
204 m_details.signal.signo = signo;
205}
206
207void
208Thread::StopInfo::SetStopReasonToTrace ()
209{
210 m_reason = eStopReasonTrace;
211}
212
213uint32_t
214Thread::StopInfo::GetExceptionType() const
215{
216 if (m_reason == eStopReasonException)
217 return m_details.exception.type;
218 return 0;
219}
220
221size_t
222Thread::StopInfo::GetExceptionDataCount() const
223{
224 if (m_reason == eStopReasonException)
225 return m_details.exception.data_count;
226 return 0;
227}
228
229void
230Thread::StopInfo::SetStopReasonWithException (uint32_t exc_type, size_t exc_data_count)
231{
232 m_reason = eStopReasonException;
233 m_details.exception.type = exc_type;
234 m_details.exception.data_count = exc_data_count;
235}
236
237void
238Thread::StopInfo::SetStopReasonWithPlan (ThreadPlanSP &thread_plan_sp)
239{
240 m_reason = eStopReasonPlanComplete;
241 m_completed_plan_sp = thread_plan_sp;
242}
243
244void
245Thread::StopInfo::SetStopReasonToNone ()
246{
247 Clear();
248 m_reason = eStopReasonNone;
249}
250
251lldb::addr_t
252Thread::StopInfo::GetExceptionDataAtIndex (uint32_t idx) const
253{
254 if (m_reason == eStopReasonException && idx < m_details.exception.data_count)
255 return m_details.exception.data[idx];
256 return 0;
257
258}
259
260
261bool
262Thread::StopInfo::SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data)
263{
264 if (m_reason == eStopReasonException && idx < m_details.exception.data_count)
265 {
266 m_details.exception.data[idx] = data;
267 return true;
268 }
269 return false;
270}
271
272void
273Thread::StopInfo::Dump (Stream *s) const
274{
275 if (m_description[0])
276 s->Printf("%s", m_description);
277 else
278 {
279 switch (m_reason)
280 {
281 case eStopReasonInvalid:
282 s->PutCString("invalid");
283 break;
284
285 case eStopReasonNone:
286 s->PutCString("none");
287 break;
288
289 case eStopReasonTrace:
290 s->PutCString("trace");
291 break;
292
293 case eStopReasonBreakpoint:
294 {
295 bool no_details = true;
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000296 s->PutCString ("breakpoint");
Chris Lattner24943d22010-06-08 16:52:24 +0000297 if (m_thread)
298 {
299 BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByID(m_details.breakpoint.bp_site_id);
300 if (bp_site_sp)
301 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000302 // Only report the breakpoint locations that actually caused this hit - some of them may
303 // have options that would have caused us not to stop here...
304 uint32_t num_locations = bp_site_sp->GetNumberOfOwners();
305 for (uint32_t i = 0; i < num_locations; i++)
306 {
307 BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(i);
308 if (bp_loc_sp->ValidForThisThread(m_thread))
309 {
310 s->PutCString(" ");
311 bp_loc_sp->GetDescription(s, lldb::eDescriptionLevelBrief);
312 no_details = false;
313 }
314 }
Chris Lattner24943d22010-06-08 16:52:24 +0000315 }
316 }
317
318 if (no_details)
319 s->Printf ("site id: %d", m_details.breakpoint.bp_site_id);
320 }
321 break;
322
323 case eStopReasonWatchpoint:
324 s->Printf("watchpoint (site id = %u)", m_details.watchpoint.watch_id);
325 break;
326
327 case eStopReasonSignal:
328 {
329 s->Printf("signal: signo = %i", m_details.signal.signo);
330 const char * signal_name = m_thread->GetProcess().GetUnixSignals().GetSignalAsCString (m_details.signal.signo);
331 if (signal_name)
332 s->Printf(" (%s)", signal_name);
333 }
334 break;
335
336 case eStopReasonException:
337 {
338 s->Printf("exception: type = 0x%8.8x, data_count = %zu", m_details.exception.type, m_details.exception.data_count);
339 uint32_t i;
340 for (i=0; i<m_details.exception.data_count; ++i)
341 {
342 s->Printf(", data[%u] = 0x%8.8llx", i, m_details.exception.data[i]);
343 }
344 }
345 break;
346
347 case eStopReasonPlanComplete:
348 {
349 m_completed_plan_sp->GetDescription (s, lldb::eDescriptionLevelBrief);
350 }
351 break;
352 }
353 }
354}
355
356bool
357Thread::GetStopInfo (Thread::StopInfo *stop_info)
358{
359 stop_info->SetThread(this);
360 ThreadPlanSP completed_plan = GetCompletedPlan();
361 if (completed_plan != NULL)
362 {
363 stop_info->Clear ();
364 stop_info->SetStopReasonWithPlan (completed_plan);
365 return true;
366 }
367 else
368 return GetRawStopReason (stop_info);
369}
370
371bool
372Thread::ThreadStoppedForAReason (void)
373{
374 Thread::StopInfo stop_info;
375 stop_info.SetThread(this);
376 if (GetRawStopReason (&stop_info))
377 {
378 StopReason reason = stop_info.GetStopReason();
379 if (reason == eStopReasonInvalid || reason == eStopReasonNone)
380 return false;
381 else
382 return true;
383 }
384 else
385 return false;
386}
387
388StateType
389Thread::GetState() const
390{
391 // If any other threads access this we will need a mutex for it
392 Mutex::Locker locker(m_state_mutex);
393 return m_state;
394}
395
396void
397Thread::SetState(StateType state)
398{
399 Mutex::Locker locker(m_state_mutex);
400 m_state = state;
401}
402
403void
404Thread::WillStop()
405{
406 ThreadPlan *current_plan = GetCurrentPlan();
407
408 // FIXME: I may decide to disallow threads with no plans. In which
409 // case this should go to an assert.
410
411 if (!current_plan)
412 return;
413
414 current_plan->WillStop();
415}
416
417void
418Thread::SetupForResume ()
419{
420 if (GetResumeState() != eStateSuspended)
421 {
422
423 // If we're at a breakpoint push the step-over breakpoint plan. Do this before
424 // telling the current plan it will resume, since we might change what the current
425 // plan is.
426
427 lldb::addr_t pc = GetRegisterContext()->GetPC();
428 BreakpointSiteSP bp_site_sp = GetProcess().GetBreakpointSiteList().FindByAddress(pc);
429 if (bp_site_sp && bp_site_sp->IsEnabled())
430 {
431 // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything
432 // special to step over a breakpoint.
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000433
434 ThreadPlan *cur_plan = GetCurrentPlan();
Chris Lattner24943d22010-06-08 16:52:24 +0000435
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000436 if (cur_plan->GetKind() != ThreadPlan::eKindStepOverBreakpoint)
437 {
438 ThreadPlanStepOverBreakpoint *step_bp_plan = new ThreadPlanStepOverBreakpoint (*this);
439 if (step_bp_plan)
Chris Lattner24943d22010-06-08 16:52:24 +0000440 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000441 ThreadPlanSP step_bp_plan_sp;
442 step_bp_plan->SetPrivate (true);
443
Chris Lattner24943d22010-06-08 16:52:24 +0000444 if (GetCurrentPlan()->RunState() != eStateStepping)
445 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000446 step_bp_plan->SetAutoContinue(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000447 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000448 step_bp_plan_sp.reset (step_bp_plan);
Chris Lattner24943d22010-06-08 16:52:24 +0000449 QueueThreadPlan (step_bp_plan_sp, false);
450 }
451 }
452 }
453 }
454}
455
456bool
457Thread::WillResume (StateType resume_state)
458{
459 // At this point clear the completed plan stack.
460 m_completed_plan_stack.clear();
461 m_discarded_plan_stack.clear();
462
463 // If this thread stopped with a signal, work out what its resume state should
464 // be. Note if the thread resume state is already set, then don't override it,
465 // the user must have asked us to resume with some other signal.
466
467 if (GetResumeSignal() == LLDB_INVALID_SIGNAL_NUMBER)
468 {
469 Thread::StopInfo stop_info;
470 GetRawStopReason(&stop_info);
471
472 StopReason reason = stop_info.GetStopReason();
473 if (reason == eStopReasonSignal)
474 {
475 UnixSignals &signals = GetProcess().GetUnixSignals();
476 int32_t signo = stop_info.GetSignal();
477 if (!signals.GetShouldSuppress(signo))
478 {
479 SetResumeSignal(signo);
480 }
481 }
482 }
483
484 // Tell all the plans that we are about to resume in case they need to clear any state.
485 // We distinguish between the plan on the top of the stack and the lower
486 // plans in case a plan needs to do any special business before it runs.
487
488 ThreadPlan *plan_ptr = GetCurrentPlan();
489 plan_ptr->WillResume(resume_state, true);
490
491 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
492 {
493 plan_ptr->WillResume (resume_state, false);
494 }
495 return true;
496}
497
498void
499Thread::DidResume ()
500{
501 SetResumeSignal (LLDB_INVALID_SIGNAL_NUMBER);
502}
503
504bool
505Thread::ShouldStop (Event* event_ptr)
506{
507 ThreadPlan *current_plan = GetCurrentPlan();
508 bool should_stop = true;
509
510 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
511 if (log)
512 {
513 StreamString s;
514 DumpThreadPlans(&s);
515 log->PutCString (s.GetData());
516 }
517
518 if (current_plan->PlanExplainsStop())
519 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000520 bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000521 while (1)
522 {
523 should_stop = current_plan->ShouldStop(event_ptr);
524 if (current_plan->MischiefManaged())
525 {
526 if (should_stop)
527 current_plan->WillStop();
528
529 // If a Master Plan wants to stop, and wants to stick on the stack, we let it.
530 // Otherwise, see if the plan's parent wants to stop.
531
532 if (should_stop && current_plan->IsMasterPlan() && !current_plan->OkayToDiscard())
533 {
534 PopPlan();
535 break;
536 }
537 else
538 {
539
540 PopPlan();
541
542 current_plan = GetCurrentPlan();
543 if (current_plan == NULL)
544 {
545 break;
546 }
547 }
548
549 }
550 else
551 {
552 break;
553 }
554 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000555 if (over_ride_stop)
556 should_stop = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000557 }
558 else
559 {
560 // If the current plan doesn't explain the stop, then, find one that
561 // does and let it handle the situation.
562 ThreadPlan *plan_ptr = current_plan;
563 while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
564 {
565 if (plan_ptr->PlanExplainsStop())
566 {
567 should_stop = plan_ptr->ShouldStop (event_ptr);
568 break;
569 }
570
571 }
572 }
573
574 return should_stop;
575}
576
577Vote
578Thread::ShouldReportStop (Event* event_ptr)
579{
580 StateType thread_state = GetResumeState ();
581 if (thread_state == eStateSuspended
582 || thread_state == eStateInvalid)
583 return eVoteNoOpinion;
584
585 if (m_completed_plan_stack.size() > 0)
586 {
587 // Don't use GetCompletedPlan here, since that suppresses private plans.
588 return m_completed_plan_stack.back()->ShouldReportStop (event_ptr);
589 }
590 else
591 return GetCurrentPlan()->ShouldReportStop (event_ptr);
592}
593
594Vote
595Thread::ShouldReportRun (Event* event_ptr)
596{
597 StateType thread_state = GetResumeState ();
598 if (thread_state == eStateSuspended
599 || thread_state == eStateInvalid)
600 return eVoteNoOpinion;
601
602 if (m_completed_plan_stack.size() > 0)
603 {
604 // Don't use GetCompletedPlan here, since that suppresses private plans.
605 return m_completed_plan_stack.back()->ShouldReportRun (event_ptr);
606 }
607 else
608 return GetCurrentPlan()->ShouldReportRun (event_ptr);
609}
610
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000611bool
612Thread::MatchesSpec (const ThreadSpec *spec)
613{
614 if (spec == NULL)
615 return true;
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000616
Jim Ingham649492b2010-06-18 01:00:58 +0000617 return spec->ThreadPassesBasicTests(this);
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000618}
619
Chris Lattner24943d22010-06-08 16:52:24 +0000620void
621Thread::PushPlan (ThreadPlanSP &thread_plan_sp)
622{
623 if (thread_plan_sp)
624 {
625 if (thread_plan_sp->IsImmediate())
626 m_immediate_plan_stack.push_back (thread_plan_sp);
627 else
628 m_plan_stack.push_back (thread_plan_sp);
629
630 thread_plan_sp->DidPush();
631
632 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
633 if (log)
634 {
635 StreamString s;
636 thread_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull);
637 log->Printf("Pushing plan: \"%s\" for thread: %d immediate: %s.",
638 s.GetData(),
639 thread_plan_sp->GetThread().GetID(),
640 thread_plan_sp->IsImmediate() ? "true" : "false");
641 }
642 }
643}
644
645void
646Thread::PopPlan ()
647{
648 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
649
650 if (!m_immediate_plan_stack.empty())
651 {
652 ThreadPlanSP &plan = m_immediate_plan_stack.back();
653 if (log)
654 {
655 log->Printf("Popping plan: \"%s\" for thread: %d immediate: true.", plan->GetName(), plan->GetThread().GetID());
656 }
657 plan->WillPop();
658 m_immediate_plan_stack.pop_back();
659 }
660 else if (m_plan_stack.empty())
661 return;
662 else
663 {
664 ThreadPlanSP &plan = m_plan_stack.back();
665 if (log)
666 {
667 log->Printf("Popping plan: \"%s\" for thread: 0x%x immediate: false.", plan->GetName(), plan->GetThread().GetID());
668 }
669 m_completed_plan_stack.push_back (plan);
670 plan->WillPop();
671 m_plan_stack.pop_back();
672 }
673}
674
675void
676Thread::DiscardPlan ()
677{
678 if (m_plan_stack.size() > 1)
679 {
680 ThreadPlanSP &plan = m_plan_stack.back();
681 m_discarded_plan_stack.push_back (plan);
682 plan->WillPop();
683 m_plan_stack.pop_back();
684 }
685}
686
687ThreadPlan *
688Thread::GetCurrentPlan ()
689{
690 if (!m_immediate_plan_stack.empty())
691 return m_immediate_plan_stack.back().get();
692 else if (m_plan_stack.empty())
693 return NULL;
694 else
695 return m_plan_stack.back().get();
696}
697
698ThreadPlanSP
699Thread::GetCompletedPlan ()
700{
701 ThreadPlanSP empty_plan_sp;
702 if (!m_completed_plan_stack.empty())
703 {
704 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
705 {
706 ThreadPlanSP completed_plan_sp;
707 completed_plan_sp = m_completed_plan_stack[i];
708 if (!completed_plan_sp->GetPrivate ())
709 return completed_plan_sp;
710 }
711 }
712 return empty_plan_sp;
713}
714
715bool
716Thread::IsThreadPlanDone (ThreadPlan *plan)
717{
718 ThreadPlanSP empty_plan_sp;
719 if (!m_completed_plan_stack.empty())
720 {
721 for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
722 {
723 if (m_completed_plan_stack[i].get() == plan)
724 return true;
725 }
726 }
727 return false;
728}
729
730bool
731Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
732{
733 ThreadPlanSP empty_plan_sp;
734 if (!m_discarded_plan_stack.empty())
735 {
736 for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--)
737 {
738 if (m_discarded_plan_stack[i].get() == plan)
739 return true;
740 }
741 }
742 return false;
743}
744
745ThreadPlan *
746Thread::GetPreviousPlan (ThreadPlan *current_plan)
747{
748 if (current_plan == NULL)
749 return NULL;
750
751 int stack_size = m_completed_plan_stack.size();
752 for (int i = stack_size - 1; i > 0; i--)
753 {
754 if (current_plan == m_completed_plan_stack[i].get())
755 return m_completed_plan_stack[i-1].get();
756 }
757
758 if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
759 {
760 if (m_immediate_plan_stack.size() > 0)
761 return m_immediate_plan_stack.back().get();
762 else if (m_plan_stack.size() > 0)
763 return m_plan_stack.back().get();
764 else
765 return NULL;
766 }
767
768 stack_size = m_immediate_plan_stack.size();
769 for (int i = stack_size - 1; i > 0; i--)
770 {
771 if (current_plan == m_immediate_plan_stack[i].get())
772 return m_immediate_plan_stack[i-1].get();
773 }
774 if (stack_size > 0 && m_immediate_plan_stack[0].get() == current_plan)
775 {
776 if (m_plan_stack.size() > 0)
777 return m_plan_stack.back().get();
778 else
779 return NULL;
780 }
781
782 stack_size = m_plan_stack.size();
783 for (int i = stack_size - 1; i > 0; i--)
784 {
785 if (current_plan == m_plan_stack[i].get())
786 return m_plan_stack[i-1].get();
787 }
788 return NULL;
789}
790
791void
792Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
793{
794 if (abort_other_plans)
795 DiscardThreadPlans(true);
796
797 PushPlan (thread_plan_sp);
798}
799
800void
801Thread::DiscardThreadPlans(bool force)
802{
803 // FIXME: It is not always safe to just discard plans. Some, like the step over
804 // breakpoint trap can't be discarded in general (though you can if you plan to
805 // force a return from a function, for instance.
806 // For now I'm just not clearing immediate plans, but I need a way for plans to
807 // say they really need to be kept on, and then a way to override that. Humm...
808
809 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
810 if (log)
811 {
812 log->Printf("Discarding thread plans for thread: 0x%x: force %d.", GetID(), force);
813 }
814
815 if (force)
816 {
817 int stack_size = m_plan_stack.size();
818 for (int i = stack_size - 1; i > 0; i--)
819 {
820 DiscardPlan();
821 }
822 return;
823 }
824
825 while (1)
826 {
827
828 int master_plan_idx;
829 bool discard;
830
831 // Find the first master plan, see if it wants discarding, and if yes discard up to it.
832 for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; master_plan_idx--)
833 {
834 if (m_plan_stack[master_plan_idx]->IsMasterPlan())
835 {
836 discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
837 break;
838 }
839 }
840
841 if (discard)
842 {
843 // First pop all the dependent plans:
844 for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
845 {
846
847 // FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
848 // for the plan leaves it in a state that it is safe to pop the plan
849 // with no more notice?
850 DiscardPlan();
851 }
852
853 // Now discard the master plan itself.
854 // The bottom-most plan never gets discarded. "OkayToDiscard" for it means
855 // discard it's dependent plans, but not it...
856 if (master_plan_idx > 0)
857 {
858 DiscardPlan();
859 }
860 }
861 else
862 {
863 // If the master plan doesn't want to get discarded, then we're done.
864 break;
865 }
866
867 }
868 // FIXME: What should we do about the immediate plans?
869}
870
871ThreadPlan *
872Thread::QueueFundamentalPlan (bool abort_other_plans)
873{
874 ThreadPlanSP thread_plan_sp (new ThreadPlanBase(*this));
875 QueueThreadPlan (thread_plan_sp, abort_other_plans);
876 return thread_plan_sp.get();
877}
878
879ThreadPlan *
880Thread::QueueThreadPlanForStepSingleInstruction (bool step_over, bool abort_other_plans, bool stop_other_threads)
881{
882 ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
883 QueueThreadPlan (thread_plan_sp, abort_other_plans);
884 return thread_plan_sp.get();
885}
886
887ThreadPlan *
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000888Thread::QueueThreadPlanForStepRange
889(
890 bool abort_other_plans,
891 StepType type,
892 const AddressRange &range,
893 const SymbolContext &addr_context,
894 lldb::RunMode stop_other_threads,
895 bool avoid_code_without_debug_info
896)
Chris Lattner24943d22010-06-08 16:52:24 +0000897{
898 ThreadPlanSP thread_plan_sp;
899 if (type == eStepTypeInto)
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000900 {
901 ThreadPlanStepInRange *plan = new ThreadPlanStepInRange (*this, range, addr_context, stop_other_threads);
902 if (avoid_code_without_debug_info)
903 plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
904 else
905 plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
906 thread_plan_sp.reset (plan);
907 }
Chris Lattner24943d22010-06-08 16:52:24 +0000908 else
909 thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads));
910
911 QueueThreadPlan (thread_plan_sp, abort_other_plans);
912 return thread_plan_sp.get();
913}
914
915
916ThreadPlan *
917Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
918{
919 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
920 QueueThreadPlan (thread_plan_sp, abort_other_plans);
921 return thread_plan_sp.get();
922}
923
924ThreadPlan *
925Thread::QueueThreadPlanForStepOut (bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
926 bool stop_other_threads, Vote stop_vote, Vote run_vote)
927{
928 ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote));
929 QueueThreadPlan (thread_plan_sp, abort_other_plans);
930 return thread_plan_sp.get();
931}
932
933ThreadPlan *
934Thread::QueueThreadPlanForStepThrough (bool abort_other_plans, bool stop_other_threads)
935{
936 ThreadPlanSP thread_plan_sp(GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (*this, stop_other_threads));
937 if (thread_plan_sp.get() == NULL)
938 {
939 thread_plan_sp.reset(new ThreadPlanStepThrough (*this, stop_other_threads));
940 if (thread_plan_sp && !thread_plan_sp->ValidatePlan (NULL))
941 return false;
942 }
943 QueueThreadPlan (thread_plan_sp, abort_other_plans);
944 return thread_plan_sp.get();
945}
946
947ThreadPlan *
Chris Lattner24943d22010-06-08 16:52:24 +0000948Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
949 Address& function,
950 lldb::addr_t arg,
951 bool stop_other_threads,
952 bool discard_on_error)
953{
954 ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
955 QueueThreadPlan (thread_plan_sp, abort_other_plans);
956 return thread_plan_sp.get();
957}
958
959ThreadPlan *
960Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
961 Address& function,
962 ValueList &args,
963 bool stop_other_threads,
964 bool discard_on_error)
965{
966 ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, args, stop_other_threads, discard_on_error));
967 QueueThreadPlan (thread_plan_sp, abort_other_plans);
968 return thread_plan_sp.get();
969}
970
971ThreadPlan *
972Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
973 Address &target_addr,
974 bool stop_other_threads)
975{
976 ThreadPlanSP thread_plan_sp (new ThreadPlanRunToAddress (*this, target_addr, stop_other_threads));
977 QueueThreadPlan (thread_plan_sp, abort_other_plans);
978 return thread_plan_sp.get();
979}
980
981ThreadPlan *
982Thread::QueueThreadPlanForStepUntil (bool abort_other_plans,
983 lldb::addr_t *address_list,
984 size_t num_addresses,
985 bool stop_other_threads)
986{
987 ThreadPlanSP thread_plan_sp (new ThreadPlanStepUntil (*this, address_list, num_addresses, stop_other_threads));
988 QueueThreadPlan (thread_plan_sp, abort_other_plans);
989 return thread_plan_sp.get();
990
991}
992
993uint32_t
994Thread::GetIndexID () const
995{
996 return m_index_id;
997}
998
999void
1000Thread::DumpThreadPlans (lldb_private::Stream *s) const
1001{
1002 uint32_t stack_size = m_plan_stack.size();
Jim Ingham3c7b5b92010-06-16 02:00:15 +00001003 s->Printf ("Plan Stack for thread #%u: tid = 0x%4.4x - %d elements.\n", GetIndexID(), GetID(), stack_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001004 for (int i = stack_size - 1; i > 0; i--)
1005 {
1006 s->Printf ("Element %d: ", i);
1007 s->IndentMore();
1008 m_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
1009 s->IndentLess();
1010 s->EOL();
1011 }
1012
1013 stack_size = m_immediate_plan_stack.size();
1014 s->Printf ("Immediate Plan Stack: %d elements.\n", stack_size);
1015 for (int i = stack_size - 1; i > 0; i--)
1016 {
1017 s->Printf ("Element %d: ", i);
1018 s->IndentMore();
1019 m_immediate_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
1020 s->IndentLess();
1021 s->EOL();
1022 }
1023
1024 stack_size = m_completed_plan_stack.size();
1025 s->Printf ("Completed Plan Stack: %d elements.\n", stack_size);
1026 for (int i = stack_size - 1; i > 0; i--)
1027 {
1028 s->Printf ("Element %d: ", i);
1029 s->IndentMore();
1030 m_completed_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
1031 s->IndentLess();
1032 s->EOL();
1033 }
1034
1035 stack_size = m_discarded_plan_stack.size();
1036 s->Printf ("Discarded Plan Stack: %d elements.\n", stack_size);
1037 for (int i = stack_size - 1; i > 0; i--)
1038 {
1039 s->Printf ("Element %d: ", i);
1040 s->IndentMore();
1041 m_discarded_plan_stack[i]->GetDescription (s, eDescriptionLevelFull);
1042 s->IndentLess();
1043 s->EOL();
1044 }
1045
1046}
1047
1048Target *
1049Thread::CalculateTarget ()
1050{
1051 return m_process.CalculateTarget();
1052}
1053
1054Process *
1055Thread::CalculateProcess ()
1056{
1057 return &m_process;
1058}
1059
1060Thread *
1061Thread::CalculateThread ()
1062{
1063 return this;
1064}
1065
1066StackFrame *
1067Thread::CalculateStackFrame ()
1068{
1069 return NULL;
1070}
1071
1072void
1073Thread::Calculate (ExecutionContext &exe_ctx)
1074{
1075 m_process.Calculate (exe_ctx);
1076 exe_ctx.thread = this;
1077 exe_ctx.frame = NULL;
1078}
1079
1080lldb::StackFrameSP
1081Thread::GetCurrentFrame ()
1082{
1083 return GetStackFrameAtIndex (m_frames.GetCurrentFrameIndex());
1084}
1085
1086uint32_t
1087Thread::SetCurrentFrame (lldb_private::StackFrame *frame)
1088{
1089 return m_frames.SetCurrentFrame(frame);
1090}
1091
1092void
1093Thread::SetCurrentFrameByIndex (uint32_t frame_idx)
1094{
1095 m_frames.SetCurrentFrameByIndex(frame_idx);
1096}
1097
1098void
1099Thread::DumpInfo
1100(
1101 Stream &strm,
1102 bool show_stop_reason,
1103 bool show_name,
1104 bool show_queue,
1105 uint32_t frame_idx
1106)
1107{
1108 strm.Printf("thread #%u: tid = 0x%4.4x", GetIndexID(), GetID());
1109
1110 if (frame_idx != LLDB_INVALID_INDEX32)
1111 {
1112 StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx));
1113 if (frame_sp)
1114 {
1115 strm.PutCString(", ");
1116 frame_sp->Dump (&strm, false);
1117 }
1118 }
1119
1120 if (show_stop_reason)
1121 {
1122 Thread::StopInfo thread_stop_info;
1123 if (GetStopInfo(&thread_stop_info))
1124 {
1125 if (thread_stop_info.GetStopReason() != eStopReasonNone)
1126 {
1127 strm.PutCString(", stop reason = ");
1128 thread_stop_info.Dump(&strm);
1129 }
1130 }
1131 }
1132
1133 if (show_name)
1134 {
1135 const char *name = GetName();
1136 if (name && name[0])
1137 strm.Printf(", name = %s", name);
1138 }
1139
1140 if (show_queue)
1141 {
1142 const char *queue = GetQueueName();
1143 if (queue && queue[0])
1144 strm.Printf(", queue = %s", queue);
1145 }
1146}
1147
1148lldb::ThreadSP
1149Thread::GetSP ()
1150{
1151 return m_process.GetThreadList().GetThreadSPForThreadPtr(this);
1152}