ThreadPlanCallFunction.cpp revision 61d4f7adb6936a6d406dd5b20452d0843e538d76
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
31using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// ThreadPlanCallFunction: Plan to call a single function
36//----------------------------------------------------------------------
37
38ThreadPlanCallFunction::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
152ThreadPlanCallFunction::~ThreadPlanCallFunction ()
153{
154}
155
156void
157ThreadPlanCallFunction::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
178void
179ThreadPlanCallFunction::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
201void
202ThreadPlanCallFunction::WillPop ()
203{
204    DoTakedown();
205}
206
207void
208ThreadPlanCallFunction::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
223bool
224ThreadPlanCallFunction::ValidatePlan (Stream *error)
225{
226    if (!m_valid)
227        return false;
228
229    return true;
230}
231
232bool
233ThreadPlanCallFunction::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
287bool
288ThreadPlanCallFunction::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
304bool
305ThreadPlanCallFunction::StopOthers ()
306{
307    return m_stop_other_threads;
308}
309
310void
311ThreadPlanCallFunction::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
321StateType
322ThreadPlanCallFunction::GetPlanRunState ()
323{
324    return eStateRunning;
325}
326
327void
328ThreadPlanCallFunction::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
340bool
341ThreadPlanCallFunction::WillStop ()
342{
343    return true;
344}
345
346bool
347ThreadPlanCallFunction::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
365void
366ThreadPlanCallFunction::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
377void
378ThreadPlanCallFunction::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
386bool
387ThreadPlanCallFunction::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