1 //===-- ThreadPlanCallFunction.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/ThreadPlanCallFunction.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/Breakpoint/Breakpoint.h"
18 #include "lldb/Breakpoint/BreakpointLocation.h"
19 #include "lldb/Core/Address.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/Stream.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "lldb/Target/StopInfo.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/ThreadPlanRunToAddress.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 //----------------------------------------------------------------------
33 // ThreadPlanCallFunction: Plan to call a single function
34 //----------------------------------------------------------------------
35 
36 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
37                                                 Address &function,
38                                                 lldb::addr_t arg,
39                                                 bool stop_other_threads,
40                                                 bool discard_on_error,
41                                                 lldb::addr_t *this_arg) :
42     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
43     m_valid (false),
44     m_stop_other_threads (stop_other_threads),
45     m_arg_addr (arg),
46     m_args (NULL),
47     m_process (thread.GetProcess()),
48     m_thread (thread)
49 {
50     SetOkayToDiscard (discard_on_error);
51 
52     Process& process = thread.GetProcess();
53     Target& target = process.GetTarget();
54     const ABI *abi = process.GetABI();
55 
56     if (!abi)
57         return;
58 
59     lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
60 
61     SymbolContextList contexts;
62     SymbolContext context;
63     ModuleSP executableModuleSP (target.GetExecutableModule());
64 
65     if (!executableModuleSP ||
66         !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
67         return;
68 
69     contexts.GetContextAtIndex(0, context);
70 
71     m_start_addr = context.symbol->GetValue();
72     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
73 
74     if (!thread.SaveFrameZeroState(m_register_backup))
75         return;
76 
77     m_function_addr = function;
78     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
79 
80     if (!abi->PrepareTrivialCall(thread,
81                                  spBelowRedZone,
82                                  FunctionLoadAddr,
83                                  StartLoadAddr,
84                                  m_arg_addr,
85                                  this_arg))
86         return;
87 
88     m_valid = true;
89 }
90 
91 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
92                                                 Address &function,
93                                                 ValueList &args,
94                                                 bool stop_other_threads,
95                                                 bool discard_on_error) :
96     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
97     m_valid (false),
98     m_stop_other_threads (stop_other_threads),
99     m_arg_addr (0),
100     m_args (&args),
101     m_process (thread.GetProcess()),
102     m_thread (thread)
103 {
104 
105     SetOkayToDiscard (discard_on_error);
106 
107     Process& process = thread.GetProcess();
108     Target& target = process.GetTarget();
109     const ABI *abi = process.GetABI();
110 
111     if(!abi)
112         return;
113 
114     lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
115 
116     SymbolContextList contexts;
117     SymbolContext context;
118     ModuleSP executableModuleSP (target.GetExecutableModule());
119 
120     if (!executableModuleSP ||
121         !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts))
122         return;
123 
124     contexts.GetContextAtIndex(0, context);
125 
126     m_start_addr = context.symbol->GetValue();
127     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
128 
129     if(!thread.SaveFrameZeroState(m_register_backup))
130         return;
131 
132     m_function_addr = function;
133     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
134 
135     if (!abi->PrepareNormalCall(thread,
136                                 spBelowRedZone,
137                                 FunctionLoadAddr,
138                                 StartLoadAddr,
139                                 *m_args))
140         return;
141 
142     m_valid = true;
143 }
144 
145 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
146 {
147 }
148 
149 void
150 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
151 {
152     if (level == lldb::eDescriptionLevelBrief)
153     {
154         s->Printf("Function call thread plan");
155     }
156     else
157     {
158         if (m_args)
159             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
160         else
161             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
162     }
163 }
164 
165 bool
166 ThreadPlanCallFunction::ValidatePlan (Stream *error)
167 {
168     if (!m_valid)
169         return false;
170 
171     return true;
172 }
173 
174 bool
175 ThreadPlanCallFunction::PlanExplainsStop ()
176 {
177     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
178     // we answer yes.
179     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
180         return true;
181 
182     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
183     if (!OkayToDiscard())
184         return false;
185 
186     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
187     // If it is not an internal breakpoint, consult OkayToDiscard.
188     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
189     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
190     {
191         uint64_t break_site_id = stop_info_sp->GetValue();
192         lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
193         if (bp_site_sp)
194         {
195             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
196             bool is_internal = true;
197             for (uint32_t i = 0; i < num_owners; i++)
198             {
199                 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
200                 {
201                     is_internal = false;
202                     break;
203                 }
204             }
205             if (is_internal)
206                 return false;
207         }
208 
209         return OkayToDiscard();
210     }
211     else
212     {
213         // If the subplan is running, any crashes are attributable to us.
214         return (m_subplan_sp.get() != NULL);
215     }
216 }
217 
218 bool
219 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
220 {
221     if (PlanExplainsStop())
222     {
223         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
224 
225         if (log)
226         {
227             RegisterContext *reg_ctx = m_thread.GetRegisterContext();
228 
229             log->PutCString("Function completed.  Register state was:");
230 
231             for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
232                  register_index < num_registers;
233                  ++register_index)
234             {
235                 const char *register_name = reg_ctx->GetRegisterName(register_index);
236                 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
237 
238                 log->Printf("  %s = 0x%llx", register_name, register_value);
239             }
240         }
241 
242         m_thread.RestoreSaveFrameZero(m_register_backup);
243         m_thread.ClearStackFrames();
244         SetPlanComplete();
245         return true;
246     }
247     else
248     {
249         return false;
250     }
251 }
252 
253 bool
254 ThreadPlanCallFunction::StopOthers ()
255 {
256     return m_stop_other_threads;
257 }
258 
259 void
260 ThreadPlanCallFunction::SetStopOthers (bool new_value)
261 {
262     if (m_subplan_sp)
263     {
264         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
265         address_plan->SetStopOthers(new_value);
266     }
267     m_stop_other_threads = new_value;
268 }
269 
270 StateType
271 ThreadPlanCallFunction::RunState ()
272 {
273     return eStateRunning;
274 }
275 
276 void
277 ThreadPlanCallFunction::DidPush ()
278 {
279 //#define SINGLE_STEP_EXPRESSIONS
280 
281 #ifndef SINGLE_STEP_EXPRESSIONS
282     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
283 
284     m_thread.QueueThreadPlan(m_subplan_sp, false);
285 #endif
286 }
287 
288 bool
289 ThreadPlanCallFunction::WillStop ()
290 {
291     return true;
292 }
293 
294 bool
295 ThreadPlanCallFunction::MischiefManaged ()
296 {
297     if (IsPlanComplete())
298     {
299         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
300 
301         if (log)
302             log->Printf("Completed call function plan.");
303 
304         ThreadPlan::MischiefManaged ();
305         return true;
306     }
307     else
308     {
309         return false;
310     }
311 }
312