Modified the thread plan that calls functions to
set breakpoints at the different locations where
an exception could be thrown, so that exceptions
thrown by expressions are properly caught.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@118142 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index 1e51762..86cdd48 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -12,6 +12,7 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
+#include "llvm/Support/MachO.h"
// Project includes
#include "lldb/lldb-private-log.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -52,10 +53,12 @@
Process& process = thread.GetProcess();
Target& target = process.GetTarget();
const ABI *abi = process.GetABI();
-
+
if (!abi)
return;
-
+
+ SetBreakpoints();
+
lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
SymbolContextList contexts;
@@ -111,6 +114,8 @@
if(!abi)
return;
+ SetBreakpoints();
+
lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
SymbolContextList contexts;
@@ -173,7 +178,7 @@
bool
ThreadPlanCallFunction::PlanExplainsStop ()
-{
+{
// If our subplan knows why we stopped, even if it's done (which would forward the question to us)
// we answer yes.
if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
@@ -186,6 +191,7 @@
// Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
// If it is not an internal breakpoint, consult OkayToDiscard.
lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
+
if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
{
uint64_t break_site_id = stop_info_sp->GetValue();
@@ -196,7 +202,24 @@
bool is_internal = true;
for (uint32_t i = 0; i < num_owners; i++)
{
- if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
+ Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
+ break_id_t bid = bp.GetID();
+
+ // Check if the breakpoint is one of ours.
+
+ if (m_cxx_exception_bp_sp.get() &&
+ bid == m_cxx_exception_bp_sp->GetID())
+ return true;
+
+ if (m_cxx_exception_alloc_bp_sp.get() &&
+ bid == m_cxx_exception_alloc_bp_sp->GetID())
+ return true;
+
+ if (m_objc_exception_bp_sp.get() &&
+ bid == m_objc_exception_bp_sp->GetID())
+ return true;
+
+ if (!bp.IsInternal())
{
is_internal = false;
break;
@@ -242,6 +265,8 @@
m_thread.RestoreSaveFrameZero(m_register_backup);
m_thread.ClearStackFrames();
SetPlanComplete();
+
+ ClearBreakpoints();
return true;
}
else
@@ -309,3 +334,67 @@
return false;
}
}
+
+void
+ThreadPlanCallFunction::SetBreakpoints ()
+{
+ Target& target = m_process.GetTarget();
+
+ ArchSpec arch_spec = target.GetArchitecture();
+
+ // A temporary fix to set breakpoints at points where exceptions are being
+ // thrown. This functionality will migrate into the Target.
+ switch (arch_spec.GetCPUType())
+ {
+ default:
+ break;
+ case llvm::MachO::CPUTypeI386:
+ m_cxx_exception_bp_sp = target.CreateBreakpoint (NULL,
+ "__cxa_throw",
+ eFunctionNameTypeBase,
+ true);
+ m_cxx_exception_alloc_bp_sp = target.CreateBreakpoint (NULL,
+ "__cxa_allocate",
+ eFunctionNameTypeBase,
+ true);
+ m_objc_exception_bp_sp = target.CreateBreakpoint (NULL,
+ "objc_exception_throw",
+ eFunctionNameTypeBase,
+ true);
+ break;
+ case llvm::MachO::CPUTypeX86_64:
+ m_cxx_exception_bp_sp = target.CreateBreakpoint (NULL,
+ "__cxa_throw",
+ eFunctionNameTypeBase,
+ true);
+ m_cxx_exception_alloc_bp_sp = target.CreateBreakpoint (NULL,
+ "__cxa_allocate",
+ eFunctionNameTypeBase,
+ true);
+ break;
+ }
+}
+
+void
+ThreadPlanCallFunction::ClearBreakpoints ()
+{
+ Target& target = m_process.GetTarget();
+
+ if (m_cxx_exception_bp_sp.get())
+ {
+ target.RemoveBreakpointByID(m_cxx_exception_bp_sp->GetID());
+ m_cxx_exception_bp_sp.reset();
+ }
+
+ if (m_cxx_exception_alloc_bp_sp.get())
+ {
+ target.RemoveBreakpointByID(m_cxx_exception_alloc_bp_sp->GetID());
+ m_cxx_exception_bp_sp.reset();
+ }
+
+ if (m_objc_exception_bp_sp.get())
+ {
+ target.RemoveBreakpointByID(m_objc_exception_bp_sp->GetID());
+ m_cxx_exception_bp_sp.reset();
+ }
+}