commit 57e11b8a3fdad90f001f7a899fb4db86d0e80e22
parent dd0091f98422624598584141c5b51431974e3b5d
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 21 Jun 2015 21:56:37 -0700
gdb-bridge: support register writes, start on memory writes
Diffstat:
M | tools/gdb-bridge.c | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 77 insertions(+), 9 deletions(-)
diff --git a/tools/gdb-bridge.c b/tools/gdb-bridge.c
@@ -208,14 +208,29 @@ int gdb_recv(struct gdbcnxn *gc, unsigned char *ptr, int len) {
}
unsigned unhex(char *x) {
+ char tmp[3];
unsigned n;
- char t = x[2];
- x[2] = 0;
- n = strtoul(x, 0, 16);
- x[2] = t;
+ tmp[0] = x[0];
+ tmp[1] = x[1];
+ tmp[2] = 0;
+ n = strtoul(tmp, 0, 16);
return n;
}
+int hextobin(void *_dst, char *src, int max) {
+ unsigned char *dst = _dst;
+ while (max > 0) {
+ if (src[0] && src[1]) {
+ *dst++ = unhex(src);
+ src += 2;
+ max -= 2;
+ } else {
+ break;
+ }
+ }
+ return dst - ((unsigned char*) _dst);
+}
+
static const char *target_xml =
"<?xml version=\"1.0\"?>"
"<target>"
@@ -318,34 +333,87 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
swdp_core_halt();
break;
case 'H':
+ /* select thread - we've only got one */
gdb_puts(gc, "OK");
break;
+ // m hexaddr , hexcount
+ // read from memory
case 'm':
- if (sscanf((char*) cmd + 1, "%x,%x", &x, &n) != 2)
+ if (sscanf((char*) cmd + 1, "%x,%x", &x, &n) != 2) {
break;
-
- if (n > 1024)
+ }
+ if (n > 1024) {
n = 1024;
-
+ }
swdp_ahb_read32(x & (~3), tmp.w, ((n + 3) & (~3)) / 4);
gdb_puthex(gc, tmp.b + (x & 3), n);
- break;
+ break;
+ // M hexaddr , hexcount : hexbytes
+ // write to memory
+ case 'M': {
+ char *data = strchr((char*) cmd + 1, ':');
+ int len;
+ if (!data) {
+ break;
+ }
+ *data++ = 0;
+ if (sscanf((char*) cmd + 1, "%x,%x", &x, &n) != 2) {
+ break;
+ }
+ len = hextobin(gc->rxbuf, data, MAXPKT);
+ zprintf("write %d bytes at %x (%d recv)\n", n, x, len);
+ gdb_puts(gc, "EFF"); //Eerrno or OK
+ break;
+ }
+ // g
+ // read registers 0...
case 'g': {
u32 regs[19];
swdp_core_read_all(regs);
gdb_puthex(gc, regs, sizeof(regs));
break;
}
+ // G hexbytes
+ // write registers 0...
+ case 'G': {
+ int len = hextobin(gc->rxbuf, (char*) cmd + 1, MAXPKT);
+ for (n = 0; n < len / 4; n++) {
+ memcpy(&x, gc->rxbuf + (n * 4), sizeof(x));
+ swdp_core_write(n, x);
+ }
+ gdb_puts(gc, "OK");
+ break;
+ }
+ // p reghex
+ // read from register
case 'p': {
u32 v;
swdp_core_read(strtoul((char*) cmd + 1, NULL, 16), &v);
gdb_puthex(gc, &v, sizeof(v));
break;
}
+ // P reghex = hexbytes
+ // write to register
+ case 'P': {
+ int len;
+ char *data = strchr((char*) cmd + 1, '=');
+ if (data) {
+ *data++ = 0;
+ n = strtoul((char*) cmd + 1, NULL, 16);
+ len = hextobin(gc->rxbuf, data, MAXPKT);
+ if (len != 4) break;
+ memcpy(&x, gc->rxbuf, sizeof(x));
+ swdp_core_write(n, x);
+ gdb_puts(gc, "OK");
+ }
+ break;
+ }
+ // single step
case 's':
swdp_core_step();
gdb_puts(gc, "S00");
break;
+ // extended query and set commands
case 'q':
case 'Q': {
char *args = (char*) (cmd + 1);