Skip to content

Commit

Permalink
[GDBStub] Remove duplicated code, minor fixups
Browse files Browse the repository at this point in the history
  • Loading branch information
emoose committed Oct 6, 2024
1 parent 851d7af commit b58b9fb
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 94 deletions.
160 changes: 68 additions & 92 deletions src/xenia/debug/gdb/gdbstub.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ constexpr const char* kGdbReplyError = "E01";

constexpr int kSignalSigtrap = 5;

constexpr char memory_map[] =
// must start with l for debugger to accept it
constexpr char kMemoryMapXml[] =
R"(l<?xml version="1.0"?>
<memory-map>
<!-- Based on memory.cc Initialize() -->
Expand All @@ -66,9 +67,8 @@ constexpr char memory_map[] =
</memory-map>
)";

// must start with l for debugger to accept it
// TODO: add power-altivec.xml (and update ReadRegister to support it)
constexpr char target_xml[] =
constexpr char kTargetXml[] =
R"(l<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
Expand Down Expand Up @@ -152,26 +152,6 @@ constexpr char target_xml[] =
</target>
)";

std::string u64_to_padded_hex(uint64_t value) {
return fmt::format("{:016x}", value);
}

std::string u32_to_padded_hex(uint32_t value) {
return fmt::format("{:08x}", value);
}

template <typename T>
T hex_to(std::string_view val) {
T result;
std::from_chars(val.data(), val.data() + val.size(), result, 16);

return result;
}

constexpr auto& hex_to_u8 = hex_to<uint8_t>;
constexpr auto& hex_to_u32 = hex_to<uint32_t>;
constexpr auto& hex_to_u64 = hex_to<uint64_t>;

std::string to_hexbyte(uint8_t i) {
std::string result = "00";
uint8_t i1 = i & 0xF;
Expand All @@ -193,60 +173,6 @@ uint8_t from_hexchar(char c) {
return 0;
}

std::string GDBStub::ReadRegister(xe::cpu::ThreadDebugInfo* thread,
uint32_t rid) {
// Send registers as 32-bit, otherwise some debuggers will switch to 64-bit
// mode (eg. IDA will switch to 64-bit and refuse to allow decompiler to work
// with it)
//
// TODO: add altivec/VMX registers here...
//
// ids from gdb/features/rs6000/powerpc-64.c
switch (rid) {
// pc
case 64: {
// If we recently hit a BP then debugger is likely asking for registers
// for it
//
// Lie about the PC and say it's the BP address, since PC might not always
// match
if (cache_.notify_bp_guest_address != -1) {
auto ret = u32_to_padded_hex((uint32_t)cache_.notify_bp_guest_address);
cache_.notify_bp_guest_address = -1;
return ret;
}
// Search for first frame that has guest_pc attached, GDB doesn't care
// about host
for (auto& frame : thread->frames) {
if (frame.guest_pc != 0) {
return u32_to_padded_hex((uint32_t)frame.guest_pc);
}
}
return u32_to_padded_hex(0);
}
case 65:
return u32_to_padded_hex((uint32_t)thread->guest_context.msr);
case 66:
return u32_to_padded_hex((uint32_t)thread->guest_context.cr());
case 67:
return u32_to_padded_hex((uint32_t)thread->guest_context.lr);
case 68:
return u32_to_padded_hex((uint32_t)thread->guest_context.ctr);
// xer
case 69:
return std::string(8, 'x');
// fpscr
case 70:
return u32_to_padded_hex(thread->guest_context.fpscr.value);
default:
if (rid > 70) return "";
return (rid > 31) ? u64_to_padded_hex(*(uint64_t*)&(
thread->guest_context.f[rid - 32])) // fpr
: u32_to_padded_hex(
(uint32_t)thread->guest_context.r[rid]); // gpr
}
}

GDBStub::GDBStub(Emulator* emulator, int listen_port)
: emulator_(emulator),
processor_(emulator->processor()),
Expand Down Expand Up @@ -533,15 +459,70 @@ void GDBStub::UpdateCache() {
}
}

std::string GDBStub::ReadRegister(xe::cpu::ThreadDebugInfo* thread,
uint32_t rid) {
// Send registers as 32-bit, otherwise some debuggers will switch to 64-bit
// mode (eg. IDA will switch to 64-bit and refuse to allow decompiler to work
// with it)
//
// TODO: add altivec/VMX registers here...
//
// ids from gdb/features/rs6000/powerpc-64.c
switch (rid) {
// pc
case 64: {
// If we recently hit a BP then debugger is likely asking for registers
// for it
//
// Lie about the PC and say it's the BP addr, since the PC (derived from
// X64 host addr) might not match expected BP addr
if (cache_.notify_bp_guest_address != -1) {
auto ret = string_util::to_hex_string(
(uint32_t)cache_.notify_bp_guest_address);
cache_.notify_bp_guest_address = -1;
return ret;
}
// Search for first frame that has guest_pc attached, GDB doesn't care
// about host
for (auto& frame : thread->frames) {
if (frame.guest_pc != 0) {
return string_util::to_hex_string((uint32_t)frame.guest_pc);
}
}
return string_util::to_hex_string((uint32_t)0);
}
case 65:
return string_util::to_hex_string((uint32_t)thread->guest_context.msr);
case 66:
return string_util::to_hex_string((uint32_t)thread->guest_context.cr());
case 67:
return string_util::to_hex_string((uint32_t)thread->guest_context.lr);
case 68:
return string_util::to_hex_string((uint32_t)thread->guest_context.ctr);
// xer
case 69:
return std::string(8, 'x');
case 70:
return string_util::to_hex_string(thread->guest_context.fpscr.value);
default:
if (rid > 70) return "";
if (rid > 31)
return string_util::to_hex_string(
*(uint64_t*)&(thread->guest_context.f[rid - 32])); // fpr
return string_util::to_hex_string(
(uint32_t)thread->guest_context.r[rid]); // gpr
}
}

std::string GDBStub::ReadRegister(const std::string& data) {
auto* thread = cache_.cur_thread_info();
if (!thread) {
return kGdbReplyError;
}
uint32_t rid = hex_to_u32(data);
uint32_t rid = string_util::from_string<uint32_t>(data, true);
std::string result = ReadRegister(thread, rid);
if (result.empty()) {
return kGdbReplyError; // TODO: is this error correct?
return kGdbReplyError;
}
return result;
}
Expand Down Expand Up @@ -592,8 +573,8 @@ std::string GDBStub::ExecutionStep() {

std::string GDBStub::ReadMemory(const std::string& data) {
auto s = data.find(',');
uint32_t addr = hex_to_u32(data.substr(0, s));
uint32_t len = hex_to_u32(data.substr(s + 1));
uint32_t addr = string_util::from_string<uint32_t>(data.substr(0, s), true);
uint32_t len = string_util::from_string<uint32_t>(data.substr(s + 1), true);
std::string result;
result.reserve(len * 2);

Expand Down Expand Up @@ -621,10 +602,6 @@ std::string GDBStub::ReadMemory(const std::string& data) {
return result;
}

std::string GDBStub::BuildMemoryMap() { return memory_map; }

std::string GDBStub::BuildTargetXml() { return target_xml; }

std::string GDBStub::BuildThreadList() {
std::string buffer;
buffer += "l<?xml version=\"1.0\"?>";
Expand Down Expand Up @@ -661,10 +638,9 @@ std::string GDBStub::GetThreadStateReply(uint32_t thread_id, uint8_t signal) {
pc_value = cache_.notify_bp_guest_address;
}

return fmt::format(
"T{:02x}{:02x}:{};{:02x}:{};thread:{:x};", signal, PC_REGISTER,
u32_to_padded_hex((uint32_t)pc_value), LR_REGISTER,
u32_to_padded_hex((uint32_t)thread->guest_context.lr), thread_id);
return fmt::format("T{:02x}{:02x}:{:08x};{:02x}:{:08x};thread:{:x};",
signal, PC_REGISTER, uint32_t(pc_value), LR_REGISTER,
uint32_t(thread->guest_context.lr), thread_id);
}
return "S05";
}
Expand Down Expand Up @@ -925,15 +901,15 @@ std::string GDBStub::HandleGDBCommand(const GDBCommand& command) {
}
auto sub_cmd = param.substr(0, param.find(':'));
if (sub_cmd == "features") {
return BuildTargetXml();
return std::string(kTargetXml);
} else if (sub_cmd == "memory-map") {
return BuildMemoryMap();
return std::string(kMemoryMapXml);
} else if (sub_cmd == "threads") {
return BuildThreadList();
}
return std::string(kGdbReplyError);
}},
// Supported features (TODO: memory map)
// Supported features
{"qSupported",
[&](const GDBCommand& cmd) {
return "PacketSize=1024;qXfer:features:read+;qXfer:threads:read+;"
Expand Down
2 changes: 0 additions & 2 deletions src/xenia/debug/gdb/gdbstub.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ class GDBStub : public cpu::DebugListener {
std::string ExecutionContinue();
std::string ExecutionStep();
std::string ReadMemory(const std::string& data);
std::string BuildMemoryMap();
std::string BuildTargetXml();
std::string BuildThreadList();

std::string GetThreadStateReply(uint32_t thread_id, uint8_t signal);
Expand Down

0 comments on commit b58b9fb

Please sign in to comment.