summaryrefslogtreecommitdiff
path: root/gdb_remote.c
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-09-04 19:34:19 -0700
committerMike Pavone <pavone@retrodev.com>2013-09-04 19:34:19 -0700
commit13c9ce6e0b47a724bf97584a0eafa3ad065f3741 (patch)
tree114c02a379447749d7bc64ba2619b703e68dda69 /gdb_remote.c
parentdc502d20a102160fdbad0f5abc02a9f44e3143c0 (diff)
Initial work on GDB remote debugging support
Diffstat (limited to 'gdb_remote.c')
-rw-r--r--gdb_remote.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/gdb_remote.c b/gdb_remote.c
new file mode 100644
index 0000000..888bbb8
--- /dev/null
+++ b/gdb_remote.c
@@ -0,0 +1,123 @@
+#include "blastem.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define INITIAL_BUFFER_SIZE 4096
+
+char * buf = NULL;
+char * curbuf = NULL;
+size_t bufsize;
+int cont = 0;
+int expect_break_response=0;
+uint32_t resume_pc;
+
+void gdb_debug_enter(genesis_context * gen, uint32_t pc)
+{
+ resume_pc = pc;
+ while(!cont)
+ {
+ }
+ cont = 0;
+}
+
+void gdb_run_command(genesis_context * gen, char * command)
+{
+ switch(*command)
+ {
+ case 'c':
+ if (*(command+1) != 0) {
+ resume_pc =
+ }
+ cont = 1;
+ expect_break_response = 1;
+ break;
+ case 's':
+
+ }
+}
+
+void gdb_run_commands(genesis_context * gen)
+{
+ int enter_debugger = 0;
+ char * cur = buf;
+ while(cur < curbuf);
+ {
+ if(*cur == '$') {
+ cur++
+ char * start = cur;
+ while (cur < curbuf && *cur != '#') {
+ cur++;
+ }
+ if (*cur == '#') {
+ //check to make sure we've received the checksum bytes
+ if (curbuf-cur >= 2) {
+ //TODO: verify checksum
+ //Null terminate payload
+ //send acknowledgement
+ write(FILENO_STDOUT, "+", 1);
+ gdb_run_command(genesis_context * gen, start);
+ cur += 2;
+ } else {
+ cur = start - 1;
+ break;
+ }
+ } else {
+ cur = start - 1;
+ break;
+ }
+ } else {
+ if (*cur == 0x03) {
+ enter_debugger = 1;
+ }
+ cur++;
+ }
+ }
+
+ //FIXME
+ if (consumed == curbuf-buf) {
+ curbuf = buf;
+ } else if (consumed > 0) {
+ memmove(buf, buf + consumed, curbuf - buf - consumed);
+ curbuf -= consumed;
+ }
+}
+
+void gdb_command_poll(genesis_context * gen)
+{
+ for(;;)
+ {
+ if (curbuf == buf + bufsize) {
+ //buffer is full, expand it
+ bufsize *= 2;
+ buf = realloc(buf, bufsize);
+ if (!buf) {
+ fprintf(stderr, "Failed to grow GDB command buffer to %d bytes\n", (int)bufsize);
+ exit(1);
+ }
+ curbuf = buf + bufsize/2;
+ }
+ int numread = read(STDIN_FILENO, buf, bufsize - (curbuf-buf));
+ if (numread < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ return;
+ } else {
+ fprintf(stderr, "Error %d while reading GDB commands from stdin", errno);
+ exit(1);
+ }
+ } else if (numread == 0) {
+ exit(0);
+ }
+ gdb_run_commands(genesis_context * gen);
+ }
+}
+
+void gdb_remote_init()
+{
+ fcntl(STDIN_FILENO, FD_SETFL, O_NONBLOCK);
+ buf = malloc(INITIAL_BUFFER_SIZE);
+ curbuf = buf;
+ bufzie = INITIAL_BUFFER_SIZE;
+}