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();
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 (!abi->PrepareTrivialCall(thread,
114                                  m_function_sp,
115                                  FunctionLoadAddr,
116                                  StartLoadAddr,
117                                  m_arg_addr,
118                                  this_arg,
119                                  cmd_arg))
120         return;
121 
122     ReportRegisterState ("Function call was set up.  Register state was:");
123 
124     m_valid = true;
125 }
126 
127 ThreadPlanCallFunction::~ThreadPlanCallFunction ()
128 {
129 }
130 
131 void
132 ThreadPlanCallFunction::ReportRegisterState (const char *message)
133 {
134     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
135     if (log)
136     {
137         RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
138 
139         log->PutCString(message);
140 
141         for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount();
142              register_index < num_registers;
143              ++register_index)
144         {
145             const char *register_name = reg_ctx->GetRegisterName(register_index);
146             uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS);
147 
148             log->Printf("  %s = 0x%llx", register_name, register_value);
149         }
150     }
151 }
152 
153 void
154 ThreadPlanCallFunction::DoTakedown ()
155 {
156     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
157     if (!m_takedown_done)
158     {
159         if (log)
160             log->Printf ("DoTakedown called for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
161         m_takedown_done = true;
162         m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
163         SetPlanComplete();
164         ClearBreakpoints();
165         if (log && log->GetVerbose())
166             ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
167 
168     }
169     else
170     {
171         if (log)
172             log->Printf ("DoTakedown called as no-op for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
173     }
174 }
175 
176 void
177 ThreadPlanCallFunction::WillPop ()
178 {
179     DoTakedown();
180 }
181 
182 void
183 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level)
184 {
185     if (level == lldb::eDescriptionLevelBrief)
186     {
187         s->Printf("Function call thread plan");
188     }
189     else
190     {
191         if (m_args)
192             s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
193         else
194             s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr);
195     }
196 }
197 
198 bool
199 ThreadPlanCallFunction::ValidatePlan (Stream *error)
200 {
201     if (!m_valid)
202         return false;
203 
204     return true;
205 }
206 
207 bool
208 ThreadPlanCallFunction::PlanExplainsStop ()
209 {
210     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
211     // we answer yes.
212     if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
213         return true;
214 
215     // Check if the breakpoint is one of ours.
216 
217     if (BreakpointsExplainStop())
218         return true;
219 
220     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
221     if (!OkayToDiscard())
222         return false;
223 
224     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
225     // If it is not an internal breakpoint, consult OkayToDiscard.
226     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
227 
228     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
229     {
230         uint64_t break_site_id = stop_info_sp->GetValue();
231         lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
232         if (bp_site_sp)
233         {
234             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
235             bool is_internal = true;
236             for (uint32_t i = 0; i < num_owners; i++)
237             {
238                 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
239 
240                 if (!bp.IsInternal())
241                 {
242                     is_internal = false;
243                     break;
244                 }
245             }
246             if (is_internal)
247                 return false;
248         }
249 
250         return OkayToDiscard();
251     }
252     else
253     {
254         // If the subplan is running, any crashes are attributable to us.
255         // If we want to discard the plan, then we say we explain the stop
256         // but if we are going to be discarded, let whoever is above us
257         // explain the stop.
258         return ((m_subplan_sp.get() != NULL) && !OkayToDiscard());
259     }
260 }
261 
262 bool
263 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
264 {
265     if (PlanExplainsStop())
266     {
267         ReportRegisterState ("Function completed.  Register state was:");
268 
269         DoTakedown();
270 
271         return true;
272     }
273     else
274     {
275         return false;
276     }
277 }
278 
279 bool
280 ThreadPlanCallFunction::StopOthers ()
281 {
282     return m_stop_other_threads;
283 }
284 
285 void
286 ThreadPlanCallFunction::SetStopOthers (bool new_value)
287 {
288     if (m_subplan_sp)
289     {
290         ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
291         address_plan->SetStopOthers(new_value);
292     }
293     m_stop_other_threads = new_value;
294 }
295 
296 StateType
297 ThreadPlanCallFunction::GetPlanRunState ()
298 {
299     return eStateRunning;
300 }
301 
302 void
303 ThreadPlanCallFunction::DidPush ()
304 {
305 //#define SINGLE_STEP_EXPRESSIONS
306 
307 #ifndef SINGLE_STEP_EXPRESSIONS
308     m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
309 
310     m_thread.QueueThreadPlan(m_subplan_sp, false);
311     m_subplan_sp->SetPrivate (true);
312 #endif
313 }
314 
315 bool
316 ThreadPlanCallFunction::WillStop ()
317 {
318     return true;
319 }
320 
321 bool
322 ThreadPlanCallFunction::MischiefManaged ()
323 {
324     if (IsPlanComplete())
325     {
326         LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
327 
328         if (log)
329             log->Printf("Completed call function plan.");
330 
331         ThreadPlan::MischiefManaged ();
332         return true;
333     }
334     else
335     {
336         return false;
337     }
338 }
339 
340 void
341 ThreadPlanCallFunction::SetBreakpoints ()
342 {
343     m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
344     m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
345 
346     if (m_cxx_language_runtime)
347         m_cxx_language_runtime->SetExceptionBreakpoints();
348     if (m_objc_language_runtime)
349         m_objc_language_runtime->SetExceptionBreakpoints();
350 }
351 
352 void
353 ThreadPlanCallFunction::ClearBreakpoints ()
354 {
355     if (m_cxx_language_runtime)
356         m_cxx_language_runtime->ClearExceptionBreakpoints();
357     if (m_objc_language_runtime)
358         m_objc_language_runtime->ClearExceptionBreakpoints();
359 }
360 
361 bool
362 ThreadPlanCallFunction::BreakpointsExplainStop()
363 {
364     lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
365 
366     if (m_cxx_language_runtime &&
367         m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
368         return true;
369 
370     if (m_objc_language_runtime &&
371         m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
372         return true;
373 
374     return false;
375 }
376