18871Srgrimes//===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
24Srgrimes//
34Srgrimes//                     The LLVM Compiler Infrastructure
44Srgrimes//
58871Srgrimes// This file is distributed under the University of Illinois Open Source
64Srgrimes// License. See LICENSE.TXT for details.
74Srgrimes//
84Srgrimes//===----------------------------------------------------------------------===//
94Srgrimes
104Srgrimes#include "lldb/Target/ThreadPlanCallFunction.h"
118871Srgrimes
124Srgrimes// C Includes
134Srgrimes// C++ Includes
144Srgrimes// Other libraries and framework includes
158871Srgrimes#include "llvm/Support/MachO.h"
164Srgrimes// Project includes
178871Srgrimes#include "lldb/lldb-private-log.h"
184Srgrimes#include "lldb/Breakpoint/Breakpoint.h"
194Srgrimes#include "lldb/Breakpoint/BreakpointLocation.h"
204Srgrimes#include "lldb/Core/Address.h"
214Srgrimes#include "lldb/Core/Log.h"
228871Srgrimes#include "lldb/Core/Module.h"
234Srgrimes#include "lldb/Core/Stream.h"
244Srgrimes#include "lldb/Symbol/ObjectFile.h"
254Srgrimes#include "lldb/Target/LanguageRuntime.h"
264Srgrimes#include "lldb/Target/Process.h"
27114589Sobrien#include "lldb/Target/RegisterContext.h"
28114589Sobrien#include "lldb/Target/StopInfo.h"
2937415Scharnier#include "lldb/Target/Target.h"
30103348Sphk#include "lldb/Target/Thread.h"
314Srgrimes#include "lldb/Target/ThreadPlanRunToAddress.h"
32104272Sphk
33113454Sphkusing namespace lldb;
3479681Sjoergusing namespace lldb_private;
3537415Scharnier
3679681Sjoerg//----------------------------------------------------------------------
3737415Scharnier// ThreadPlanCallFunction: Plan to call a single function
3837415Scharnier//----------------------------------------------------------------------
3937415Scharnierbool
4037415ScharnierThreadPlanCallFunction::ConstructorSetup (Thread &thread,
41148035Sphk                                          ABI *& abi,
4279681Sjoerg                                          lldb::addr_t &start_load_addr,
4379681Sjoerg                                          lldb::addr_t &function_load_addr)
44100202Sbde{
454Srgrimes    SetIsMasterPlan (true);
4637415Scharnier    SetOkayToDiscard (false);
4716561Salex    SetPrivate (true);
4816561Salex
494Srgrimes    ProcessSP process_sp (thread.GetProcess());
50227081Sed    if (!process_sp)
514Srgrimes        return false;
52217808Ssobomax
53217808Ssobomax    abi = process_sp->GetABI().get();
54217808Ssobomax
55217808Ssobomax    if (!abi)
564Srgrimes        return false;
574Srgrimes
584Srgrimes    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
594Srgrimes
604Srgrimes    SetBreakpoints();
614Srgrimes
624Srgrimes    m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
634Srgrimes    // If we can't read memory at the point of the process where we are planning to put our function, we're
644Srgrimes    // not going to get any further...
654Srgrimes    Error error;
664Srgrimes    process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
674Srgrimes    if (!error.Success())
68217808Ssobomax    {
694Srgrimes        m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp);
704Srgrimes        if (log)
714Srgrimes            log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
7220061Ssos        return false;
7320061Ssos    }
7493394Sphk
754Srgrimes    Module *exe_module = GetTarget().GetExecutableModulePointer();
7693394Sphk
7710514Sjoerg    if (exe_module == NULL)
7893394Sphk    {
794Srgrimes        m_constructor_errors.Printf ("Can't execute code without an executable module.");
8093394Sphk        if (log)
81145763Snyan            log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
82145763Snyan        return false;
83113454Sphk    }
844Srgrimes    else
854Srgrimes    {
8693394Sphk        ObjectFile *objectFile = exe_module->GetObjectFile();
87148035Sphk        if (!objectFile)
8893394Sphk        {
894Srgrimes            m_constructor_errors.Printf ("Could not find object file for module \"%s\".",
904Srgrimes                                         exe_module->GetFileSpec().GetFilename().AsCString());
9193394Sphk
9293394Sphk            if (log)
9393394Sphk                log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
9493394Sphk            return false;
954Srgrimes        }
964Srgrimes
974Srgrimes        m_start_addr = objectFile->GetEntryPointAddress();
984Srgrimes        if (!m_start_addr.IsValid())
9919459Sjkh        {
10019459Sjkh            m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".",
10119459Sjkh                                         exe_module->GetFileSpec().GetFilename().AsCString());
10219459Sjkh            if (log)
10319459Sjkh                log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
10419459Sjkh            return false;
10519459Sjkh        }
10619459Sjkh    }
10719459Sjkh
10819459Sjkh    start_load_addr = m_start_addr.GetLoadAddress (&GetTarget());
10919459Sjkh
11019459Sjkh    // Checkpoint the thread state so we can restore it later.
111224150Srstone    if (log && log->GetVerbose())
112224150Srstone        ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
113224150Srstone
11419459Sjkh    if (!thread.CheckpointThreadState (m_stored_thread_state))
11519459Sjkh    {
11619459Sjkh        m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
11748282Srnordier        if (log)
11857896Simp            log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
1194Srgrimes        return false;
12048282Srnordier    }
1214Srgrimes    function_load_addr = m_function_addr.GetLoadAddress (&GetTarget());
122181036Sobrien
1234Srgrimes    return true;
12457896Simp}
12595002Strhodes
12619459SjkhThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
12719459Sjkh                                                const Address &function,
128169143Smaxim                                                const ClangASTType &return_type,
1294Srgrimes                                                llvm::ArrayRef<addr_t> args,
130187246Sluigi                                                const EvaluateExpressionOptions &options) :
131187246Sluigi    ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
132187246Sluigi    m_valid (false),
133187246Sluigi    m_stop_other_threads (options.GetStopOthers()),
134187246Sluigi    m_unwind_on_error (options.DoesUnwindOnError()),
135187246Sluigi    m_ignore_breakpoints (options.DoesIgnoreBreakpoints()),
136187246Sluigi    m_debug_execution (options.GetDebug()),
137187246Sluigi    m_trap_exceptions (options.GetTrapExceptions()),
138187246Sluigi    m_function_addr (function),
139187246Sluigi    m_function_sp (0),
140187248Sluigi    m_return_type (return_type),
141187248Sluigi    m_takedown_done (false),
142187246Sluigi    m_should_clear_objc_exception_bp(false),
143187246Sluigi    m_should_clear_cxx_exception_bp (false),
144187246Sluigi    m_stop_address (LLDB_INVALID_ADDRESS)
145187246Sluigi{
146187246Sluigi    lldb::addr_t start_load_addr;
147187246Sluigi    ABI *abi;
148187246Sluigi    lldb::addr_t function_load_addr;
149187246Sluigi    if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
150187246Sluigi        return;
151187246Sluigi
152187246Sluigi    if (!abi->PrepareTrivialCall(thread,
153187246Sluigi                                 m_function_sp,
154187246Sluigi                                 function_load_addr,
155187246Sluigi                                 start_load_addr,
156187248Sluigi                                 args))
157187246Sluigi        return;
158187246Sluigi
159187246Sluigi    ReportRegisterState ("Function call was set up.  Register state was:");
160187246Sluigi
161187246Sluigi    m_valid = true;
162187246Sluigi}
163187246Sluigi
164187246SluigiThreadPlanCallFunction::~ThreadPlanCallFunction ()
165187246Sluigi{
166187246Sluigi    DoTakedown(PlanSucceeded());
167187246Sluigi}
168187246Sluigi
169187246Sluigivoid
170187246SluigiThreadPlanCallFunction::ReportRegisterState (const char *message)
171187246Sluigi{
172187246Sluigi    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE));
173187246Sluigi    if (log)
174187246Sluigi    {
175187246Sluigi        StreamString strm;
176187246Sluigi        RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
177187246Sluigi
178187246Sluigi        log->PutCString(message);
179187246Sluigi
180187246Sluigi        RegisterValue reg_value;
181187246Sluigi
182187246Sluigi        for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
183187246Sluigi             reg_idx < num_registers;
184187246Sluigi             ++reg_idx)
185187246Sluigi        {
186187246Sluigi            const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx);
187187246Sluigi            if (reg_ctx->ReadRegister(reg_info, reg_value))
188187246Sluigi            {
189187246Sluigi                reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
190187246Sluigi                strm.EOL();
191187246Sluigi            }
192187246Sluigi        }
193187246Sluigi        log->PutCString(strm.GetData());
194187246Sluigi    }
195187246Sluigi}
196187246Sluigi
197187246Sluigivoid
198187246SluigiThreadPlanCallFunction::DoTakedown (bool success)
199187246Sluigi{
200187246Sluigi    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
201187246Sluigi
202187246Sluigi    if (!m_valid)
203187246Sluigi    {
204187246Sluigi        //Don't call DoTakedown if we were never valid to begin with.
205187246Sluigi        if (log)
206187246Sluigi            log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.", this);
207187246Sluigi        return;
208187246Sluigi    }
209187246Sluigi
210187246Sluigi    if (!m_takedown_done)
211187248Sluigi    {
212187246Sluigi        if (success)
213187246Sluigi        {
214187246Sluigi            ProcessSP process_sp (m_thread.GetProcess());
215187246Sluigi            const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
216187246Sluigi            if (abi && m_return_type.IsValid())
217187246Sluigi            {
218187246Sluigi                const bool persistent = false;
219187246Sluigi                m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent);
220187246Sluigi            }
221234345Smarck        }
222187246Sluigi        if (log)
223187246Sluigi            log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
2244Srgrimes        m_takedown_done = true;
2254Srgrimes        m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
226187246Sluigi        m_real_stop_info_sp = GetPrivateStopInfo ();
227187246Sluigi        if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state))
228187246Sluigi        {
229187246Sluigi            if (log)
230187246Sluigi                log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state", this);
231187246Sluigi        }
232187246Sluigi        SetPlanComplete(success);
233187246Sluigi        ClearBreakpoints();
234187246Sluigi        if (log && log->GetVerbose())
235187246Sluigi            ReportRegisterState ("Restoring thread state after function call.  Restored register state:");
236227292Sae
237187239Sluigi    }
238187241Sluigi    else
23916561Salex    {
24019459Sjkh        if (log)
24116561Salex            log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
24293394Sphk    }
24316561Salex}
24493394Sphk
24593394Sphkvoid
24679681SjoergThreadPlanCallFunction::WillPop ()
24781164Siedowse{
24893394Sphk    DoTakedown(PlanSucceeded());
24916561Salex}
250148035Sphk
25193394Sphkvoid
25293394SphkThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level)
25393394Sphk{
25493394Sphk    if (level == eDescriptionLevelBrief)
255217808Ssobomax    {
25619459Sjkh        s->Printf("Function call thread plan");
25719459Sjkh    }
25865054Sjhb    else
25937415Scharnier    {
2604Srgrimes        TargetSP target_sp (m_thread.CalculateTarget());
26116561Salex        s->Printf("Thread plan to call 0x%" PRIx64, m_function_addr.GetLoadAddress(target_sp.get()));
26216561Salex    }
2634Srgrimes}
26448282Srnordier
26593394Sphkbool
26693394SphkThreadPlanCallFunction::ValidatePlan (Stream *error)
2674Srgrimes{
268181036Sobrien    if (!m_valid)
26948282Srnordier    {
27048282Srnordier        if (error)
27148282Srnordier        {
2724Srgrimes            if (m_constructor_errors.GetSize() > 0)
27357896Simp                error->PutCString (m_constructor_errors.GetData());
27457896Simp            else
27557896Simp                error->PutCString ("Unknown error");
27648282Srnordier        }
27748282Srnordier        return false;
27848282Srnordier    }
27948282Srnordier
28048282Srnordier    return true;
28148282Srnordier}
28248282Srnordier
28348282Srnordier
28448282SrnordierVote
28548282SrnordierThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
28648282Srnordier{
28748282Srnordier    if (m_takedown_done || IsPlanComplete())
288169143Smaxim        return eVoteYes;
289169143Smaxim    else
290169143Smaxim        return ThreadPlan::ShouldReportStop(event_ptr);
291181036Sobrien}
292181036Sobrien
293181036Sobrienbool
29457896SimpThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
29557896Simp{
29657896Simp    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
29748282Srnordier    m_real_stop_info_sp = GetPrivateStopInfo ();
29848282Srnordier
29948282Srnordier    // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
30048282Srnordier    // we answer yes.
30148282Srnordier    if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr))
30248282Srnordier    {
30348282Srnordier        SetPlanComplete();
30448282Srnordier        return true;
30548282Srnordier    }
30648282Srnordier
30748282Srnordier    // Check if the breakpoint is one of ours.
30848282Srnordier
30948282Srnordier    StopReason stop_reason;
31048282Srnordier    if (!m_real_stop_info_sp)
31148282Srnordier        stop_reason = eStopReasonNone;
31248282Srnordier    else
31348282Srnordier        stop_reason = m_real_stop_info_sp->GetStopReason();
3144Srgrimes    if (log)
31548282Srnordier        log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", Thread::StopReasonAsCString(stop_reason));
31648282Srnordier
31748282Srnordier    if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
31848282Srnordier        return true;
31948282Srnordier
32048282Srnordier    // We control breakpoints separately from other "stop reasons."  So first,
3214Srgrimes    // check the case where we stopped for an internal breakpoint, in that case, continue on.
32279681Sjoerg    // If it is not an internal breakpoint, consult m_ignore_breakpoints.
32379681Sjoerg
32479681Sjoerg
325182844Slulf    if (stop_reason == eStopReasonBreakpoint)
326182844Slulf    {
327187203Sluigi        ProcessSP process_sp (m_thread.CalculateProcess());
32810514Sjoerg        uint64_t break_site_id = m_real_stop_info_sp->GetValue();
32979681Sjoerg        BreakpointSiteSP bp_site_sp;
33079681Sjoerg        if (process_sp)
3314Srgrimes            bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id);
33263027Sjhb        if (bp_site_sp)
33363027Sjhb        {
33463027Sjhb            uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
335159757Ssimon            bool is_internal = true;
336159757Ssimon            for (uint32_t i = 0; i < num_owners; i++)
33763329Sjhb            {
33863329Sjhb                Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
33963027Sjhb                if (log)
340169143Smaxim                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: hit breakpoint %d while calling function", bp.GetID());
341169143Smaxim
342169143Smaxim                if (!bp.IsInternal())
343169143Smaxim                {
344169143Smaxim                    is_internal = false;
345169143Smaxim                    break;
346169143Smaxim                }
347169143Smaxim            }
348187203Sluigi            if (is_internal)
349169143Smaxim            {
350169143Smaxim                if (log)
351169143Smaxim                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop hit an internal breakpoint, not stopping.");
352169143Smaxim                return false;
353169143Smaxim            }
354169143Smaxim        }
355169143Smaxim
356169143Smaxim        if (m_ignore_breakpoints)
357169143Smaxim        {
358169143Smaxim            if (log)
359169143Smaxim                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
360169143Smaxim            m_real_stop_info_sp->OverrideShouldStop(false);
361169143Smaxim            return true;
36293394Sphk        }
36357896Simp        else
36457896Simp        {
36557896Simp            if (log)
36657896Simp                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
36757896Simp            m_real_stop_info_sp->OverrideShouldStop(true);
36857896Simp            return false;
369187203Sluigi        }
37057896Simp    }
37157896Simp    else if (!m_unwind_on_error)
37257896Simp    {
37357896Simp        // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
37457896Simp        return false;
37557896Simp    }
37657896Simp    else
37757896Simp    {
37857896Simp        // If the subplan is running, any crashes are attributable to us.
37957896Simp        // If we want to discard the plan, then we say we explain the stop
3804Srgrimes        // but if we are going to be discarded, let whoever is above us
38119459Sjkh        // explain the stop.
38293394Sphk        // But don't discard the plan if the stop would restart itself (for instance if it is a
38350215Sphk        // signal that is set not to stop.  Check that here first.  We just say we explain the stop
38450215Sphk        // but aren't done and everything will continue on from there.
385187203Sluigi
38650215Sphk        if (m_real_stop_info_sp->ShouldStopSynchronous(event_ptr))
38750215Sphk        {
38850215Sphk            SetPlanComplete(false);
38965054Sjhb            if (m_subplan_sp)
39065054Sjhb            {
39181164Siedowse                if (m_unwind_on_error)
39250215Sphk                    return true;
393187239Sluigi                else
39495002Strhodes                    return false;
39595002Strhodes            }
39650215Sphk            else
39750215Sphk                return false;
39893394Sphk        }
39919459Sjkh        else
40019459Sjkh            return true;
40119459Sjkh    }
40219459Sjkh}
40319459Sjkh
404187239Sluigibool
40519459SjkhThreadPlanCallFunction::ShouldStop (Event *event_ptr)
40619459Sjkh{
40793394Sphk    // We do some computation in DoPlanExplainsStop that may or may not set the plan as complete.
40819459Sjkh    // We need to do that here to make sure our state is correct.
40919459Sjkh    DoPlanExplainsStop(event_ptr);
41019459Sjkh
4114Srgrimes    if (IsPlanComplete())
4124Srgrimes    {
41319459Sjkh        ReportRegisterState ("Function completed.  Register state was:");
41465054Sjhb        return true;
4154Srgrimes    }
41620061Ssos    else
41719459Sjkh    {
41819459Sjkh        return false;
41919459Sjkh    }
42026421Sbrian}
42119459Sjkh
42219459Sjkhbool
4234SrgrimesThreadPlanCallFunction::StopOthers ()
4244Srgrimes{
42519459Sjkh    return m_stop_other_threads;
4264Srgrimes}
4274Srgrimes
42848282Srnordiervoid
42943054SrnordierThreadPlanCallFunction::SetStopOthers (bool new_value)
43043054Srnordier{
43148282Srnordier    if (m_subplan_sp)
43295002Strhodes    {
43319459Sjkh        ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
43419459Sjkh        address_plan->SetStopOthers(new_value);
43519459Sjkh    }
436187239Sluigi    m_stop_other_threads = new_value;
43795002Strhodes}
43819459Sjkh
4394SrgrimesStateType
440145763SnyanThreadPlanCallFunction::GetPlanRunState ()
44119459Sjkh{
44219459Sjkh    return eStateRunning;
44319459Sjkh}
4444Srgrimes
4454Srgrimesvoid
4464SrgrimesThreadPlanCallFunction::DidPush ()
44737415Scharnier{
4484Srgrimes//#define SINGLE_STEP_EXPRESSIONS
44937415Scharnier
45037415Scharnier    // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
45137415Scharnier    // Wait till the plan is pushed so we aren't changing the stop info till we're about to run.
45248282Srnordier
453181036Sobrien    GetThread().SetStopInfoToNothing();
45448282Srnordier
45537415Scharnier#ifndef SINGLE_STEP_EXPRESSIONS
4564Srgrimes    m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
4574Srgrimes
45816561Salex    m_thread.QueueThreadPlan(m_subplan_sp, false);
459187239Sluigi    m_subplan_sp->SetPrivate (true);
4604Srgrimes#endif
46193394Sphk}
4624Srgrimes
4634Srgrimesbool
4644SrgrimesThreadPlanCallFunction::WillStop ()
465187241Sluigi{
466187241Sluigi    return true;
467187241Sluigi}
468187241Sluigi
4694Srgrimesbool
4704SrgrimesThreadPlanCallFunction::MischiefManaged ()
47193394Sphk{
4724Srgrimes    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
47316561Salex
474187241Sluigi    if (IsPlanComplete())
4754Srgrimes    {
47626389Sgibbs        if (log)
4774Srgrimes            log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this);
4784Srgrimes
4794Srgrimes        ThreadPlan::MischiefManaged ();
4804Srgrimes        return true;
4814Srgrimes    }
48226389Sgibbs    else
48326389Sgibbs    {
48426389Sgibbs        return false;
48526389Sgibbs    }
48626389Sgibbs}
48726389Sgibbs
48890866Sjoevoid
48990866SjoeThreadPlanCallFunction::SetBreakpoints ()
490100202Sbde{
49137244Sbde    ProcessSP process_sp (m_thread.CalculateProcess());
492226908Sjmg    if (m_trap_exceptions && process_sp)
493100202Sbde    {
49434952Sobrien        m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
49534952Sobrien        m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
49669371Sobrien
4974Srgrimes        if (m_cxx_language_runtime)
49869371Sobrien        {
4994Srgrimes            m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
5004Srgrimes            m_cxx_language_runtime->SetExceptionBreakpoints();
50169371Sobrien        }
50269371Sobrien        if (m_objc_language_runtime)
5034Srgrimes        {
5044Srgrimes            m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet();
50519459Sjkh            m_objc_language_runtime->SetExceptionBreakpoints();
50616561Salex        }
50719459Sjkh    }
50819459Sjkh}
50995860Speter
51048282Srnordiervoid
51193394SphkThreadPlanCallFunction::ClearBreakpoints ()
51263027Sjhb{
51348282Srnordier    if (m_trap_exceptions)
51448282Srnordier    {
51593394Sphk        if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
51693394Sphk            m_cxx_language_runtime->ClearExceptionBreakpoints();
51763027Sjhb        if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
518226907Sjmg            m_objc_language_runtime->ClearExceptionBreakpoints();
519226907Sjmg    }
52063027Sjhb}
52163027Sjhb
52263218Sachebool
52363218SacheThreadPlanCallFunction::BreakpointsExplainStop()
52463027Sjhb{
52563027Sjhb    StopInfoSP stop_info_sp = GetPrivateStopInfo ();
52693394Sphk
52793394Sphk    if (m_trap_exceptions)
52848282Srnordier    {
52963027Sjhb        if ((m_cxx_language_runtime &&
53063027Sjhb                m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
53195860Speter           ||(m_objc_language_runtime &&
53295860Speter                m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
53395860Speter        {
53495860Speter            Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
53595860Speter            if (log)
53695860Speter                log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
53795860Speter
538113454Sphk            SetPlanComplete(false);
53995860Speter
54019459Sjkh            // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
54119459Sjkh            // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
54219459Sjkh            stop_info_sp->OverrideShouldStop (true);
54319459Sjkh            return true;
54416561Salex        }
5454Srgrimes    }
546187203Sluigi
5474Srgrimes    return false;
54819459Sjkh}
5494Srgrimes
5504Srgrimesbool
5514SrgrimesThreadPlanCallFunction::RestoreThreadState()
55265054Sjhb{
55363027Sjhb    return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
55463027Sjhb}
5554Srgrimes
55665054Sjhb