Factored the code that implements breakpoints on

exceptions for different languages out of 
ThreadPlanCallFunction and put it into the 
appropriate language runtimes.

llvm-svn: 118200
This commit is contained in:
Sean Callanan 2010-11-03 22:19:38 +00:00
parent 49b0c45ecf
commit f211510ff6
7 changed files with 229 additions and 105 deletions

View File

@ -45,6 +45,21 @@ public:
virtual lldb::ValueObjectSP
GetDynamicValue (lldb::ValueObjectSP in_value, ExecutionContextScope *exe_scope) = 0;
virtual void
SetExceptionBreakpoints ()
{
}
virtual void
ClearExceptionBreakpoints ()
{
}
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
return false;
}
protected:
//------------------------------------------------------------------
// Classes that inherit from LanguageRuntime can see and modify these

View File

@ -97,9 +97,8 @@ private:
Thread &m_thread;
Thread::RegisterCheckpoint m_register_backup;
lldb::ThreadPlanSP m_subplan_sp;
lldb::BreakpointSP m_cxx_exception_bp_sp;
lldb::BreakpointSP m_cxx_exception_alloc_bp_sp;
lldb::BreakpointSP m_objc_exception_bp_sp;
LanguageRuntime *m_cxx_language_runtime;
LanguageRuntime *m_objc_language_runtime;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};

View File

@ -9,6 +9,7 @@
#include "ItaniumABILanguageRuntime.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
@ -17,6 +18,7 @@
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@ -116,3 +118,89 @@ ItaniumABILanguageRuntime::EnablePluginLogging (Stream *strm, Args &command)
{
return NULL;
}
void
ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
{
if (!m_process)
return;
if (!m_cxx_exception_bp_sp)
m_cxx_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
"__cxa_throw",
eFunctionNameTypeBase,
true);
if (!m_cxx_exception_alloc_bp_sp)
m_cxx_exception_alloc_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
"__cxa_allocate",
eFunctionNameTypeBase,
true);
}
void
ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
{
if (!m_process)
return;
if (m_cxx_exception_bp_sp.get())
{
m_process->GetTarget().RemoveBreakpointByID(m_cxx_exception_bp_sp->GetID());
m_cxx_exception_bp_sp.reset();
}
if (m_cxx_exception_alloc_bp_sp.get())
{
m_process->GetTarget().RemoveBreakpointByID(m_cxx_exception_alloc_bp_sp->GetID());
m_cxx_exception_bp_sp.reset();
}
}
bool
ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
if (!m_process)
return false;
if (!stop_reason ||
stop_reason->GetStopReason() != eStopReasonBreakpoint)
return false;
uint64_t break_site_id = stop_reason->GetValue();
lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id);
if (!bp_site_sp)
return false;
uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
bool check_cxx_exception = false;
break_id_t cxx_exception_bid;
bool check_cxx_exception_alloc = false;
break_id_t cxx_exception_alloc_bid;
if (m_cxx_exception_bp_sp)
{
check_cxx_exception = true;
cxx_exception_bid = m_cxx_exception_bp_sp->GetID();
}
if (m_cxx_exception_alloc_bp_sp)
{
check_cxx_exception_alloc = true;
cxx_exception_alloc_bid = m_cxx_exception_alloc_bp_sp->GetID();
}
for (uint32_t i = 0; i < num_owners; i++)
{
break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID();
if ((check_cxx_exception && (bid == cxx_exception_bid)) ||
(check_cxx_exception_alloc && (bid == cxx_exception_alloc_bid)))
return true;
}
return false;
}

View File

@ -65,9 +65,22 @@ namespace lldb_private {
virtual lldb_private::Log *
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
virtual void
SetExceptionBreakpoints ();
virtual void
ClearExceptionBreakpoints ();
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
protected:
private:
ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead.
lldb::BreakpointSP m_cxx_exception_bp_sp;
lldb::BreakpointSP m_cxx_exception_alloc_bp_sp;
};
} // namespace lldb_private

View File

@ -10,8 +10,10 @@
#include "AppleObjCRuntimeV2.h"
#include "AppleObjCTrampolineHandler.h"
#include "llvm/Support/MachO.h"
#include "clang/AST/Type.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
@ -24,6 +26,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@ -286,3 +289,84 @@ AppleObjCRuntimeV2::EnablePluginLogging (Stream *strm, Args &command)
{
return NULL;
}
void
AppleObjCRuntimeV2::SetExceptionBreakpoints ()
{
if (!m_process)
return;
if (!m_objc_exception_bp_sp)
{
ArchSpec arch_spec = m_process->GetTarget().GetArchitecture();
switch (arch_spec.GetCPUType())
{
default:
break;
case llvm::MachO::CPUTypeI386:
m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
"objc_exception_throw",
eFunctionNameTypeBase,
true);
break;
case llvm::MachO::CPUTypeX86_64:
m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL,
"__cxa_throw",
eFunctionNameTypeBase,
true);
break;
}
}
}
void
AppleObjCRuntimeV2::ClearExceptionBreakpoints ()
{
if (!m_process)
return;
if (m_objc_exception_bp_sp.get())
{
m_process->GetTarget().RemoveBreakpointByID(m_objc_exception_bp_sp->GetID());
m_objc_exception_bp_sp.reset();
}
}
bool
AppleObjCRuntimeV2::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
if (!m_process)
return false;
if (!stop_reason ||
stop_reason->GetStopReason() != eStopReasonBreakpoint)
return false;
uint64_t break_site_id = stop_reason->GetValue();
lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id);
if (!bp_site_sp)
return false;
uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
bool check_objc_exception = false;
break_id_t objc_exception_bid;
if (m_objc_exception_bp_sp)
{
check_objc_exception = true;
objc_exception_bid = m_objc_exception_bp_sp->GetID();
}
for (uint32_t i = 0; i < num_owners; i++)
{
break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID();
if ((check_objc_exception && (bid == objc_exception_bid)))
return true;
}
return false;
}

View File

@ -87,6 +87,15 @@ public:
virtual lldb_private::Log *
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
virtual void
SetExceptionBreakpoints ();
virtual void
ClearExceptionBreakpoints ();
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
protected:
Address *
GetPrintForDebuggerAddr();
@ -95,6 +104,7 @@ private:
std::auto_ptr<Address> m_PrintForDebugger_addr;
bool m_read_objc_library;
std::auto_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
lldb::BreakpointSP m_objc_exception_bp_sp;
AppleObjCRuntimeV2(Process *process) :
lldb_private::ObjCLanguageRuntime(process),

View File

@ -20,6 +20,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@ -328,122 +329,36 @@ ThreadPlanCallFunction::MischiefManaged ()
void
ThreadPlanCallFunction::SetBreakpoints ()
{
Target& target = m_process.GetTarget();
m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus);
m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC);
ArchSpec arch_spec = target.GetArchitecture();
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;
}
if (m_cxx_language_runtime)
m_cxx_language_runtime->SetExceptionBreakpoints();
if (m_objc_language_runtime)
m_objc_language_runtime->SetExceptionBreakpoints();
}
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();
}
if (m_cxx_language_runtime)
m_cxx_language_runtime->ClearExceptionBreakpoints();
if (m_objc_language_runtime)
m_objc_language_runtime->ClearExceptionBreakpoints();
}
bool
ThreadPlanCallFunction::BreakpointsExplainStop()
{
// A temporary fix to set breakpoints at points where exceptions are being
// thrown. This functionality will migrate into the Target.
lldb::StopInfoSP stop_info_sp = GetPrivateStopReason();
if (!stop_info_sp ||
stop_info_sp->GetStopReason() != eStopReasonBreakpoint)
return false;
if (m_cxx_language_runtime &&
m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
return true;
uint64_t break_site_id = stop_info_sp->GetValue();
lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id);
if (!bp_site_sp)
return false;
uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
bool check_cxx_exception = false;
break_id_t cxx_exception_bid;
bool check_cxx_exception_alloc = false;
break_id_t cxx_exception_alloc_bid;
bool check_objc_exception = false;
break_id_t objc_exception_bid;
if (m_cxx_exception_bp_sp.get())
{
check_cxx_exception = true;
cxx_exception_bid = m_cxx_exception_bp_sp->GetID();
}
if (m_cxx_exception_bp_sp.get())
{
check_cxx_exception_alloc = true;
cxx_exception_alloc_bid = m_cxx_exception_alloc_bp_sp->GetID();
}
if (m_cxx_exception_bp_sp.get())
{
check_objc_exception = true;
objc_exception_bid = m_objc_exception_bp_sp->GetID();
}
for (uint32_t i = 0; i < num_owners; i++)
{
break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID();
if ((check_cxx_exception && (bid == cxx_exception_bid)) ||
(check_cxx_exception_alloc && (bid == cxx_exception_alloc_bid)) ||
(check_objc_exception && (bid == objc_exception_bid)))
return true;
}
if (m_objc_language_runtime &&
m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
return true;
return false;
}