ThreadPlanCallFunction.cpp revision 4c3fb4b50a87e6e08987096d7edacc26545f58dc
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                                                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
148ThreadPlanCallFunction::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
244ThreadPlanCallFunction::~ThreadPlanCallFunction ()
245{
246}
247
248void
249ThreadPlanCallFunction::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
276void
277ThreadPlanCallFunction::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
307void
308ThreadPlanCallFunction::WillPop ()
309{
310    DoTakedown();
311}
312
313void
314ThreadPlanCallFunction::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
326bool
327ThreadPlanCallFunction::ValidatePlan (Stream *error)
328{
329    if (!m_valid)
330        return false;
331
332    return true;
333}
334
335bool
336ThreadPlanCallFunction::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
391bool
392ThreadPlanCallFunction::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
408bool
409ThreadPlanCallFunction::StopOthers ()
410{
411    return m_stop_other_threads;
412}
413
414void
415ThreadPlanCallFunction::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
425StateType
426ThreadPlanCallFunction::GetPlanRunState ()
427{
428    return eStateRunning;
429}
430
431void
432ThreadPlanCallFunction::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
444bool
445ThreadPlanCallFunction::WillStop ()
446{
447    return true;
448}
449
450bool
451ThreadPlanCallFunction::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
469void
470ThreadPlanCallFunction::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
481void
482ThreadPlanCallFunction::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
490bool
491ThreadPlanCallFunction::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