Implement breakpoints (untested)
This commit is contained in:
parent
bb680f9be4
commit
1b0d2d61b3
|
@ -6,13 +6,30 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <vb.h>
|
#include <vb.h>
|
||||||
|
|
||||||
|
typedef enum rdb_server_stop_reason_t {
|
||||||
|
/* not even stopped */
|
||||||
|
stop_reason_none,
|
||||||
|
/* we are stepping */
|
||||||
|
stop_reason_trace,
|
||||||
|
/* we hit an actual breakpoint */
|
||||||
|
stop_reason_breakpoint,
|
||||||
|
/* the user hit pause */
|
||||||
|
stop_reason_trap,
|
||||||
|
/* some opcode is not implemented */
|
||||||
|
stop_reason_not_implemented
|
||||||
|
} rdb_server_stop_reason_t;
|
||||||
|
|
||||||
|
#define RDB_SERVER_MAX_BREAKPOINTS 16
|
||||||
typedef struct RdbServer {
|
typedef struct RdbServer {
|
||||||
VB *sim;
|
VB *sim;
|
||||||
bool running;
|
bool running;
|
||||||
|
uint32_t brks[RDB_SERVER_MAX_BREAKPOINTS];
|
||||||
|
uint32_t brkslen;
|
||||||
|
rdb_server_stop_reason_t stopreason;
|
||||||
} RdbServer;
|
} RdbServer;
|
||||||
|
|
||||||
void rdbServerInit(RdbServer *srv, VB *sim);
|
void rdbServerInit(RdbServer *srv, VB *sim);
|
||||||
int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res);
|
int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res);
|
||||||
int rdbServerBreak(RdbServer *srv, RdbResponse *res);
|
int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *res);
|
||||||
|
|
||||||
#endif
|
#endif
|
16
main.c
16
main.c
|
@ -48,13 +48,15 @@ int server(int connfd, VB *sim) {
|
||||||
cycles = MAX_STEP_CYCLES;
|
cycles = MAX_STEP_CYCLES;
|
||||||
brk = vbEmulate(sim, &cycles);
|
brk = vbEmulate(sim, &cycles);
|
||||||
if (brk) {
|
if (brk) {
|
||||||
/* We hit a breakpoint */
|
/* We stopped for some reason */
|
||||||
if (brk == -1) {
|
if (brk == -1) {
|
||||||
/* actually, not implemented */
|
/* the reason was "opcode not implemented" */
|
||||||
rdbServerBreak(&srv, &res);
|
srv.running = false;
|
||||||
} else {
|
srv.stopreason = stop_reason_not_implemented;
|
||||||
fprintf(stderr, "surprising response %d from vbEmulate\n", brk);
|
}
|
||||||
return -1;
|
result = rdbServerSendStopPacket(&srv, &res);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sleepNanos((MAX_STEP_CYCLES - cycles) * 50);
|
sleepNanos((MAX_STEP_CYCLES - cycles) * 50);
|
||||||
|
@ -139,11 +141,9 @@ int main(int argc, char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* relevant state at the start of the physics sim's main */
|
/* relevant state at the start of the physics sim's main */
|
||||||
/*
|
|
||||||
vbSetProgramCounter(sim, 0x070002ba);
|
vbSetProgramCounter(sim, 0x070002ba);
|
||||||
vbSetProgramRegister(sim, 3, 0x0500ffc0);
|
vbSetProgramRegister(sim, 3, 0x0500ffc0);
|
||||||
vbSetProgramRegister(sim, 4, 0x05008000);
|
vbSetProgramRegister(sim, 4, 0x05008000);
|
||||||
*/
|
|
||||||
|
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
char *end;
|
char *end;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
void rdbRequestInit(RdbRequest *req, int connfd, char *buf, size_t buflen) {
|
void rdbRequestInit(RdbRequest *req, int connfd, char *buf, size_t buflen) {
|
||||||
req->connfd = connfd;
|
req->connfd = connfd;
|
||||||
req->outbuf = buf;
|
req->outbuf = buf;
|
||||||
|
req->outbuflen = buflen;
|
||||||
req->blocking = true;
|
req->blocking = true;
|
||||||
rdbRequestReset(req);
|
rdbRequestReset(req);
|
||||||
}
|
}
|
||||||
|
|
109
server.c
109
server.c
|
@ -69,9 +69,59 @@ const uint32_t SYSTEM_REGISTERS[] = {
|
||||||
|
|
||||||
const uint32_t PC_INDEX = 32 + 13;
|
const uint32_t PC_INDEX = 32 + 13;
|
||||||
|
|
||||||
|
/* TODO: this should use userdata */
|
||||||
|
static void *SERVER_POINTER;
|
||||||
|
static int onExecute(VB *sim, uint32_t address, const uint16_t *code, int length) {
|
||||||
|
uint32_t i;
|
||||||
|
RdbServer *srv = SERVER_POINTER;
|
||||||
|
|
||||||
|
(void)sim;
|
||||||
|
(void)code;
|
||||||
|
(void)length;
|
||||||
|
for (i = 0; i < srv->brkslen; ++i) {
|
||||||
|
if (srv->brks[i] == address) {
|
||||||
|
srv->stopreason = stop_reason_breakpoint;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool addBreakpoint(RdbServer *srv, uint32_t address) {
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < srv->brkslen; ++i) {
|
||||||
|
if (srv->brks[i] == address) {
|
||||||
|
/* This breakpoint is already set */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == RDB_SERVER_MAX_BREAKPOINTS) {
|
||||||
|
/* We've added too many breakpoints */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
srv->brks[i] = address;
|
||||||
|
++srv->brkslen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void removeBreakpoint(RdbServer *srv, uint32_t address) {
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < srv->brkslen; ++i) {
|
||||||
|
if (srv->brks[i] == address) {
|
||||||
|
srv->brks[i] = srv->brks[srv->brkslen - 1];
|
||||||
|
--srv->brkslen;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void rdbServerInit(RdbServer *srv, VB *sim) {
|
void rdbServerInit(RdbServer *srv, VB *sim) {
|
||||||
srv->sim = sim;
|
srv->sim = sim;
|
||||||
srv->running = false;
|
srv->running = false;
|
||||||
|
srv->brkslen = 0;
|
||||||
|
srv->stopreason = stop_reason_none;
|
||||||
|
SERVER_POINTER = srv;
|
||||||
|
vbSetCallback(sim, VB_EXECUTE, (void*)(uint64_t)&onExecute);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
||||||
|
@ -199,21 +249,19 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
||||||
/* The debugger has told us to run until we are stopped. */
|
/* The debugger has told us to run until we are stopped. */
|
||||||
/* Don't send a response to this until we receive an ETX (when the debugger pauses us). */
|
/* Don't send a response to this until we receive an ETX (when the debugger pauses us). */
|
||||||
srv->running = true;
|
srv->running = true;
|
||||||
|
srv->stopreason = stop_reason_none;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (cmdMatchStr(cmd, "\x03")) {
|
if (cmdMatchStr(cmd, "\x03")) {
|
||||||
/* Received an ETX, indicating that the server wants to cancel the "c" command from before. */
|
/* Received an ETX, indicating that the server wants to cancel the "c" command from before. */
|
||||||
srv->running = false;
|
srv->running = false;
|
||||||
|
srv->stopreason = stop_reason_trap;
|
||||||
/* Send the response to the "c" command from before. */
|
/* Send the response to the "c" command from before. */
|
||||||
rdbResponseWriteStr(res, "T05thread:p1.t1;threads:p1.t1");
|
return rdbServerSendStopPacket(srv, res);
|
||||||
return rdbResponseSendPacket(res);
|
|
||||||
}
|
}
|
||||||
if (cmdMatchStr(cmd, "?")) {
|
if (cmdMatchStr(cmd, "?")) {
|
||||||
/* The debugger has asked us why we stopped */
|
/* The debugger has asked us why we stopped */
|
||||||
rdbResponseWriteStr(res, "T");
|
return rdbServerSendStopPacket(srv, res);
|
||||||
rdbResponseWriteStr(res, srv->running ? "00" : "05");
|
|
||||||
rdbResponseWriteStr(res, "thread:p1.t1;threads:p1.t1;");
|
|
||||||
return rdbResponseSendPacket(res);
|
|
||||||
}
|
}
|
||||||
if (cmdMatchStr(cmd, "m")) {
|
if (cmdMatchStr(cmd, "m")) {
|
||||||
/* read memory */
|
/* read memory */
|
||||||
|
@ -244,14 +292,55 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
||||||
rdbResponseWriteStr(res, "OK");
|
rdbResponseWriteStr(res, "OK");
|
||||||
return rdbResponseSendPacket(res);
|
return rdbResponseSendPacket(res);
|
||||||
}
|
}
|
||||||
|
if (cmdMatchStr(cmd, "Z0,")) {
|
||||||
|
/* set a breakpoint */
|
||||||
|
uint32_t address;
|
||||||
|
if (!cmdMatchHexNumber(cmd, &address)) return -1;
|
||||||
|
if (!cmdMatchStr(cmd, ",0")) return -1;
|
||||||
|
|
||||||
|
if (!addBreakpoint(srv, address)) return -1;
|
||||||
|
rdbResponseWriteStr(res, "OK");
|
||||||
|
return rdbResponseSendPacket(res);
|
||||||
|
}
|
||||||
|
if (cmdMatchStr(cmd, "z0,")) {
|
||||||
|
/* remove a breakpoint */
|
||||||
|
uint32_t address;
|
||||||
|
if (!cmdMatchHexNumber(cmd, &address)) return -1;
|
||||||
|
if (!cmdMatchStr(cmd, ",0")) return -1;
|
||||||
|
|
||||||
|
removeBreakpoint(srv, address);
|
||||||
|
rdbResponseWriteStr(res, "OK");
|
||||||
|
return rdbResponseSendPacket(res);
|
||||||
|
}
|
||||||
fprintf(stderr, "Unrecognized command.\n");
|
fprintf(stderr, "Unrecognized command.\n");
|
||||||
return rdbResponseSendPacket(res);
|
return rdbResponseSendPacket(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rdbServerBreak(RdbServer *srv, RdbResponse *res) {
|
int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *res) {
|
||||||
srv->running = false;
|
|
||||||
rdbResponseBeginPacket(res);
|
rdbResponseBeginPacket(res);
|
||||||
rdbResponseWriteStr(res, "T05:thread:p1.t1;threads:p1.t1;");
|
switch (srv->stopreason) {
|
||||||
|
case stop_reason_trace:
|
||||||
|
case stop_reason_none:
|
||||||
|
rdbResponseWriteStr(res, "T00");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rdbResponseWriteStr(res, "T05");
|
||||||
|
}
|
||||||
|
rdbResponseWriteStr(res, "thread:p1.t1;threads:p1.t1;");
|
||||||
|
switch (srv->stopreason) {
|
||||||
|
case stop_reason_trace:
|
||||||
|
rdbResponseWriteStr(res, "reason:trace;");
|
||||||
|
break;
|
||||||
|
case stop_reason_breakpoint:
|
||||||
|
rdbResponseWriteStr(res, "reason:breakpoint;");
|
||||||
|
break;
|
||||||
|
case stop_reason_trap:
|
||||||
|
rdbResponseWriteStr(res, "reason:trap;");
|
||||||
|
break;
|
||||||
|
case stop_reason_not_implemented:
|
||||||
|
rdbResponseWriteStr(res, "reason:exception;description:opcode not implemented;");
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
return rdbResponseSendPacket(res);
|
return rdbResponseSendPacket(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue