mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Integrate new gdb stub
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
#include <debugging/win_x64_gdb_stub_handler.hpp>
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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<handler>;
|
||||
|
||||
async_handler(handler_function handler);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
|
||||
namespace gdb_stub
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
#include <network/tcp_server_socket.hpp>
|
||||
|
||||
#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<std::string>& 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())
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
#include "../std_include.hpp"
|
||||
#include "gdb_stub.hpp"
|
||||
|
||||
#include <utils/finally.hpp>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <gdbstub.h>
|
||||
}
|
||||
|
||||
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<gdb_stub_handler*>(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<int>(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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include <x64_emulator.hpp>
|
||||
#include "gdb_stub.hpp"
|
||||
#include "scoped_hook.hpp"
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <gdb-stub/gdb_stub.hpp>
|
||||
|
||||
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<breakpoint_key>
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user