Implement breakpoints (untested)
This commit is contained in:
parent
bb680f9be4
commit
1b0d2d61b3
|
@ -6,13 +6,30 @@
|
|||
#include <stdbool.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 {
|
||||
VB *sim;
|
||||
bool running;
|
||||
uint32_t brks[RDB_SERVER_MAX_BREAKPOINTS];
|
||||
uint32_t brkslen;
|
||||
rdb_server_stop_reason_t stopreason;
|
||||
} RdbServer;
|
||||
|
||||
void rdbServerInit(RdbServer *srv, VB *sim);
|
||||
int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res);
|
||||
int rdbServerBreak(RdbServer *srv, RdbResponse *res);
|
||||
int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *res);
|
||||
|
||||
#endif
|
16
main.c
16
main.c
|
@ -48,13 +48,15 @@ int server(int connfd, VB *sim) {
|
|||
cycles = MAX_STEP_CYCLES;
|
||||
brk = vbEmulate(sim, &cycles);
|
||||
if (brk) {
|
||||
/* We hit a breakpoint */
|
||||
/* We stopped for some reason */
|
||||
if (brk == -1) {
|
||||
/* actually, not implemented */
|
||||
rdbServerBreak(&srv, &res);
|
||||
} else {
|
||||
fprintf(stderr, "surprising response %d from vbEmulate\n", brk);
|
||||
return -1;
|
||||
/* the reason was "opcode not implemented" */
|
||||
srv.running = false;
|
||||
srv.stopreason = stop_reason_not_implemented;
|
||||
}
|
||||
result = rdbServerSendStopPacket(&srv, &res);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
sleepNanos((MAX_STEP_CYCLES - cycles) * 50);
|
||||
|
@ -139,11 +141,9 @@ int main(int argc, char** argv) {
|
|||
return 1;
|
||||
}
|
||||
/* relevant state at the start of the physics sim's main */
|
||||
/*
|
||||
vbSetProgramCounter(sim, 0x070002ba);
|
||||
vbSetProgramRegister(sim, 3, 0x0500ffc0);
|
||||
vbSetProgramRegister(sim, 4, 0x05008000);
|
||||
*/
|
||||
|
||||
if (argc > 2) {
|
||||
char *end;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
void rdbRequestInit(RdbRequest *req, int connfd, char *buf, size_t buflen) {
|
||||
req->connfd = connfd;
|
||||
req->outbuf = buf;
|
||||
req->outbuflen = buflen;
|
||||
req->blocking = true;
|
||||
rdbRequestReset(req);
|
||||
}
|
||||
|
|
109
server.c
109
server.c
|
@ -69,9 +69,59 @@ const uint32_t SYSTEM_REGISTERS[] = {
|
|||
|
||||
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) {
|
||||
srv->sim = sim;
|
||||
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) {
|
||||
|
@ -199,21 +249,19 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
|||
/* 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). */
|
||||
srv->running = true;
|
||||
srv->stopreason = stop_reason_none;
|
||||
return 0;
|
||||
}
|
||||
if (cmdMatchStr(cmd, "\x03")) {
|
||||
/* Received an ETX, indicating that the server wants to cancel the "c" command from before. */
|
||||
srv->running = false;
|
||||
srv->stopreason = stop_reason_trap;
|
||||
/* Send the response to the "c" command from before. */
|
||||
rdbResponseWriteStr(res, "T05thread:p1.t1;threads:p1.t1");
|
||||
return rdbResponseSendPacket(res);
|
||||
return rdbServerSendStopPacket(srv, res);
|
||||
}
|
||||
if (cmdMatchStr(cmd, "?")) {
|
||||
/* The debugger has asked us why we stopped */
|
||||
rdbResponseWriteStr(res, "T");
|
||||
rdbResponseWriteStr(res, srv->running ? "00" : "05");
|
||||
rdbResponseWriteStr(res, "thread:p1.t1;threads:p1.t1;");
|
||||
return rdbResponseSendPacket(res);
|
||||
return rdbServerSendStopPacket(srv, res);
|
||||
}
|
||||
if (cmdMatchStr(cmd, "m")) {
|
||||
/* read memory */
|
||||
|
@ -244,14 +292,55 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) {
|
|||
rdbResponseWriteStr(res, "OK");
|
||||
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");
|
||||
return rdbResponseSendPacket(res);
|
||||
}
|
||||
|
||||
int rdbServerBreak(RdbServer *srv, RdbResponse *res) {
|
||||
srv->running = false;
|
||||
int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue