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                                                 addr_t arg,
41                                                 bool stop_other_threads,
42                                                 bool discard_on_error,
43                                                 addr_t *this_arg,
44                                                 addr_t *cmd_arg) :
45     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
46     m_valid (false),
47     m_stop_other_threads (stop_other_threads),
48     m_function_sp (NULL),
49     m_process (thread.GetProcess()),
50     m_thread (thread),
51     m_takedown_done (false)
52 {
53     SetOkayToDiscard (discard_on_error);
54 
55     Process& process = thread.GetProcess();
56     Target& target = process.GetTarget();
57     const ABI *abi = process.GetABI().get();
58 
59     if (!abi)
60         return;
61 
62     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
63 
64     SetBreakpoints();
65 
66     m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
67 
68     ModuleSP executableModuleSP (target.GetExecutableModule());
69 
70     if (!executableModuleSP)
71     {
72         log->Printf ("Can't execute code without an executable module.");
73         return;
74     }
75     else
76     {
77         ObjectFile *objectFile = executableModuleSP->GetObjectFile();
78         if (!objectFile)
79         {
80             log->Printf ("Could not find object file for module \"%s\".",
81                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
82             return;
83         }
84         m_start_addr = objectFile->GetEntryPointAddress();
85         if (!m_start_addr.IsValid())
86         {
87             log->Printf ("Could not find entry point address for executable module \"%s\".",
88                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
89             return;
90         }
91     }
92 
93     addr_t start_load_addr = m_start_addr.GetLoadAddress(&target);
94 
95     // Checkpoint the thread state so we can restore it later.
96     if (log && log->GetVerbose())
97         ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
98 
99     if (!thread.CheckpointThreadState (m_stored_thread_state))
100     {
101         if (log)
102             log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
103         return;
104     }
105     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
106     thread.SetStopInfoToNothing();
107 
108     m_function_addr = function;
109     addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
110 
111     if (this_arg && cmd_arg)
112     {
113         if (!abi->PrepareTrivialCall (thread,
114                                       m_function_sp,
115                                       FunctionLoadAddr,
116                                       start_load_addr,
117                                       this_arg,
118                                       cmd_arg,
119                                       &arg))
120             return;
121     }
122     else if (this_arg)
123     {
124         if (!abi->PrepareTrivialCall (thread,
125                                       m_function_sp,
126                                       FunctionLoadAddr,
127                                       start_load_addr,
128                                       this_arg,
129                                       &arg))
130             return;
131     }
132     else
133     {
134         if (!abi->PrepareTrivialCall (thread,
135                                       m_function_sp,
136                                       FunctionLoadAddr,
137                                       start_load_addr,
138                                       &arg))
139             return;
140     }
141 
142     ReportRegisterState ("Function call was set up.  Register state was:");
143 
144     m_valid = true;
145 }
146 
147 
148 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
149                                                 Address &function,
150                                                 bool stop_other_threads,
151                                                 bool discard_on_error,
152                                                 addr_t *arg1_ptr,
153                                                 addr_t *arg2_ptr,
154                                                 addr_t *arg3_ptr,
155                                                 addr_t *arg4_ptr,
156                                                 addr_t *arg5_ptr,
157                                                 addr_t *arg6_ptr) :
158     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
159     m_valid (false),
160     m_stop_other_threads (stop_other_threads),
161     m_function_sp(NULL),
162     m_process (thread.GetProcess()),
163     m_thread (thread),
164     m_takedown_done (false)
165 {
166     SetOkayToDiscard (discard_on_error);
167 
168     Process& process = thread.GetProcess();
169     Target& target = process.GetTarget();
170     const ABI *abi = process.GetABI().get();
171 
172     if (!abi)
173         return;
174 
175     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
176 
177     SetBreakpoints();
178 
179     m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
180 
181     ModuleSP executableModuleSP (target.GetExecutableModule());
182 
183     if (!executableModuleSP)
184     {
185         log->Printf ("Can't execute code without an executable module.");
186         return;
187     }
188     else
189     {
190         ObjectFile *objectFile = executableModuleSP->GetObjectFile();
191         if (!objectFile)
192         {
193             log->Printf ("Could not find object file for module \"%s\".",
194                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
195             return;
196         }
197         m_start_addr = objectFile->GetEntryPointAddress();
198         if (!m_start_addr.IsValid())
199         {
200             if (log)
201                 log->Printf ("Could not find entry point address for executable module \"%s\".",
202                              executableModuleSP->GetFileSpec().GetFilename().AsCString());
203             return;
204         }
205     }
206 
207     addr_t start_load_addr = m_start_addr.GetLoadAddress(&target);
208 
209     // Checkpoint the thread state so we can restore it later.
210     if (log && log->GetVerbose())
211         ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
212 
213     if (!thread.CheckpointThreadState (m_stored_thread_state))
214     {
215         if (log)
216             log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
217         return;
218     }
219     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
220     thread.SetStopInfoToNothing();
221 
222     m_function_addr = function;
223     addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
224 
225     if (!abi->PrepareTrivialCall (thread,
226                                   m_function_sp,
227                                   FunctionLoadAddr,
228                                   start_load_addr,
229                                   arg1_ptr,
230                                   arg2_ptr,
231                                   arg3_ptr,
232                                   arg4_ptr,
233                                   arg5_ptr,
234                                   arg6_ptr))
235     {
236             return;
237     }
238 
239     ReportRegisterState ("Function call was set up.  Register state was:");
240 
241     m_valid = true;
242 }
243 
244 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
245 {
246 }
247 
248 void
249 ThreadPlanCallFunction::ReportRegisterState (const char *message)
250 {
251     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE));
252     if (log)
253     {
254         StreamString strm;
255         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
256 
257         log->PutCString(message);
258 
259         RegisterValue reg_value;
260 
261         for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
262              reg_idx < num_registers;
263              ++reg_idx)
264         {
265             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx);
266             if (reg_ctx->ReadRegister(reg_info, reg_value))
267             {
268                 reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
269                 strm.EOL();
270             }
271         }
272         log->PutCString(strm.GetData());
273     }
274 }
275 
276 void
277 ThreadPlanCallFunction::DoTakedown ()
278 {
279     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
280     if (!m_takedown_done)
281     {
282         // TODO: how do we tell if all went well?
283         if (m_return_value_sp)
284         {
285             const ABI *abi = m_thread.GetProcess().GetABI().get();
286             if (abi)
287                 abi->GetReturnValue(m_thread, *m_return_value_sp);
288         }
289         if (log)
290             log->Printf ("DoTakedown called for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
291         m_takedown_done = true;
292         m_real_stop_info_sp = GetPrivateStopReason();
293         m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
294         SetPlanComplete();
295         ClearBreakpoints();
296         if (log && log->GetVerbose())
297             ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
298 
299     }
300     else
301     {
302         if (log)
303             log->Printf ("DoTakedown called as no-op for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
304     }
305 }
306 
307 void
308 ThreadPlanCallFunction::WillPop ()
309 {
310     DoTakedown();
311 }
312 
313 void
314 ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level)
315 {
316     if (level == eDescriptionLevelBrief)
317     {
318         s->Printf("Function call thread plan");
319     }
320     else
321     {
322         s->Printf("Thread plan to call 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()));
323     }
324 }
325 
326 bool
327 ThreadPlanCallFunction::ValidatePlan (Stream *error)
328 {
329     if (!m_valid)
330         return false;
331 
332     return true;
333 }
334 
335 bool
336 ThreadPlanCallFunction::PlanExplainsStop ()
337 {
338     m_real_stop_info_sp = GetPrivateStopReason();
339 
340     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
341     // we answer yes.
342     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
343         return true;
344 
345     // Check if the breakpoint is one of ours.
346 
347     if (BreakpointsExplainStop())
348         return true;
349 
350     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
351     if (!OkayToDiscard())
352         return false;
353 
354     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
355     // If it is not an internal breakpoint, consult OkayToDiscard.
356 
357     if (m_real_stop_info_sp && m_real_stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
358     {
359         uint64_t break_site_id = m_real_stop_info_sp->GetValue();
360         BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
361         if (bp_site_sp)
362         {
363             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
364             bool is_internal = true;
365             for (uint32_t i = 0; i < num_owners; i++)
366             {
367                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
368 
369                 if (!bp.IsInternal())
370                 {
371                     is_internal = false;
372                     break;
373                 }
374             }
375             if (is_internal)
376                 return false;
377         }
378 
379         return OkayToDiscard();
380     }
381     else
382     {
383         // If the subplan is running, any crashes are attributable to us.
384         // If we want to discard the plan, then we say we explain the stop
385         // but if we are going to be discarded, let whoever is above us
386         // explain the stop.
387         return ((m_subplan_sp.get() != NULL) && !OkayToDiscard());
388     }
389 }
390 
391 bool
392 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
393 {
394     if (PlanExplainsStop())
395     {
396         ReportRegisterState ("Function completed.  Register state was:");
397 
398         DoTakedown();
399 
400         return true;
401     }
402     else
403     {
404         return false;
405     }
406 }
407 
408 bool
409 ThreadPlanCallFunction::StopOthers ()
410 {
411     return m_stop_other_threads;
412 }
413 
414 void
415 ThreadPlanCallFunction::SetStopOthers (bool new_value)
416 {
417     if (m_subplan_sp)
418     {
419         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
420         address_plan->SetStopOthers(new_value);
421     }
422     m_stop_other_threads = new_value;
423 }
424 
425 StateType
426 ThreadPlanCallFunction::GetPlanRunState ()
427 {
428     return eStateRunning;
429 }
430 
431 void
432 ThreadPlanCallFunction::DidPush ()
433 {
434 //#define SINGLE_STEP_EXPRESSIONS
435 
436 #ifndef SINGLE_STEP_EXPRESSIONS
437     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
438 
439     m_thread.QueueThreadPlan(m_subplan_sp, false);
440     m_subplan_sp->SetPrivate (true);
441 #endif
442 }
443 
444 bool
445 ThreadPlanCallFunction::WillStop ()
446 {
447     return true;
448 }
449 
450 bool
451 ThreadPlanCallFunction::MischiefManaged ()
452 {
453     if (IsPlanComplete())
454     {
455         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
456 
457         if (log)
458             log->Printf("Completed call function plan.");
459 
460         ThreadPlan::MischiefManaged ();
461         return true;
462     }
463     else
464     {
465         return false;
466     }
467 }
468 
469 void
470 ThreadPlanCallFunction::SetBreakpoints ()
471 {
472     m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
473     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
474 
475     if (m_cxx_language_runtime)
476         m_cxx_language_runtime->SetExceptionBreakpoints();
477     if (m_objc_language_runtime)
478         m_objc_language_runtime->SetExceptionBreakpoints();
479 }
480 
481 void
482 ThreadPlanCallFunction::ClearBreakpoints ()
483 {
484     if (m_cxx_language_runtime)
485         m_cxx_language_runtime->ClearExceptionBreakpoints();
486     if (m_objc_language_runtime)
487         m_objc_language_runtime->ClearExceptionBreakpoints();
488 }
489 
490 bool
491 ThreadPlanCallFunction::BreakpointsExplainStop()
492 {
493     StopInfoSP stop_info_sp = GetPrivateStopReason();
494 
495     if (m_cxx_language_runtime &&
496         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
497         return true;
498 
499     if (m_objc_language_runtime &&
500         m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
501         return true;
502 
503     return false;
504 }
505