Support dump generation for GDB mode

This commit is contained in:
momo5502
2025-03-23 13:17:23 +01:00
parent 2bc3cda062
commit 7c3f848b36
8 changed files with 54 additions and 20 deletions

View File

@@ -14,7 +14,7 @@ namespace
{
struct analysis_options
{
bool use_gdb{false};
mutable bool use_gdb{false};
bool concise_logging{false};
bool verbose_logging{false};
bool silent{false};
@@ -98,7 +98,9 @@ namespace
const auto* address = "127.0.0.1:28960";
win_emu.log.print(color::pink, "Waiting for GDB connection on %s...\n", address);
win_x64_gdb_stub_handler handler{win_emu};
const auto should_stop = [&] { return signals_received > 0; };
win_x64_gdb_stub_handler handler{win_emu, should_stop};
gdb_stub::run_gdb_stub(network::address{"0.0.0.0:28960", AF_INET}, handler);
}
else
@@ -108,6 +110,8 @@ namespace
if (signals_received > 0)
{
options.use_gdb = false;
win_emu.log.log("Do you want to create a snapshot? (y/n)\n");
const auto write_snapshot = read_yes_no_answer();

View File

@@ -18,9 +18,9 @@ namespace network
tcp_client_socket accept();
void listen();
private:
bool listening_{false};
void listen();
};
}

View File

@@ -10,7 +10,6 @@ namespace utils
template <typename Ret, typename... Args>
class optional_function<Ret(Args...)>
{
private:
std::function<Ret(Args...)> func;
public:

View File

@@ -23,8 +23,10 @@ namespace gdb_stub
}
}
connection_handler::connection_handler(network::tcp_client_socket& client)
: client_(client)
connection_handler::connection_handler(network::tcp_client_socket& client,
utils::optional_function<bool()> should_stop)
: should_stop_(std::move(should_stop)),
client_(client)
{
this->client_.set_blocking(false);
@@ -48,7 +50,7 @@ namespace gdb_stub
std::optional<std::string> connection_handler::get_packet()
{
while (this->client_.is_valid() && !this->processor_.has_packet())
while (this->client_.is_valid() && !this->processor_.has_packet() && !this->should_stop_())
{
if (!read_from_socket(this->processor_, this->client_))
{

View File

@@ -1,7 +1,7 @@
#pragma once
#include "stream_processor.hpp"
#include <utils/concurrency.hpp>
#include <utils/function.hpp>
#include <network/tcp_client_socket.hpp>
#include <thread>
@@ -13,7 +13,7 @@ namespace gdb_stub
class connection_handler
{
public:
connection_handler(network::tcp_client_socket& client);
connection_handler(network::tcp_client_socket& client, utils::optional_function<bool()> should_stop = {});
~connection_handler();
connection_handler(connection_handler&&) = delete;
@@ -32,6 +32,7 @@ namespace gdb_stub
bool should_stop() const;
private:
utils::optional_function<bool()> should_stop_{};
network::tcp_client_socket& client_;
stream_processor processor_{};

View File

@@ -35,7 +35,8 @@ namespace gdb_stub
async_handler& async;
};
network::tcp_client_socket accept_client(const network::address& bind_address)
network::tcp_client_socket accept_client(const network::address& bind_address,
const utils::optional_function<bool()>& should_stop)
{
network::tcp_server_socket server{bind_address.get_family()};
if (!server.bind(bind_address))
@@ -43,6 +44,17 @@ namespace gdb_stub
return false;
}
server.set_blocking(false);
server.listen();
while (true)
{
if (should_stop() || server.sleep(100ms))
{
break;
}
}
return server.accept();
}
@@ -593,7 +605,11 @@ namespace gdb_stub
bool run_gdb_stub(const network::address& bind_address, debugging_handler& handler)
{
auto client = accept_client(bind_address);
const auto should_stop = [&] {
return handler.should_stop(); //
};
auto client = accept_client(bind_address, should_stop);
if (!client)
{
return false;
@@ -602,11 +618,10 @@ namespace gdb_stub
async_handler async{[&](std::atomic_bool& can_run) {
while (can_run)
{
std::this_thread::sleep_for(10ms);
(void)client.sleep(100ms);
const auto data = client.receive(1);
if (is_interrupt_packet(data) || !client.is_valid())
if (is_interrupt_packet(data) || !client.is_valid() || should_stop())
{
handler.on_interrupt();
can_run = false;
@@ -615,7 +630,7 @@ namespace gdb_stub
}};
debugging_state state{};
connection_handler connection{client};
connection_handler connection{client, should_stop};
debugging_context c{
.connection = connection,
@@ -624,10 +639,10 @@ namespace gdb_stub
.async = async,
};
while (true)
while (!should_stop())
{
const auto packet = connection.get_packet();
if (!packet)
if (!packet || should_stop())
{
break;
}

View File

@@ -50,6 +50,11 @@ namespace gdb_stub
virtual std::vector<uint32_t> get_thread_ids() = 0;
virtual std::optional<uint32_t> get_exit_code() = 0;
virtual bool should_stop()
{
return false;
}
};
bool run_gdb_stub(const network::address& bind_address, debugging_handler& handler);

View File

@@ -2,16 +2,23 @@
#include "x64_gdb_stub_handler.hpp"
#include <windows_emulator.hpp>
#include <utils/function.hpp>
class win_x64_gdb_stub_handler : public x64_gdb_stub_handler
{
public:
win_x64_gdb_stub_handler(windows_emulator& win_emu)
win_x64_gdb_stub_handler(windows_emulator& win_emu, utils::optional_function<bool()> should_stop = {})
: x64_gdb_stub_handler(win_emu.emu()),
win_emu_(&win_emu)
win_emu_(&win_emu),
should_stop_(std::move(should_stop))
{
}
bool should_stop() override
{
return this->should_stop_();
}
gdb_stub::action run() override
{
try
@@ -81,4 +88,5 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler
private:
windows_emulator* win_emu_{};
utils::optional_function<bool()> should_stop_{};
};