Implement breakpoints
This commit is contained in:
parent
d0ff238cb0
commit
184c379e96
5 changed files with 61 additions and 11 deletions
|
@ -2,6 +2,12 @@
|
|||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
GDBStub::GDBStub(VM &vm, int port)
|
||||
: server_fd(-1), client_fd(-1), running(false), vm(vm) {
|
||||
server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -174,6 +180,12 @@ void GDBStub::handle_packet(const std::string &packet) {
|
|||
break;
|
||||
|
||||
case 'c':
|
||||
try {
|
||||
while (true) {
|
||||
vm.step();
|
||||
}
|
||||
} catch (const EbreakException &ex) {
|
||||
}
|
||||
send_packet("S05"); // TODO: continue execution
|
||||
break;
|
||||
|
||||
|
@ -189,6 +201,36 @@ void GDBStub::handle_packet(const std::string &packet) {
|
|||
send_packet(""); // Empty response
|
||||
}
|
||||
break;
|
||||
case 'Z': {
|
||||
// Insert breakpoint
|
||||
if (packet[1] == '0') {
|
||||
uint32_t addr =
|
||||
std::stoul(packet.substr(3, packet.find(',')), nullptr, 16);
|
||||
|
||||
if (breakpoints.count(addr) == 0) {
|
||||
uint32_t original_instr = vm.read_memory_word(addr);
|
||||
breakpoints[addr] = original_instr;
|
||||
vm.write_memory_word(addr, 0x00100073); // 0x00100073 is EBREAK
|
||||
}
|
||||
}
|
||||
send_packet("OK");
|
||||
break;
|
||||
}
|
||||
case 'z': {
|
||||
// Delete breakpoint
|
||||
if (packet[1] == '0') {
|
||||
uint32_t addr =
|
||||
std::stoul(packet.substr(3, packet.find(',')), nullptr, 16);
|
||||
|
||||
if (breakpoints.count(addr) > 0) {
|
||||
// Restore the original instruction
|
||||
vm.write_memory_word(addr, breakpoints[addr]);
|
||||
breakpoints.erase(addr);
|
||||
}
|
||||
}
|
||||
send_packet("OK");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
send_packet(""); // Unsupported packet
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "vm.hpp"
|
||||
|
||||
|
@ -49,4 +44,6 @@ class GDBStub {
|
|||
std::string read_memory(size_t addr, size_t length);
|
||||
|
||||
VM &vm;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> breakpoints;
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@ int main(int argc, char *argv[]) {
|
|||
if (!debug) {
|
||||
try {
|
||||
vm.eval();
|
||||
} catch (const EbreakException &e) {
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Emulator error: " << e.what() << std::endl;
|
||||
return 1;
|
||||
|
|
13
src/vm.cpp
13
src/vm.cpp
|
@ -52,6 +52,12 @@ std::vector<uint8_t> VM::read_memory(size_t start, size_t size) {
|
|||
memory_.begin() + start + size);
|
||||
}
|
||||
|
||||
uint32_t VM::read_memory_word(size_t pos) { return *(uint32_t*)&memory_[pos]; }
|
||||
|
||||
void VM::write_memory_word(size_t pos, uint32_t value) {
|
||||
*(uint32_t*)&memory_[pos] = value;
|
||||
}
|
||||
|
||||
uint32_t VM::read_register(size_t regnum) {
|
||||
if (regnum == 32) return pc;
|
||||
|
||||
|
@ -303,8 +309,9 @@ void VM::step() {
|
|||
(imm << 12); // Add the immediate (shifted left) to the current PC
|
||||
break;
|
||||
}
|
||||
case 0x73: { // EBREAK
|
||||
running = false; // Flag to stop the emulator
|
||||
case 0x73: { // EBREAK
|
||||
pc -= 4;
|
||||
throw EbreakException();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -313,7 +320,7 @@ void VM::step() {
|
|||
}
|
||||
|
||||
void VM::eval() {
|
||||
while (running) {
|
||||
while (true) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class EbreakException : std::exception {};
|
||||
|
||||
const int NUM_REGISTERS = 32; // Standard RISC-V has 32 registers
|
||||
|
||||
std::vector<uint8_t> load_program(const std::string& filename,
|
||||
|
@ -18,6 +20,9 @@ class VM {
|
|||
void eval();
|
||||
|
||||
std::vector<uint8_t> read_memory(size_t start, size_t size);
|
||||
uint32_t read_memory_word(size_t pos);
|
||||
void write_memory_word(size_t pos, uint32_t value);
|
||||
|
||||
uint32_t read_register(size_t regnum);
|
||||
|
||||
private:
|
||||
|
@ -25,6 +30,4 @@ class VM {
|
|||
|
||||
uint32_t registers[NUM_REGISTERS] = {0};
|
||||
uint32_t pc = 0;
|
||||
|
||||
bool running = true;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue