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