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                                                 lldb::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_arg_addr (arg),
49     m_args (NULL),
50     m_process (thread.GetProcess()),
51     m_thread (thread),
52     m_takedown_done (false),
53     m_function_sp(NULL)
54 {
55     SetOkayToDiscard (discard_on_error);
56 
57     Process& process = thread.GetProcess();
58     Target& target = process.GetTarget();
59     const ABI *abi = process.GetABI().get();
60 
61     if (!abi)
62         return;
63 
64     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
65 
66     SetBreakpoints();
67 
68     m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
69 
70     ModuleSP executableModuleSP (target.GetExecutableModule());
71 
72     if (!executableModuleSP)
73     {
74         log->Printf ("Can't execute code without an executable module.");
75         return;
76     }
77     else
78     {
79         ObjectFile *objectFile = executableModuleSP->GetObjectFile();
80         if (!objectFile)
81         {
82             log->Printf ("Could not find object file for module \"%s\".",
83                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
84             return;
85         }
86         m_start_addr = objectFile->GetEntryPointAddress();
87         if (!m_start_addr.IsValid())
88         {
89             log->Printf ("Could not find entry point address for executable module \"%s\".",
90                          executableModuleSP->GetFileSpec().GetFilename().AsCString());
91             return;
92         }
93     }
94 
95     lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target);
96 
97     // Checkpoint the thread state so we can restore it later.
98     if (log && log->GetVerbose())
99         ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
100 
101     if (!thread.CheckpointThreadState (m_stored_thread_state))
102     {
103         if (log)
104             log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
105         return;
106     }
107     // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
108     thread.SetStopInfoToNothing();
109 
110     m_function_addr = function;
111     lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target);
112 
113     if (this_arg && cmd_arg)
114     {
115         if (!abi->PrepareTrivialCall (thread,
116                                       m_function_sp,
117                                       FunctionLoadAddr,
118                                       StartLoadAddr,
119                                       this_arg,
120                                       cmd_arg,
121                                       &m_arg_addr))
122             return;
123     }
124     else if (this_arg)
125     {
126         if (!abi->PrepareTrivialCall (thread,
127                                       m_function_sp,
128                                       FunctionLoadAddr,
129                                       StartLoadAddr,
130                                       this_arg,
131                                       &m_arg_addr,
132                                       NULL))
133             return;
134     }
135     else
136     {
137         if (!abi->PrepareTrivialCall (thread,
138                                       m_function_sp,
139                                       FunctionLoadAddr,
140                                       StartLoadAddr,
141                                       &m_arg_addr,
142                                       NULL,
143                                       NULL))
144             return;
145     }
146 
147     ReportRegisterState ("Function call was set up.  Register state was:");
148 
149     m_valid = true;
150 }
151 
152 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
153 {
154 }
155 
156 void
157 ThreadPlanCallFunction::ReportRegisterState (const char *message)
158 {
159     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
160     if (log)
161     {
162         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
163 
164         log->PutCString(message);
165 
166         for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
167              register_index < num_registers;
168              ++register_index)
169         {
170             const char *register_name = reg_ctx->GetRegisterName(register_index);
171             uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
172 
173             log->Printf("  %s = 0x%llx", register_name, register_value);
174         }
175     }
176 }
177 
178 void
179 ThreadPlanCallFunction::DoTakedown ()
180 {
181     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
182     if (!m_takedown_done)
183     {
184         if (log)
185             log->Printf ("DoTakedown called for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
186         m_takedown_done = true;
187         m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
188         SetPlanComplete();
189         ClearBreakpoints();
190         if (log && log->GetVerbose())
191             ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
192 
193     }
194     else
195     {
196         if (log)
197             log->Printf ("DoTakedown called as no-op for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
198     }
199 }
200 
201 void
202 ThreadPlanCallFunction::WillPop ()
203 {
204     DoTakedown();
205 }
206 
207 void
208 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
209 {
210     if (level == lldb::eDescriptionLevelBrief)
211     {
212         s->Printf("Function call thread plan");
213     }
214     else
215     {
216         if (m_args)
217             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
218         else
219             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
220     }
221 }
222 
223 bool
224 ThreadPlanCallFunction::ValidatePlan (Stream *error)
225 {
226     if (!m_valid)
227         return false;
228 
229     return true;
230 }
231 
232 bool
233 ThreadPlanCallFunction::PlanExplainsStop ()
234 {
235     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
236     // we answer yes.
237     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
238         return true;
239 
240     // Check if the breakpoint is one of ours.
241 
242     if (BreakpointsExplainStop())
243         return true;
244 
245     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
246     if (!OkayToDiscard())
247         return false;
248 
249     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
250     // If it is not an internal breakpoint, consult OkayToDiscard.
251     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
252 
253     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
254     {
255         uint64_t break_site_id = stop_info_sp->GetValue();
256         lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
257         if (bp_site_sp)
258         {
259             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
260             bool is_internal = true;
261             for (uint32_t i = 0; i < num_owners; i++)
262             {
263                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
264 
265                 if (!bp.IsInternal())
266                 {
267                     is_internal = false;
268                     break;
269                 }
270             }
271             if (is_internal)
272                 return false;
273         }
274 
275         return OkayToDiscard();
276     }
277     else
278     {
279         // If the subplan is running, any crashes are attributable to us.
280         // If we want to discard the plan, then we say we explain the stop
281         // but if we are going to be discarded, let whoever is above us
282         // explain the stop.
283         return ((m_subplan_sp.get() != NULL) && !OkayToDiscard());
284     }
285 }
286 
287 bool
288 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
289 {
290     if (PlanExplainsStop())
291     {
292         ReportRegisterState ("Function completed.  Register state was:");
293 
294         DoTakedown();
295 
296         return true;
297     }
298     else
299     {
300         return false;
301     }
302 }
303 
304 bool
305 ThreadPlanCallFunction::StopOthers ()
306 {
307     return m_stop_other_threads;
308 }
309 
310 void
311 ThreadPlanCallFunction::SetStopOthers (bool new_value)
312 {
313     if (m_subplan_sp)
314     {
315         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
316         address_plan->SetStopOthers(new_value);
317     }
318     m_stop_other_threads = new_value;
319 }
320 
321 StateType
322 ThreadPlanCallFunction::GetPlanRunState ()
323 {
324     return eStateRunning;
325 }
326 
327 void
328 ThreadPlanCallFunction::DidPush ()
329 {
330 //#define SINGLE_STEP_EXPRESSIONS
331 
332 #ifndef SINGLE_STEP_EXPRESSIONS
333     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
334 
335     m_thread.QueueThreadPlan(m_subplan_sp, false);
336     m_subplan_sp->SetPrivate (true);
337 #endif
338 }
339 
340 bool
341 ThreadPlanCallFunction::WillStop ()
342 {
343     return true;
344 }
345 
346 bool
347 ThreadPlanCallFunction::MischiefManaged ()
348 {
349     if (IsPlanComplete())
350     {
351         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
352 
353         if (log)
354             log->Printf("Completed call function plan.");
355 
356         ThreadPlan::MischiefManaged ();
357         return true;
358     }
359     else
360     {
361         return false;
362     }
363 }
364 
365 void
366 ThreadPlanCallFunction::SetBreakpoints ()
367 {
368     m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
369     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
370 
371     if (m_cxx_language_runtime)
372         m_cxx_language_runtime->SetExceptionBreakpoints();
373     if (m_objc_language_runtime)
374         m_objc_language_runtime->SetExceptionBreakpoints();
375 }
376 
377 void
378 ThreadPlanCallFunction::ClearBreakpoints ()
379 {
380     if (m_cxx_language_runtime)
381         m_cxx_language_runtime->ClearExceptionBreakpoints();
382     if (m_objc_language_runtime)
383         m_objc_language_runtime->ClearExceptionBreakpoints();
384 }
385 
386 bool
387 ThreadPlanCallFunction::BreakpointsExplainStop()
388 {
389     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
390 
391     if (m_cxx_language_runtime &&
392         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
393         return true;
394 
395     if (m_objc_language_runtime &&
396         m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
397         return true;
398 
399     return false;
400 }
401