From 0253592ae96b63e461fdfc7c8dd89f8d9078489b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 17 Jan 2025 17:23:05 +0100 Subject: [PATCH] Integrate new gdb stub --- src/analyzer/main.cpp | 7 +- src/gdb-stub/async_handler.hpp | 2 +- src/gdb-stub/checksum.hpp | 1 + src/gdb-stub/gdb_stub.cpp | 26 +++- src/gdb-stub/gdb_stub.hpp | 5 +- src/windows-emulator/debugging/gdb_stub.cpp | 136 ------------------ src/windows-emulator/debugging/gdb_stub.hpp | 39 ----- .../debugging/win_x64_gdb_stub_handler.hpp | 17 ++- .../debugging/x64_gdb_stub_handler.hpp | 32 +++-- 9 files changed, 58 insertions(+), 207 deletions(-) delete mode 100644 src/windows-emulator/debugging/gdb_stub.cpp delete mode 100644 src/windows-emulator/debugging/gdb_stub.hpp diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 6dbdafdc..ef180990 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -4,7 +4,6 @@ #include #include "object_watching.hpp" -#include "gdb-stub/gdb_stub.hpp" namespace { @@ -53,7 +52,7 @@ namespace win_emu.log.print(color::pink, "Waiting for GDB connection on %s...\n", address); win_x64_gdb_stub_handler handler{win_emu}; - run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), address); + gdb_stub::run_gdb_stub(network::address{"0.0.0.0:28960", AF_INET}, handler); } else { @@ -182,7 +181,7 @@ namespace for (int i = 1; i < argc; ++i) { - args.push_back(argv[i]); + args.emplace_back(argv[i]); } return args; @@ -230,8 +229,6 @@ int main(const int argc, char** argv) { try { - gdb_stub::run_gdb_stub(network::address{"0.0.0.0:28960", AF_INET}); - auto args = bundle_arguments(argc, argv); const auto options = parse_options(args); diff --git a/src/gdb-stub/async_handler.hpp b/src/gdb-stub/async_handler.hpp index 30bfd769..608fdd66 100644 --- a/src/gdb-stub/async_handler.hpp +++ b/src/gdb-stub/async_handler.hpp @@ -9,7 +9,7 @@ namespace gdb_stub class async_handler { public: - using handler = void(const std::atomic_bool& should_run); + using handler = void(std::atomic_bool& should_run); using handler_function = std::function; async_handler(handler_function handler); diff --git a/src/gdb-stub/checksum.hpp b/src/gdb-stub/checksum.hpp index 1ad71bc1..533329d3 100644 --- a/src/gdb-stub/checksum.hpp +++ b/src/gdb-stub/checksum.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include namespace gdb_stub diff --git a/src/gdb-stub/gdb_stub.cpp b/src/gdb-stub/gdb_stub.cpp index a587fb79..4647ec64 100644 --- a/src/gdb-stub/gdb_stub.cpp +++ b/src/gdb-stub/gdb_stub.cpp @@ -3,8 +3,11 @@ #include #include "stream_processor.hpp" +#include "async_handler.hpp" #include "checksum.hpp" +using namespace std::literals; + namespace gdb_stub { namespace @@ -111,10 +114,16 @@ namespace gdb_stub const auto command = packet.front(); const auto event = handle_command(client, command, packet.substr(1)); + (void)event; + } + + bool is_interrupt_packet(const std::optional& data) + { + return data && data->size() == 1 && data->front() == '\x03'; } } - bool run_gdb_stub(const network::address& bind_address) + bool run_gdb_stub(const network::address& bind_address, gdb_stub_handler& handler) { stream_processor processor{}; @@ -124,6 +133,21 @@ namespace gdb_stub return false; } + async_handler async{[&](std::atomic_bool& can_run) { + while (can_run) + { + std::this_thread::sleep_for(10ms); + + const auto data = client.receive(1); + + if (is_interrupt_packet(data) || !client.is_valid()) + { + handler.on_interrupt(); + can_run = false; + } + } + }}; + client.set_blocking(false); while (client.is_valid()) diff --git a/src/gdb-stub/gdb_stub.hpp b/src/gdb-stub/gdb_stub.hpp index c8a09ae8..ec7629ac 100644 --- a/src/gdb-stub/gdb_stub.hpp +++ b/src/gdb-stub/gdb_stub.hpp @@ -4,7 +4,6 @@ namespace gdb_stub { - /* enum class gdb_action : uint8_t { none, @@ -42,7 +41,5 @@ namespace gdb_stub virtual std::string get_target_description() const = 0; }; - bool run_gdb_stub(gdb_stub_handler& handler, size_t register_count, const network::address& bind_address); - */ - bool run_gdb_stub(const network::address& bind_address); + bool run_gdb_stub(const network::address& bind_address, gdb_stub_handler& handler); } diff --git a/src/windows-emulator/debugging/gdb_stub.cpp b/src/windows-emulator/debugging/gdb_stub.cpp deleted file mode 100644 index 6d38a08f..00000000 --- a/src/windows-emulator/debugging/gdb_stub.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "../std_include.hpp" -#include "gdb_stub.hpp" - -#include - -extern "C" -{ -#include -} - -namespace -{ - gdb_action_t map_gdb_action(const gdb_action action) - { - switch (action) - { - case gdb_action::none: - return ACT_NONE; - case gdb_action::resume: - return ACT_RESUME; - case gdb_action::shutdown: - return ACT_SHUTDOWN; - } - - throw std::runtime_error("Bad action"); - } - - breakpoint_type map_breakpoint_type(const bp_type_t type) - { - switch (type) - { - case BP_SOFTWARE: - return breakpoint_type::software; - case BP_HARDWARE_EXEC: - return breakpoint_type::hardware_exec; - case BP_HARDWARE_WRITE: - return breakpoint_type::hardware_write; - case BP_HARDWARE_READ: - return breakpoint_type::hardware_read; - case BP_HARDWARE_READ_WRITE: - return breakpoint_type::hardware_read_write; - } - - throw std::runtime_error("Bad breakpoint type"); - } - - gdb_stub_handler& get_handler(void* args) - { - return *static_cast(args); - } - - gdb_action_t cont(void* args) - { - return map_gdb_action(get_handler(args).cont()); - } - - gdb_action_t stepi(void* args) - { - return map_gdb_action(get_handler(args).stepi()); - } - - int read_reg(void* args, const int regno, size_t* value) - { - return get_handler(args).read_reg(regno, value) ? 0 : 1; - } - - int write_reg(void* args, const int regno, const size_t value) - { - return get_handler(args).write_reg(regno, value) ? 0 : 1; - } - - int read_mem(void* args, const size_t addr, const size_t len, void* val) - { - return get_handler(args).read_mem(addr, len, val) ? 0 : 1; - } - - int write_mem(void* args, const size_t addr, const size_t len, void* val) - { - return get_handler(args).write_mem(addr, len, val) ? 0 : 1; - } - - bool set_bp(void* args, const size_t addr, const bp_type_t type, const size_t size) - { - return get_handler(args).set_bp(map_breakpoint_type(type), addr, size); - } - - bool del_bp(void* args, const size_t addr, const bp_type_t type, const size_t size) - { - return get_handler(args).del_bp(map_breakpoint_type(type), addr, size); - } - - void on_interrupt(void* args) - { - get_handler(args).on_interrupt(); - } - - target_ops get_target_ops() - { - target_ops ops{}; - - ops.cont = cont; - ops.stepi = stepi; - ops.read_reg = read_reg; - ops.write_reg = write_reg; - ops.read_mem = read_mem; - ops.write_mem = write_mem; - ops.set_bp = set_bp; - ops.del_bp = del_bp; - ops.on_interrupt = on_interrupt; - - return ops; - } -} - -bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, const size_t register_count, - std::string bind_address) -{ - const arch_info_t info{ - target_description.data(), - static_cast(register_count), - sizeof(uint64_t), - }; - - auto ops = get_target_ops(); - - gdbstub_t stub{}; - - if (!gdbstub_init(&stub, &ops, info, bind_address.data())) - { - return false; - } - - const auto _ = utils::finally([&] { gdbstub_close(&stub); }); - - return gdbstub_run(&stub, &handler); -} diff --git a/src/windows-emulator/debugging/gdb_stub.hpp b/src/windows-emulator/debugging/gdb_stub.hpp deleted file mode 100644 index de6101f3..00000000 --- a/src/windows-emulator/debugging/gdb_stub.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -enum class gdb_action : uint8_t -{ - none, - resume, - shutdown, -}; - -enum class breakpoint_type : uint8_t -{ - software, - hardware_exec, - hardware_write, - hardware_read, - hardware_read_write, -}; - -struct gdb_stub_handler -{ - virtual ~gdb_stub_handler() = default; - - virtual gdb_action cont() = 0; - virtual gdb_action stepi() = 0; - - virtual bool read_reg(int regno, size_t* value) = 0; - virtual bool write_reg(int regno, size_t value) = 0; - - virtual bool read_mem(size_t addr, size_t len, void* val) = 0; - virtual bool write_mem(size_t addr, size_t len, void* val) = 0; - - virtual bool set_bp(breakpoint_type type, size_t addr, size_t size) = 0; - virtual bool del_bp(breakpoint_type type, size_t addr, size_t size) = 0; - - virtual void on_interrupt() = 0; -}; - -bool run_gdb_stub(gdb_stub_handler& handler, std::string target_description, size_t register_count, - std::string bind_address); diff --git a/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp b/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp index ce2bc314..7f9574b6 100644 --- a/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp +++ b/src/windows-emulator/debugging/win_x64_gdb_stub_handler.hpp @@ -12,7 +12,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler { } - gdb_action cont() override + gdb_stub::gdb_action cont() override { try { @@ -20,13 +20,13 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler } catch (const std::exception& e) { - puts(e.what()); + this->win_emu_->log.error("%s\n", e.what()); } - return gdb_action::resume; + return gdb_stub::gdb_action::resume; } - gdb_action stepi() override + gdb_stub::gdb_action stepi() override { try { @@ -34,10 +34,15 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler } catch (const std::exception& e) { - puts(e.what()); + this->win_emu_->log.error("%s\n", e.what()); } - return gdb_action::resume; + return gdb_stub::gdb_action::resume; + } + + std::string get_target_description() const override + { + return "i386:x86-64"; } private: diff --git a/src/windows-emulator/debugging/x64_gdb_stub_handler.hpp b/src/windows-emulator/debugging/x64_gdb_stub_handler.hpp index 58e1a47b..fae1fe04 100644 --- a/src/windows-emulator/debugging/x64_gdb_stub_handler.hpp +++ b/src/windows-emulator/debugging/x64_gdb_stub_handler.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include "gdb_stub.hpp" #include "scoped_hook.hpp" #include +#include inline std::vector gdb_registers{ x64_register::rax, x64_register::rbx, x64_register::rcx, x64_register::rdx, x64_register::rsi, x64_register::rdi, @@ -16,18 +16,20 @@ inline std::vector gdb_registers{ x64_register::gs,*/ }; -inline memory_operation map_breakpoint_type(const breakpoint_type type) +inline memory_operation map_breakpoint_type(const gdb_stub::breakpoint_type type) { + using enum gdb_stub::breakpoint_type; + switch (type) { - case breakpoint_type::software: - case breakpoint_type::hardware_exec: + case software: + case hardware_exec: return memory_operation::exec; - case breakpoint_type::hardware_read: + case hardware_read: return memory_permission::read; - case breakpoint_type::hardware_write: + case hardware_write: return memory_permission::write; - case breakpoint_type::hardware_read_write: + case hardware_read_write: return memory_permission::read_write; default: throw std::runtime_error("Bad bp type"); @@ -38,7 +40,7 @@ struct breakpoint_key { size_t addr{}; size_t size{}; - breakpoint_type type{}; + gdb_stub::breakpoint_type type{}; bool operator==(const breakpoint_key& other) const { @@ -56,7 +58,7 @@ struct std::hash } }; -class x64_gdb_stub_handler : public gdb_stub_handler +class x64_gdb_stub_handler : public gdb_stub::gdb_stub_handler { public: x64_gdb_stub_handler(x64_emulator& emu) @@ -66,7 +68,7 @@ class x64_gdb_stub_handler : public gdb_stub_handler ~x64_gdb_stub_handler() override = default; - gdb_action cont() override + gdb_stub::gdb_action cont() override { try { @@ -77,10 +79,10 @@ class x64_gdb_stub_handler : public gdb_stub_handler puts(e.what()); } - return gdb_action::resume; + return gdb_stub::gdb_action::resume; } - gdb_action stepi() override + gdb_stub::gdb_action stepi() override { try { @@ -91,7 +93,7 @@ class x64_gdb_stub_handler : public gdb_stub_handler puts(e.what()); } - return gdb_action::resume; + return gdb_stub::gdb_action::resume; } bool read_reg(const int regno, size_t* value) override @@ -150,7 +152,7 @@ class x64_gdb_stub_handler : public gdb_stub_handler } } - bool set_bp(const breakpoint_type type, const size_t addr, const size_t size) override + bool set_bp(const gdb_stub::breakpoint_type type, const size_t addr, const size_t size) override { try { @@ -170,7 +172,7 @@ class x64_gdb_stub_handler : public gdb_stub_handler } } - bool del_bp(const breakpoint_type type, const size_t addr, const size_t size) override + bool del_bp(const gdb_stub::breakpoint_type type, const size_t addr, const size_t size) override { try {