1 //===-- ThreadPlanStepThrough.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/Target/ThreadPlanStepThrough.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/lldb-private-log.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Target/DynamicLoader.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // ThreadPlanStepThrough: If the current instruction is a trampoline, step through it
28 // If it is the beginning of the prologue of a function, step through that as well.
29 // FIXME: At present only handles DYLD trampolines.
30 //----------------------------------------------------------------------
31 
32 ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, bool stop_others) :
33     ThreadPlan (ThreadPlan::eKindStepThrough, "Step through trampolines and prologues", thread, eVoteNoOpinion, eVoteNoOpinion),
34     m_start_address (0),
35     m_stop_others (stop_others)
36 {
37     m_start_address = GetThread().GetRegisterContext()->GetPC(0);
38 }
39 
40 ThreadPlanStepThrough::~ThreadPlanStepThrough ()
41 {
42 }
43 
44 void
45 ThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level)
46 {
47     if (level == lldb::eDescriptionLevelBrief)
48         s->Printf ("Step through");
49     else
50     {
51         s->Printf ("Stepping through trampoline code from: ");
52         s->Address(m_start_address, sizeof (addr_t));
53     }
54 }
55 
56 bool
57 ThreadPlanStepThrough::ValidatePlan (Stream *error)
58 {
59     if (HappyToStopHere())
60         return false;
61     else
62         return true;
63 }
64 
65 bool
66 ThreadPlanStepThrough::PlanExplainsStop ()
67 {
68     return true;
69 }
70 
71 bool
72 ThreadPlanStepThrough::ShouldStop (Event *event_ptr)
73 {
74     return true;
75 }
76 
77 bool
78 ThreadPlanStepThrough::StopOthers ()
79 {
80     return m_stop_others;
81 }
82 
83 StateType
84 ThreadPlanStepThrough::RunState ()
85 {
86     return eStateStepping;
87 }
88 
89 bool
90 ThreadPlanStepThrough::WillResume (StateType resume_state, bool current_plan)
91 {
92     ThreadPlan::WillResume(resume_state, current_plan);
93     if (current_plan)
94     {
95         ThreadPlanSP sub_plan_sp(m_thread.GetProcess().GetDynamicLoader()->GetStepThroughTrampolinePlan (m_thread, m_stop_others));
96         if (sub_plan_sp != NULL)
97             PushPlan (sub_plan_sp);
98     }
99     return true;
100 }
101 
102 bool
103 ThreadPlanStepThrough::WillStop ()
104 {
105     return true;
106 }
107 
108 bool
109 ThreadPlanStepThrough::MischiefManaged ()
110 {
111     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
112 
113     // Stop if we're happy with the place we've landed...
114 
115     if (!HappyToStopHere())
116     {
117         // If we are still at the PC we were trying to step over.
118         return false;
119     }
120     else
121     {
122         if (log)
123             log->Printf("Completed step through step plan.");
124         ThreadPlan::MischiefManaged ();
125         return true;
126     }
127 }
128 
129 bool
130 ThreadPlanStepThrough::HappyToStopHere()
131 {
132     // This should again ask the various trampolines whether we are still at a
133     // trampoline point, and if so, continue through the possibly nested trampolines.
134 
135     return true;
136 }
137 
138