[GDBStub] Provide exception type to debugger

This commit is contained in:
emoose 2024-10-08 00:04:46 +01:00
parent a4187736ad
commit e260d0a110
6 changed files with 48 additions and 11 deletions

View File

@ -30,6 +30,9 @@ class DebugListener {
// end.
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
// ExceutionState::kPaused.
virtual void OnExecutionPaused() = 0;

View File

@ -724,7 +724,7 @@ bool Processor::OnUnhandledException(Exception* ex) {
execution_state_ = ExecutionState::kPaused;
// Notify debugger that exceution stopped.
// debug_listener_->OnException(info);
debug_listener_->OnUnhandledException(ex);
debug_listener_->OnExecutionPaused();
// Suspend self.

View File

@ -27,6 +27,7 @@
#include "xenia/cpu/breakpoint.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
#include "xenia/cpu/stack_walker.h"
#include "xenia/cpu/thread.h"
#include "xenia/kernel/xmodule.h"
#include "xenia/kernel/xthread.h"
@ -50,7 +51,9 @@ enum class GdbStubControl : char {
constexpr const char* kGdbReplyOK = "OK";
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
constexpr char kMemoryMapXml[] =
@ -222,12 +225,26 @@ void GDBStub::Listen(std::unique_ptr<Socket>& client) {
{
std::unique_lock<std::mutex> lock(mtx_);
if (cache_.notify_stopped) {
if (cache_.notify_bp_thread_id != -1) {
cache_.cur_thread_id = cache_.notify_bp_thread_id;
if (cache_.notify_thread_id != -1) {
cache_.cur_thread_id = cache_.notify_thread_id;
}
SendPacket(client, GetThreadStateReply(cache_.notify_bp_thread_id,
kSignalSigtrap));
cache_.notify_bp_thread_id = -1;
int sig_num = kSignalSigtrap;
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;
}
}
@ -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() {
#ifdef DEBUG
debugging::DebugPrint("GDBStub: OnExecutionPaused\n");
@ -925,7 +953,7 @@ void GDBStub::OnStepCompleted(cpu::ThreadDebugInfo* thread_info) {
#endif
// Some debuggers like IDA will remove the current breakpoint & step into next
// 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;
UpdateCache();
}
@ -938,7 +966,7 @@ void GDBStub::OnBreakpointHit(Breakpoint* breakpoint,
#endif
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;
UpdateCache();
}

View File

@ -35,6 +35,7 @@ class GDBStub : public cpu::DebugListener {
void OnFocus() override;
void OnDetached() override;
void OnUnhandledException(Exception* ex) override;
void OnExecutionPaused() override;
void OnExecutionContinued() override;
void OnExecutionEnded() override;
@ -100,9 +101,11 @@ class GDBStub : public cpu::DebugListener {
uint32_t last_bp_thread_id = -1;
uint64_t notify_bp_guest_address = -1;
uint32_t notify_bp_thread_id = -1;
std::vector<std::string> notify_debug_messages;
uint32_t notify_thread_id = -1;
bool notify_stopped = false;
std::optional<Exception::AccessViolationOperation>
notify_exception_access_violation;
std::optional<Exception::Code> notify_exception_code;
bool is_stopped = false;
std::vector<kernel::object_ref<kernel::XModule>> modules;

View File

@ -1576,6 +1576,8 @@ void DebugWindow::OnDetached() {
}
}
void DebugWindow::OnUnhandledException(Exception* ex) {}
void DebugWindow::OnExecutionPaused() {
UpdateCache();
Focus();

View File

@ -44,6 +44,7 @@ class DebugWindow : public cpu::DebugListener {
void OnFocus() override;
void OnDetached() override;
void OnUnhandledException(Exception* ex) override;
void OnExecutionPaused() override;
void OnExecutionContinued() override;
void OnExecutionEnded() override;