Centralized the Mach exception stop info code by adding it as a first

class citizen on the StopInfo class. 

llvm-svn: 109235
This commit is contained in:
Greg Clayton 2010-07-23 16:45:51 +00:00
parent 2e00e3b12d
commit 896dff661a
5 changed files with 267 additions and 274 deletions

View File

@ -68,7 +68,7 @@ public:
SetStopReasonToTrace ();
void
SetStopReasonWithException (uint32_t exc_type, size_t exc_data_count);
SetStopReasonWithGenericException (uint32_t exc_type, size_t exc_data_count);
void
SetStopReasonWithPlan (lldb::ThreadPlanSP &plan);
@ -81,6 +81,11 @@ public:
void
SetStopDescription(const char *desc);
void
SetStopReasonWithMachException (uint32_t exc_type,
size_t exc_data_count,
const lldb::addr_t *exc_data);
lldb::user_id_t
GetBreakpointSiteID() const;

View File

@ -209,42 +209,9 @@ MachException::Data::GetStopInfo(Thread::StopInfo *stop_info) const
return true;
// We always stop with a mach exceptions
const size_t exc_data_count = exc_data.size();
stop_info->SetStopReasonWithException(exc_type, exc_data_count);
// Fill in a text description
const char * exc_name = MachException::Name(exc_type);
StreamString sstr;
if (exc_name)
sstr.PutCString(exc_name);
else
sstr.Printf ("%i", exc_type);
int signal = SoftSignal();
if (signal > 0)
{
const char *sig_str = Host::GetSignalAsCString(signal);
if (sig_str)
sstr.Printf (" EXC_SOFT_SIGNAL(%s)", sig_str);
else
sstr.Printf (" EXC_SOFT_SIGNAL(%i)", signal);
}
else
{
// No special disassembly for exception data, just
sstr.Printf (" data[%zu] = {", exc_data_count);
for (size_t idx = 0; idx < exc_data_count; ++idx)
sstr.Printf (MACH_EXCEPTION_DATA_FMT_MINHEX "%s", exc_data[idx], ((idx + 1 == exc_data_count) ? "" : ","));
sstr.PutChar('}');
}
stop_info->SetStopDescription (sstr.GetData());
// Copy the exception data
size_t i;
for (i=0; i<exc_data_count; i++)
stop_info->SetExceptionDataAtIndex(i, exc_data[i]);
stop_info->SetStopReasonWithMachException (exc_type,
exc_data_count,
exc_data_count ? &exc_data[0] : NULL);
return true;
}

View File

@ -63,7 +63,7 @@ public:
task_t task_port;
lldb::tid_t thread_port;
exception_type_t exc_type;
std::vector<mach_exception_data_type_t> exc_data;
std::vector<lldb::addr_t> exc_data;
Data() :
task_port(TASK_NULL),
thread_port(THREAD_NULL),
@ -125,7 +125,7 @@ public:
typedef std::vector<Message> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
typedef collection::const_iterator const_iterator;
};
enum

View File

@ -964,7 +964,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
std::string value;
std::string thread_name;
uint32_t exc_type = 0;
std::vector<uint64_t> exc_data;
std::vector<addr_t> exc_data;
uint32_t tid = LLDB_INVALID_THREAD_ID;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
uint32_t exc_data_count = 0;
@ -1011,245 +1011,17 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
gdb_thread->SetStopInfoStopID (GetStopID());
if (exc_type != 0)
{
bool exc_translated = false;
const char *exc_desc = NULL;
const char *code_label = "code";
const char *code_desc = NULL;
const char *subcode_label = "subcode";
const char *subcode_desc = NULL;
switch (exc_type)
{
case 1: // EXC_BAD_ACCESS
exc_desc = "EXC_BAD_ACCESS";
subcode_label = "address";
switch (GetArchSpec().GetGenericCPUType())
{
case ArchSpec::eCPU_arm:
switch (exc_data[0])
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (exc_data[0])
{
case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
case 0x102: code_desc = "EXC_PPC_BADSPACE"; break;
case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break;
}
break;
default:
break;
}
break;
case 2: // EXC_BAD_INSTRUCTION
exc_desc = "EXC_BAD_INSTRUCTION";
switch (GetArchSpec().GetGenericCPUType())
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
if (exc_data[0] == 1)
code_desc = "EXC_I386_INVOP";
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (exc_data[0])
{
case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break;
case 2: code_desc = "EXC_PPC_UNIPL_INST"; break;
case 3: code_desc = "EXC_PPC_PRIVINST"; break;
case 4: code_desc = "EXC_PPC_PRIVREG"; break;
case 5: // EXC_PPC_TRACE
stop_info.SetStopReasonToTrace();
exc_translated = true;
break;
case 6: code_desc = "EXC_PPC_PERFMON"; break;
}
break;
case ArchSpec::eCPU_arm:
if (exc_data[0] == 1)
code_desc = "EXC_ARM_UNDEFINED";
break;
default:
break;
}
break;
case 3: // EXC_ARITHMETIC
exc_desc = "EXC_ARITHMETIC";
switch (GetArchSpec().GetGenericCPUType())
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
switch (exc_data[0])
{
case 1: code_desc = "EXC_I386_DIV"; break;
case 2: code_desc = "EXC_I386_INTO"; break;
case 3: code_desc = "EXC_I386_NOEXT"; break;
case 4: code_desc = "EXC_I386_EXTOVR"; break;
case 5: code_desc = "EXC_I386_EXTERR"; break;
case 6: code_desc = "EXC_I386_EMERR"; break;
case 7: code_desc = "EXC_I386_BOUND"; break;
case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (exc_data[0])
{
case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
}
break;
default:
break;
}
break;
case 4: // EXC_EMULATION
exc_desc = "EXC_EMULATION";
break;
case 5: // EXC_SOFTWARE
exc_desc = "EXC_SOFTWARE";
if (exc_data[0] == EXC_SOFT_SIGNAL && exc_data.size() == 2)
{
stop_info.SetStopReasonWithSignal(exc_data[1]);
exc_translated = true;
}
break;
case 6:
{
exc_desc = "EXC_SOFTWARE";
bool is_software_breakpoint = false;
switch (GetArchSpec().GetGenericCPUType())
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
if (exc_data[0] == 1) // EXC_I386_SGL
{
exc_translated = true;
stop_info.SetStopReasonToTrace ();
}
else if (exc_data[0] == 2) // EXC_I386_BPT
{
is_software_breakpoint = true;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
is_software_breakpoint = exc_data[0] == 1; // EXC_PPC_BREAKPOINT
break;
case ArchSpec::eCPU_arm:
is_software_breakpoint = exc_data[0] == 1; // EXC_ARM_BREAKPOINT
break;
default:
break;
}
if (is_software_breakpoint)
{
addr_t pc = gdb_thread->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
{
exc_translated = true;
if (bp_site_sp->ValidForThisThread (thread_sp.get()))
{
stop_info.Clear ();
stop_info.SetStopReasonWithBreakpointSiteID (bp_site_sp->GetID());
}
else
{
stop_info.Clear ();
stop_info.SetStopReasonToNone();
}
}
}
}
break;
case 7:
exc_desc = "EXC_SYSCALL";
break;
case 8:
exc_desc = "EXC_MACH_SYSCALL";
break;
case 9:
exc_desc = "EXC_RPC_ALERT";
break;
case 10:
exc_desc = "EXC_CRASH";
break;
}
if (!exc_translated)
{
stop_info.SetStopReasonWithException(exc_type, exc_data.size());
for (uint32_t i=0; i<exc_data.size(); ++i)
stop_info.SetExceptionDataAtIndex(i, exc_data[i]);
StreamString desc_strm;
if (exc_desc)
desc_strm.PutCString(exc_desc);
else
desc_strm.Printf("EXC_??? (%u)", exc_type);
if (exc_data.size() >= 1)
{
if (code_desc)
desc_strm.Printf(" (%s=%s", code_label, code_desc);
else
desc_strm.Printf(" (%s=%llu", code_label, exc_data[0]);
}
if (exc_data.size() >= 2)
{
if (subcode_desc)
desc_strm.Printf(", %s=%s", subcode_label, subcode_desc);
else
desc_strm.Printf(", %s=0x%llx", subcode_label, exc_data[1]);
}
if (exc_data.empty() == false)
desc_strm.PutChar(')');
stop_info.SetStopDescription(desc_strm.GetString().c_str());
}
stop_info.SetStopReasonWithMachException (exc_type,
exc_data.size(),
&exc_data[0]);
}
else if (signo)
{
stop_info.SetStopReasonWithSignal(signo);
stop_info.SetStopReasonWithSignal (signo);
}
else
{
stop_info.SetStopReasonToNone();
stop_info.SetStopReasonToNone ();
}
}
return eStateStopped;

View File

@ -17,6 +17,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
@ -138,6 +139,254 @@ Thread::StopInfo::SetStopDescription(const char *desc)
}
}
void
Thread::StopInfo::SetStopReasonWithMachException
(
uint32_t exc_type,
size_t exc_data_count,
const addr_t *exc_data
)
{
assert (exc_data_count < LLDB_THREAD_MAX_STOP_EXC_DATA);
assert (m_thread != NULL);
m_reason = eStopReasonException;
m_details.exception.type = exc_type;
m_details.exception.data_count = exc_data_count;
for (size_t i=0; i<exc_data_count; ++i)
m_details.exception.data[i] = exc_data[i];
if (m_details.exception.type != 0)
{
ArchSpec::CPU cpu = m_thread->GetProcess().GetTarget().GetArchitecture().GetGenericCPUType();
bool exc_translated = false;
const char *exc_desc = NULL;
const char *code_label = "code";
const char *code_desc = NULL;
const char *subcode_label = "subcode";
const char *subcode_desc = NULL;
switch (m_details.exception.type)
{
case 1: // EXC_BAD_ACCESS
exc_desc = "EXC_BAD_ACCESS";
subcode_label = "address";
switch (cpu)
{
case ArchSpec::eCPU_arm:
switch (m_details.exception.data[0])
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (m_details.exception.data[0])
{
case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
case 0x102: code_desc = "EXC_PPC_BADSPACE"; break;
case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break;
}
break;
default:
break;
}
break;
case 2: // EXC_BAD_INSTRUCTION
exc_desc = "EXC_BAD_INSTRUCTION";
switch (cpu)
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
if (m_details.exception.data[0] == 1)
code_desc = "EXC_I386_INVOP";
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (m_details.exception.data[0])
{
case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break;
case 2: code_desc = "EXC_PPC_UNIPL_INST"; break;
case 3: code_desc = "EXC_PPC_PRIVINST"; break;
case 4: code_desc = "EXC_PPC_PRIVREG"; break;
case 5: // EXC_PPC_TRACE
SetStopReasonToTrace();
exc_translated = true;
break;
case 6: code_desc = "EXC_PPC_PERFMON"; break;
}
break;
case ArchSpec::eCPU_arm:
if (m_details.exception.data[0] == 1)
code_desc = "EXC_ARM_UNDEFINED";
break;
default:
break;
}
break;
case 3: // EXC_ARITHMETIC
exc_desc = "EXC_ARITHMETIC";
switch (cpu)
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
switch (m_details.exception.data[0])
{
case 1: code_desc = "EXC_I386_DIV"; break;
case 2: code_desc = "EXC_I386_INTO"; break;
case 3: code_desc = "EXC_I386_NOEXT"; break;
case 4: code_desc = "EXC_I386_EXTOVR"; break;
case 5: code_desc = "EXC_I386_EXTERR"; break;
case 6: code_desc = "EXC_I386_EMERR"; break;
case 7: code_desc = "EXC_I386_BOUND"; break;
case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
switch (m_details.exception.data[0])
{
case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
}
break;
default:
break;
}
break;
case 4: // EXC_EMULATION
exc_desc = "EXC_EMULATION";
break;
case 5: // EXC_SOFTWARE
exc_desc = "EXC_SOFTWARE";
if (m_details.exception.data[0] == EXC_SOFT_SIGNAL && m_details.exception.data_count == 2)
{
SetStopReasonWithSignal(m_details.exception.data[1]);
exc_translated = true;
}
break;
case 6:
{
exc_desc = "EXC_SOFTWARE";
bool is_software_breakpoint = false;
switch (cpu)
{
case ArchSpec::eCPU_i386:
case ArchSpec::eCPU_x86_64:
if (m_details.exception.data[0] == 1) // EXC_I386_SGL
{
exc_translated = true;
SetStopReasonToTrace ();
}
else if (m_details.exception.data[0] == 2) // EXC_I386_BPT
{
is_software_breakpoint = true;
}
break;
case ArchSpec::eCPU_ppc:
case ArchSpec::eCPU_ppc64:
is_software_breakpoint = m_details.exception.data[0] == 1; // EXC_PPC_BREAKPOINT
break;
case ArchSpec::eCPU_arm:
is_software_breakpoint = m_details.exception.data[0] == 1; // EXC_ARM_BREAKPOINT
break;
default:
break;
}
if (is_software_breakpoint)
{
addr_t pc = m_thread->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = m_thread->GetProcess().GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
{
exc_translated = true;
if (bp_site_sp->ValidForThisThread (m_thread))
{
Clear ();
SetStopReasonWithBreakpointSiteID (bp_site_sp->GetID());
}
else
{
Clear ();
SetStopReasonToNone();
}
}
}
}
break;
case 7:
exc_desc = "EXC_SYSCALL";
break;
case 8:
exc_desc = "EXC_MACH_SYSCALL";
break;
case 9:
exc_desc = "EXC_RPC_ALERT";
break;
case 10:
exc_desc = "EXC_CRASH";
break;
}
if (!exc_translated)
{
StreamString desc_strm;
if (exc_desc)
desc_strm.PutCString(exc_desc);
else
desc_strm.Printf("EXC_??? (%u)", exc_type);
if (m_details.exception.data_count >= 1)
{
if (code_desc)
desc_strm.Printf(" (%s=%s", code_label, code_desc);
else
desc_strm.Printf(" (%s=%llu", code_label, exc_data[0]);
}
if (m_details.exception.data_count >= 2)
{
if (subcode_desc)
desc_strm.Printf(", %s=%s", subcode_label, subcode_desc);
else
desc_strm.Printf(", %s=0x%llx", subcode_label, exc_data[1]);
}
if (m_details.exception.data_count > 0)
desc_strm.PutChar(')');
SetStopDescription(desc_strm.GetString().c_str());
}
}
}
void
Thread::StopInfo::SetThread (Thread* thread)
{
@ -227,7 +476,7 @@ Thread::StopInfo::GetExceptionDataCount() const
}
void
Thread::StopInfo::SetStopReasonWithException (uint32_t exc_type, size_t exc_data_count)
Thread::StopInfo::SetStopReasonWithGenericException (uint32_t exc_type, size_t exc_data_count)
{
m_reason = eStopReasonException;
m_details.exception.type = exc_type;