diff --git a/include/server.h b/include/server.h index 39260b4..8dfdebb 100644 --- a/include/server.h +++ b/include/server.h @@ -6,6 +6,12 @@ #include #include +typedef enum rdb_server_state_t { + state_stopped, + state_running, + state_stepping +} rdb_server_state_t; + typedef enum rdb_server_stop_reason_t { /* not even stopped */ stop_reason_none, @@ -22,13 +28,14 @@ typedef enum 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_state_t state; rdb_server_stop_reason_t stopreason; } RdbServer; void rdbServerInit(RdbServer *srv, VB *sim); +bool rdbServerIsRunning(RdbServer *srv); int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res); int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *res); diff --git a/main.c b/main.c index 72719af..b44d39b 100644 --- a/main.c +++ b/main.c @@ -44,14 +44,14 @@ int server(int connfd, VB *sim) { printf("client has disconnected\n"); return 0; } else if (read_result == read_result_pending) { - if (srv.running) { + if (rdbServerIsRunning(&srv)) { cycles = MAX_STEP_CYCLES; brk = vbEmulate(sim, &cycles); if (brk) { /* We stopped for some reason */ if (brk == -1) { /* the reason was "opcode not implemented" */ - srv.running = false; + srv.state = state_stopped; srv.stopreason = stop_reason_not_implemented; } result = rdbServerSendStopPacket(&srv, &res); @@ -70,7 +70,7 @@ int server(int connfd, VB *sim) { if (result != 0) { return result; } - rdbRequestSetBlocking(&req, !srv.running); + rdbRequestSetBlocking(&req, !rdbServerIsRunning(&srv)); rdbRequestReset(&req); } @@ -140,10 +140,6 @@ int main(int argc, char** argv) { if (readROM(sim, argv[1])) { 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; diff --git a/server.c b/server.c index 24da6d3..ad9b7bf 100644 --- a/server.c +++ b/server.c @@ -76,8 +76,22 @@ static int onExecute(VB *sim, uint32_t address, const uint16_t *code, int length (void)sim; (void)code; (void)length; + + /* if we're stopped, just stop */ + if (srv->state == state_stopped) { + return 1; + } + + /* if we're stepping, we'll run this one instruction but no others */ + if (srv->state == state_stepping) { + srv->state = state_stopped; + srv->stopreason = stop_reason_trace; + return 0; + } + for (i = 0; i < srv->brkslen; ++i) { if (srv->brks[i] == address) { + srv->state = state_stopped; srv->stopreason = stop_reason_breakpoint; return 1; } @@ -115,8 +129,8 @@ static void removeBreakpoint(RdbServer *srv, uint32_t address) { void rdbServerInit(RdbServer *srv, VB *sim) { srv->sim = sim; - srv->running = false; srv->brkslen = 0; + srv->state = state_stopped; srv->stopreason = stop_reason_none; vbSetUserData(sim, srv); vbSetExecuteCallback(sim, onExecute); @@ -134,7 +148,7 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) { } if (cmdMatchStr(cmd, "qSupported")) { /* The debugger is asking for a list of features we support. */ - rdbResponseWriteStr(res, "no-resumed+;multiprocess;vContSupported;QNonStop+"); + rdbResponseWriteStr(res, "no-resumed+;multiprocess;vContSupported"); return rdbResponseSendPacket(res); } if (cmdMatchStr(cmd, "QThreadSuffixSupported")) { @@ -187,6 +201,11 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) { rdbResponseWriteStr(res, "c;C;s;S"); return rdbResponseSendPacket(res); } + if (cmdMatchStr(cmd, "vCont;s:1")) { + /* The debugger wants us to step */ + srv->state = state_stepping; + return 0; + } if (cmdMatchStr(cmd, "qC")) { /* The debugger is asking for the current thread id. Return "thread 1". */ rdbResponseWriteStr(res, "QCp1.t1"); @@ -246,13 +265,13 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) { if (cmdMatchStr(cmd, "c")) { /* 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->state = state_running; 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->state = state_stopped; srv->stopreason = stop_reason_trap; /* Send the response to the "c" command from before. */ return rdbServerSendStopPacket(srv, res); @@ -265,7 +284,10 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) { /* read memory */ uint32_t i, address, len; if (!cmdMatchHexNumber(cmd, &address)) return -1; - if (!cmdMatchStr(cmd, ",")) return -1; + if (!cmdMatchStr(cmd, ",")) { + /* if the server asks for too much memory, just error */ + return rdbResponseSendPacket(res); + }; if (!cmdMatchHexNumber(cmd, &len)) return -1; for (i = 0; i < len; ++i) { @@ -314,6 +336,11 @@ int rdbServerHandleCommand(RdbServer *srv, CommandBuf *cmd, RdbResponse *res) { return rdbResponseSendPacket(res); } +bool rdbServerIsRunning(RdbServer *srv) { + /* stepping counts */ + return srv->state != state_stopped; +} + int rdbServerSendStopPacket(RdbServer *srv, RdbResponse *res) { rdbResponseBeginPacket(res); switch (srv->stopreason) {