[GDBStub] Provide exception type to debugger
This commit is contained in:
parent
a4187736ad
commit
e260d0a110
|
@ -30,6 +30,9 @@ class DebugListener {
|
||||||
// end.
|
// end.
|
||||||
virtual void OnDetached() = 0;
|
virtual void OnDetached() = 0;
|
||||||
|
|
||||||
|
// Handles exception info (will be followed by OnExecutionPaused)
|
||||||
|
virtual void OnUnhandledException(Exception* ex) = 0;
|
||||||
|
|
||||||
// Handles execution being interrupted and transitioning to
|
// Handles execution being interrupted and transitioning to
|
||||||
// ExceutionState::kPaused.
|
// ExceutionState::kPaused.
|
||||||
virtual void OnExecutionPaused() = 0;
|
virtual void OnExecutionPaused() = 0;
|
||||||
|
|
|
@ -724,7 +724,7 @@ bool Processor::OnUnhandledException(Exception* ex) {
|
||||||
execution_state_ = ExecutionState::kPaused;
|
execution_state_ = ExecutionState::kPaused;
|
||||||
|
|
||||||
// Notify debugger that exceution stopped.
|
// Notify debugger that exceution stopped.
|
||||||
// debug_listener_->OnException(info);
|
debug_listener_->OnUnhandledException(ex);
|
||||||
debug_listener_->OnExecutionPaused();
|
debug_listener_->OnExecutionPaused();
|
||||||
|
|
||||||
// Suspend self.
|
// Suspend self.
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "xenia/cpu/breakpoint.h"
|
#include "xenia/cpu/breakpoint.h"
|
||||||
#include "xenia/cpu/ppc/ppc_opcode_info.h"
|
#include "xenia/cpu/ppc/ppc_opcode_info.h"
|
||||||
#include "xenia/cpu/stack_walker.h"
|
#include "xenia/cpu/stack_walker.h"
|
||||||
|
#include "xenia/cpu/thread.h"
|
||||||
#include "xenia/kernel/xmodule.h"
|
#include "xenia/kernel/xmodule.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
|
|
||||||
|
@ -50,7 +51,9 @@ enum class GdbStubControl : char {
|
||||||
constexpr const char* kGdbReplyOK = "OK";
|
constexpr const char* kGdbReplyOK = "OK";
|
||||||
constexpr const char* kGdbReplyError = "E01";
|
constexpr const char* kGdbReplyError = "E01";
|
||||||
|
|
||||||
constexpr int kSignalSigtrap = 5;
|
constexpr int kSignalSigill = 4; // Illegal instruction
|
||||||
|
constexpr int kSignalSigtrap = 5; // Trace trap
|
||||||
|
constexpr int kSignalSigsegv = 11; // Segmentation fault
|
||||||
|
|
||||||
// must start with l for debugger to accept it
|
// must start with l for debugger to accept it
|
||||||
constexpr char kMemoryMapXml[] =
|
constexpr char kMemoryMapXml[] =
|
||||||
|
@ -222,12 +225,26 @@ void GDBStub::Listen(std::unique_ptr<Socket>& client) {
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mtx_);
|
std::unique_lock<std::mutex> lock(mtx_);
|
||||||
if (cache_.notify_stopped) {
|
if (cache_.notify_stopped) {
|
||||||
if (cache_.notify_bp_thread_id != -1) {
|
if (cache_.notify_thread_id != -1) {
|
||||||
cache_.cur_thread_id = cache_.notify_bp_thread_id;
|
cache_.cur_thread_id = cache_.notify_thread_id;
|
||||||
}
|
}
|
||||||
SendPacket(client, GetThreadStateReply(cache_.notify_bp_thread_id,
|
|
||||||
kSignalSigtrap));
|
int sig_num = kSignalSigtrap;
|
||||||
cache_.notify_bp_thread_id = -1;
|
if (cache_.notify_exception_code.has_value()) {
|
||||||
|
if (cache_.notify_exception_code ==
|
||||||
|
xe::Exception::Code::kIllegalInstruction) {
|
||||||
|
sig_num = kSignalSigill;
|
||||||
|
} else {
|
||||||
|
sig_num = kSignalSigsegv;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_.notify_exception_code.reset();
|
||||||
|
cache_.notify_exception_access_violation.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendPacket(client,
|
||||||
|
GetThreadStateReply(cache_.notify_thread_id, sig_num));
|
||||||
|
cache_.notify_thread_id = -1;
|
||||||
cache_.notify_stopped = false;
|
cache_.notify_stopped = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,6 +915,17 @@ void GDBStub::OnDetached() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDBStub::OnUnhandledException(Exception* ex) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
debugging::DebugPrint("GDBStub: OnUnhandledException {} {}\n",
|
||||||
|
int(ex->code()), int(ex->access_violation_operation()));
|
||||||
|
#endif
|
||||||
|
std::unique_lock<std::mutex> lock(mtx_);
|
||||||
|
cache_.notify_exception_code = ex->code();
|
||||||
|
cache_.notify_exception_access_violation = ex->access_violation_operation();
|
||||||
|
cache_.notify_thread_id = cpu::Thread::GetCurrentThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
void GDBStub::OnExecutionPaused() {
|
void GDBStub::OnExecutionPaused() {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debugging::DebugPrint("GDBStub: OnExecutionPaused\n");
|
debugging::DebugPrint("GDBStub: OnExecutionPaused\n");
|
||||||
|
@ -925,7 +953,7 @@ void GDBStub::OnStepCompleted(cpu::ThreadDebugInfo* thread_info) {
|
||||||
#endif
|
#endif
|
||||||
// Some debuggers like IDA will remove the current breakpoint & step into next
|
// Some debuggers like IDA will remove the current breakpoint & step into next
|
||||||
// instruction, only re-adding BP after it's told about the step
|
// instruction, only re-adding BP after it's told about the step
|
||||||
cache_.notify_bp_thread_id = thread_info->thread_id;
|
cache_.notify_thread_id = thread_info->thread_id;
|
||||||
cache_.last_bp_thread_id = thread_info->thread_id;
|
cache_.last_bp_thread_id = thread_info->thread_id;
|
||||||
UpdateCache();
|
UpdateCache();
|
||||||
}
|
}
|
||||||
|
@ -938,7 +966,7 @@ void GDBStub::OnBreakpointHit(Breakpoint* breakpoint,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cache_.notify_bp_guest_address = breakpoint->address();
|
cache_.notify_bp_guest_address = breakpoint->address();
|
||||||
cache_.notify_bp_thread_id = thread_info->thread_id;
|
cache_.notify_thread_id = thread_info->thread_id;
|
||||||
cache_.last_bp_thread_id = thread_info->thread_id;
|
cache_.last_bp_thread_id = thread_info->thread_id;
|
||||||
UpdateCache();
|
UpdateCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ class GDBStub : public cpu::DebugListener {
|
||||||
|
|
||||||
void OnFocus() override;
|
void OnFocus() override;
|
||||||
void OnDetached() override;
|
void OnDetached() override;
|
||||||
|
void OnUnhandledException(Exception* ex) override;
|
||||||
void OnExecutionPaused() override;
|
void OnExecutionPaused() override;
|
||||||
void OnExecutionContinued() override;
|
void OnExecutionContinued() override;
|
||||||
void OnExecutionEnded() override;
|
void OnExecutionEnded() override;
|
||||||
|
@ -100,9 +101,11 @@ class GDBStub : public cpu::DebugListener {
|
||||||
uint32_t last_bp_thread_id = -1;
|
uint32_t last_bp_thread_id = -1;
|
||||||
|
|
||||||
uint64_t notify_bp_guest_address = -1;
|
uint64_t notify_bp_guest_address = -1;
|
||||||
uint32_t notify_bp_thread_id = -1;
|
uint32_t notify_thread_id = -1;
|
||||||
std::vector<std::string> notify_debug_messages;
|
|
||||||
bool notify_stopped = false;
|
bool notify_stopped = false;
|
||||||
|
std::optional<Exception::AccessViolationOperation>
|
||||||
|
notify_exception_access_violation;
|
||||||
|
std::optional<Exception::Code> notify_exception_code;
|
||||||
|
|
||||||
bool is_stopped = false;
|
bool is_stopped = false;
|
||||||
std::vector<kernel::object_ref<kernel::XModule>> modules;
|
std::vector<kernel::object_ref<kernel::XModule>> modules;
|
||||||
|
|
|
@ -1576,6 +1576,8 @@ void DebugWindow::OnDetached() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugWindow::OnUnhandledException(Exception* ex) {}
|
||||||
|
|
||||||
void DebugWindow::OnExecutionPaused() {
|
void DebugWindow::OnExecutionPaused() {
|
||||||
UpdateCache();
|
UpdateCache();
|
||||||
Focus();
|
Focus();
|
||||||
|
|
|
@ -44,6 +44,7 @@ class DebugWindow : public cpu::DebugListener {
|
||||||
|
|
||||||
void OnFocus() override;
|
void OnFocus() override;
|
||||||
void OnDetached() override;
|
void OnDetached() override;
|
||||||
|
void OnUnhandledException(Exception* ex) override;
|
||||||
void OnExecutionPaused() override;
|
void OnExecutionPaused() override;
|
||||||
void OnExecutionContinued() override;
|
void OnExecutionContinued() override;
|
||||||
void OnExecutionEnded() override;
|
void OnExecutionEnded() override;
|
||||||
|
|
Loading…
Reference in New Issue