Initialize debugger with the VM instance

This commit is contained in:
Konstantin Nazarov 2024-12-09 00:49:57 +00:00
parent 79177d17e5
commit c7ff2c784c
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
3 changed files with 71 additions and 68 deletions

View file

@ -1,6 +1,7 @@
#include "debug.hpp" #include "debug.hpp"
GDBStub::GDBStub(int port) : server_fd(-1), client_fd(-1), running(false) { GDBStub::GDBStub(VM &vm, int port)
: server_fd(-1), client_fd(-1), running(false), vm(vm) {
server_fd = socket(AF_INET, SOCK_STREAM, 0); server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) { if (server_fd == -1) {
throw std::runtime_error("Failed to create socket."); throw std::runtime_error("Failed to create socket.");
@ -11,7 +12,8 @@ GDBStub::GDBStub(int port) : server_fd(-1), client_fd(-1), running(false) {
server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port); server_addr.sin_port = htons(port);
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) ==
-1) {
throw std::runtime_error("Failed to bind socket."); throw std::runtime_error("Failed to bind socket.");
} }
@ -19,7 +21,8 @@ GDBStub::GDBStub(int port) : server_fd(-1), client_fd(-1), running(false) {
throw std::runtime_error("Failed to listen on socket."); throw std::runtime_error("Failed to listen on socket.");
} }
std::cout << "Waiting for GDB connection on port " << port << "..." << std::endl; std::cout << "Waiting for GDB connection on port " << port << "..."
<< std::endl;
client_fd = accept(server_fd, nullptr, nullptr); client_fd = accept(server_fd, nullptr, nullptr);
if (client_fd == -1) { if (client_fd == -1) {
throw std::runtime_error("Failed to accept connection."); throw std::runtime_error("Failed to accept connection.");
@ -49,9 +52,7 @@ void GDBStub::run() {
} }
} }
void GDBStub::stop() { void GDBStub::stop() { running = false; }
running = false;
}
void GDBStub::send_ack() { void GDBStub::send_ack() {
if (send(client_fd, "+", 1, 0) == -1) { if (send(client_fd, "+", 1, 0) == -1) {
@ -78,7 +79,8 @@ void GDBStub::send_packet(const std::string &packet) {
} }
std::ostringstream response; std::ostringstream response;
response << '$' << packet << '#' << std::hex << std::setfill('0') << std::setw(2) << (checksum & 0xFF); response << '$' << packet << '#' << std::hex << std::setfill('0')
<< std::setw(2) << (checksum & 0xFF);
const std::string response_str = response.str(); const std::string response_str = response.str();
if (send(client_fd, response_str.c_str(), response_str.size(), 0) == -1) { if (send(client_fd, response_str.c_str(), response_str.size(), 0) == -1) {
@ -121,68 +123,69 @@ std::string GDBStub::receive_packet() {
void GDBStub::handle_packet(const std::string &packet) { void GDBStub::handle_packet(const std::string &packet) {
switch (packet[0]) { switch (packet[0]) {
case '?': case '?':
send_packet("S05"); // TODO: real stop reason send_packet("S05"); // TODO: real stop reason
break; break;
case 'g': // Read all registers case 'g': // Read all registers
send_packet(read_registers()); send_packet(read_registers());
break; break;
case 'p': { case 'p': {
// Getting specific register // Getting specific register
int regnum = std::stoi(packet.substr(1), nullptr, 16); int regnum = std::stoi(packet.substr(1), nullptr, 16);
uint32_t reg_value = 0; uint32_t reg_value = 0;
std::ostringstream response; std::ostringstream response;
response << std::hex << std::setfill('0') << std::setw(8) << reg_value; response << std::hex << std::setfill('0') << std::setw(8) << reg_value;
send_packet(response.str()); send_packet(response.str());
break; break;
}
case 'G':
send_packet("OK"); // TODO: write registers
break;
case 'm': {
size_t addr, length;
if (parse_memory_request(packet, addr, length)) {
send_packet(read_memory(addr, length));
} else {
send_packet("E01"); // Error
} }
break;
}
case 'M': case 'G':
send_packet("OK"); // TODO: write memory send_packet("OK"); // TODO: write registers
break; break;
case 'c': case 'm': {
send_packet("S05"); // TODO: continue execution size_t addr, length;
break; if (parse_memory_request(packet, addr, length)) {
send_packet(read_memory(addr, length));
case 's': } else {
send_packet("S05"); // TODO: step execution send_packet("E01"); // Error
break; }
break;
case 'q':
if (packet.find("qSupported") == 0) {
send_packet("PacketSize=4096"); // Example capability
} else {
send_packet(""); // Empty response
} }
break;
default: case 'M':
send_packet(""); // Unsupported packet send_packet("OK"); // TODO: write memory
break; break;
case 'c':
send_packet("S05"); // TODO: continue execution
break;
case 's':
send_packet("S05"); // TODO: step execution
break;
case 'q':
if (packet.find("qSupported") == 0) {
send_packet("PacketSize=4096"); // Example capability
} else {
send_packet(""); // Empty response
}
break;
default:
send_packet(""); // Unsupported packet
break;
} }
} }
bool GDBStub::parse_memory_request(const std::string &packet, size_t &addr, size_t &length) { bool GDBStub::parse_memory_request(const std::string &packet, size_t &addr,
size_t &length) {
size_t comma_pos = packet.find(','); size_t comma_pos = packet.find(',');
if (comma_pos == std::string::npos) { if (comma_pos == std::string::npos) {
return false; return false;
@ -200,7 +203,7 @@ bool GDBStub::parse_memory_request(const std::string &packet, size_t &addr, size
std::string GDBStub::read_registers() { std::string GDBStub::read_registers() {
std::ostringstream out; std::ostringstream out;
for (int i = 0; i < 32; ++i) { for (int i = 0; i < 32; ++i) {
out << std::string(8, '0'); // TODO: stub out << std::string(8, '0'); // TODO: stub
} }
return out.str(); return out.str();
} }
@ -208,7 +211,7 @@ std::string GDBStub::read_registers() {
std::string GDBStub::read_memory(size_t addr, size_t length) { std::string GDBStub::read_memory(size_t addr, size_t length) {
std::ostringstream out; std::ostringstream out;
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
out << "00"; // TODO: stub out << "00"; // TODO: stub
} }
return out.str(); return out.str();
} }

View file

@ -17,7 +17,7 @@
class GDBStub { class GDBStub {
public: public:
GDBStub(int port); GDBStub(VM &vm, int port);
~GDBStub(); ~GDBStub();
void run(); void run();
@ -47,4 +47,6 @@ class GDBStub {
std::string read_registers(); std::string read_registers();
std::string read_memory(size_t addr, size_t length); std::string read_memory(size_t addr, size_t length);
VM &vm;
}; };

View file

@ -1,16 +1,14 @@
#include "vm.hpp"
#include "debug.hpp"
#include <iostream>
#include <cstdlib>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include "debug.hpp"
#include "vm.hpp"
int main(int argc, char* argv[]) { int main(int argc, char *argv[]) {
const size_t MEMORY_SIZE = 128*1024; const size_t MEMORY_SIZE = 128 * 1024;
bool debug = false; bool debug = false;
std::string program_filename = ""; std::string program_filename = "";
@ -39,7 +37,7 @@ int main(int argc, char* argv[]) {
if (!debug) { if (!debug) {
try { try {
vm.eval(); vm.eval();
} catch (const std::exception& e) { } catch (const std::exception &e) {
std::cerr << "Emulator error: " << e.what() << std::endl; std::cerr << "Emulator error: " << e.what() << std::endl;
return 1; return 1;
} }
@ -50,7 +48,7 @@ int main(int argc, char* argv[]) {
} else { } else {
// to debug, do: "set debug remote 1" in gdb // to debug, do: "set debug remote 1" in gdb
// and then "target remote :1234" // and then "target remote :1234"
GDBStub stub(1234); GDBStub stub(vm, 1234);
stub.run(); stub.run();
} }