GDB command progress

This commit is contained in:
momo5502
2025-01-18 09:20:08 +01:00
parent b180d9629c
commit 2044a3c4ab
4 changed files with 134 additions and 31 deletions

View File

@@ -47,7 +47,7 @@ namespace gdb_stub
return std::nullopt;
}
void connection_handler::send_packet(const std::string_view data) const
void connection_handler::send_reply(const std::string_view data) const
{
const auto checksum = utils::string::to_hex_string(compute_checksum(data));
this->send_raw_data("$" + std::string(data) + "#" + checksum);

View File

@@ -11,7 +11,7 @@ namespace gdb_stub
std::optional<std::string> get_packet();
void send_packet(std::string_view data) const;
void send_reply(std::string_view data) const;
void send_raw_data(std::string_view data) const;
void close() const;

View File

@@ -6,12 +6,20 @@
#include "async_handler.hpp"
#include "connection_handler.hpp"
#include <cassert>
#include <cinttypes>
using namespace std::literals;
namespace gdb_stub
{
namespace
{
void rt_assert(const bool condition)
{
assert(condition);
}
network::tcp_client_socket accept_client(const network::address& bind_address)
{
network::tcp_server_socket server{bind_address.get_family()};
@@ -23,7 +31,7 @@ namespace gdb_stub
return server.accept();
}
void process_query(const connection_handler& connection, const std::string_view payload)
std::pair<std::string_view, std::string_view> split_colon(const std::string_view payload)
{
auto name = payload;
std::string_view args{};
@@ -36,25 +44,50 @@ namespace gdb_stub
args = payload.substr(separator + 1);
}
if (name == "Supported")
return {name, args};
}
void process_xfer(const connection_handler& connection, gdb_stub_handler& handler,
const std::string_view payload)
{
auto [name, args] = split_colon(payload);
if (name == "features")
{
connection.send_packet("PacketSize=1024;qXfer:features:read+");
}
else if (name == "Attached")
{
connection.send_packet("1");
}
else if (name == "Xfer")
{
// process_xfer(gdbstub, args);
}
else if (name == "Symbol")
{
connection.send_packet("OK");
connection.send_reply("l<target version=\"1.0\"><architecture>" //
+ handler.get_target_description() //
+ "<architecture>%s</architecture></target>");
}
else
{
connection.send_packet({});
connection.send_reply({});
}
}
void process_query(const connection_handler& connection, gdb_stub_handler& handler,
const std::string_view payload)
{
auto [name, args] = split_colon(payload);
if (name == "Supported")
{
connection.send_reply("PacketSize=1024;qXfer:features:read+");
}
else if (name == "Attached")
{
connection.send_reply("1");
}
else if (name == "Xfer")
{
process_xfer(connection, handler, args);
}
else if (name == "Symbol")
{
connection.send_reply("OK");
}
else
{
connection.send_reply({});
}
}
@@ -66,8 +99,54 @@ namespace gdb_stub
}
}
void read_registers()
breakpoint_type translate_breakpoint_type(const uint32_t type)
{
if (type >= static_cast<size_t>(breakpoint_type::END))
{
return breakpoint_type::software;
}
return static_cast<breakpoint_type>(type);
}
bool change_breakpoint(gdb_stub_handler& handler, const bool set, const breakpoint_type type,
const uint64_t address, const size_t size)
{
if (set)
{
return handler.set_breakpoint(type, address, size);
}
return handler.delete_breakpoint(type, address, size);
}
void handle_breakpoint(const connection_handler& connection, gdb_stub_handler& handler, const std::string& data,
const bool set)
{
uint32_t type{};
uint64_t addr{};
size_t kind{};
rt_assert(sscanf(data.c_str(), "%x,%" PRIX64 ",%zx", &type, &addr, &kind) == 3);
const auto res = change_breakpoint(handler, set, translate_breakpoint_type(type), addr, kind);
connection.send_reply(res ? "OK" : "E01");
}
void handle_v_packet(const connection_handler& connection, const std::string_view data)
{
auto [name, args] = split_colon(data);
if (name == "Cont?")
{
// IDA pro gets confused if the reply arrives too early :(
std::this_thread::sleep_for(1s);
connection.send_reply("vCont;s;c;");
}
else
{
connection.send_reply({});
}
}
void handle_command(const connection_handler& connection, async_handler& async, gdb_stub_handler& handler,
@@ -86,13 +165,36 @@ namespace gdb_stub
break;
case 'q':
process_query(connection, data);
process_query(connection, handler, data);
break;
case 'g':
case 'D':
connection.close();
break;
case 'z':
case 'Z':
handle_breakpoint(connection, handler, std::string(data), command == 'Z');
break;
case '?':
connection.send_reply("S05");
break;
case 'v':
handle_v_packet(connection, data);
break;
// TODO
case 'g':
case 'm':
case 'p':
case 'G':
case 'M':
case 'P':
case 'X':
default:
connection.send_packet({});
connection.send_reply({});
break;
}
}

View File

@@ -13,11 +13,12 @@ namespace gdb_stub
enum class breakpoint_type : uint8_t
{
software,
hardware_exec,
hardware_write,
hardware_read,
hardware_read_write,
software = 0,
hardware_exec = 1,
hardware_write = 2,
hardware_read = 3,
hardware_read_write = 4,
END,
};
struct gdb_stub_handler
@@ -33,11 +34,11 @@ namespace gdb_stub
virtual bool read_register(size_t reg, void* data, size_t max_length) = 0;
virtual bool write_register(size_t reg, const void* data, size_t size) = 0;
virtual bool read_memory(size_t address, void* data, size_t length) = 0;
virtual bool write_memory(size_t address, const void* data, size_t length) = 0;
virtual bool read_memory(uint64_t address, void* data, size_t length) = 0;
virtual bool write_memory(uint64_t address, const void* data, size_t length) = 0;
virtual bool set_breakpoint(breakpoint_type type, size_t address, size_t size) = 0;
virtual bool delete_breakpoint(breakpoint_type type, size_t address, size_t size) = 0;
virtual bool set_breakpoint(breakpoint_type type, uint64_t address, size_t size) = 0;
virtual bool delete_breakpoint(breakpoint_type type, uint64_t address, size_t size) = 0;
virtual void on_interrupt() = 0;