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