[GDBStub] Provide exception type to debugger
This commit is contained in:
parent
a4187736ad
commit
e260d0a110
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1576,6 +1576,8 @@ void DebugWindow::OnDetached() {
|
|||
}
|
||||
}
|
||||
|
||||
void DebugWindow::OnUnhandledException(Exception* ex) {}
|
||||
|
||||
void DebugWindow::OnExecutionPaused() {
|
||||
UpdateCache();
|
||||
Focus();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue