Browse Source

Implement get_reg for gdbserver

Rather important for getting the stack pointer to step out of functions.
Also tidy the formatting of some error messages that showed up alongside the bug.

Seems the list of registers is duplicated in sys/src/9/amd64/dat.h
We should probably pick one place for this to avoid the duplication.

Signed-off-by: Graham MacDonald <grahamamacdonald@gmail.com>
Graham MacDonald 7 years ago
parent
commit
c83827e49f

+ 30 - 1
sys/src/cmd/gdbserver/gdb.h

@@ -93,6 +93,35 @@ enum regnames {
 	GDB_GS,			/* 23 */
 };
 
+// Again, this is very gdb-specific.  Order should be maintained the table above
+static const
+char* regstrs[] = {
+	"AX",
+	"BX",
+	"CX",
+	"DX",
+	"SI",
+	"DI",
+	"BP",
+	"SP",
+	"R8",
+	"R9",
+	"R10",
+	"R11",
+	"R12",
+	"R13",
+	"R14",
+	"R15",
+	"PC",
+	"PS",
+	"CS",
+	"SS",
+	"DS",
+	"ES",
+	"FS",
+	"GS",
+};
+
 #define GDB_ORIG_AX		57
 #define DBG_MAX_REG_NUM		24
 /* 17 64 bit regs and 5 32 bit regs */
@@ -182,7 +211,7 @@ char *mem2hex(unsigned char *mem, char *buf, int count);
 char *hex2mem(char *buf, unsigned char *mem, int count);
 void gdb_cmd_reg_get(struct state *ks);
 void gdb_cmd_reg_set(struct state *ks);
-
+uint64_t arch_get_reg(struct state *ks, int regnum);
 
 extern int isremovedbreak(unsigned long addr);
 extern void schedule_breakpoint(void);

+ 18 - 9
sys/src/cmd/gdbserver/gdbstub.c

@@ -1,4 +1,4 @@
-/*
+	/*
  * Kernel Debug Core
  *
  * Maintainer: Jason Wessel <jason.wessel@windriver.com>
@@ -56,6 +56,8 @@ int debug = 0;
 int attached_to_existing_pid = 0;
 Map* cormap;
 
+static struct state ks;
+
 /* support crap */
 /*
  * GDB remote protocol parser:
@@ -604,14 +606,23 @@ int_to_threadref(unsigned char *id, int value)
 uint64_t
 get_reg(Map *map, char *reg)
 {
-	//uint64_t v;
-	//int ret = get8(map, reg, &v);
+	(void)map;
+
+	int reg_idx = -1;
+	for (int i = 0; i < DBG_MAX_REG_NUM; i++) {
+		if (!strcmp(reg, regstrs[i])) {
+			reg_idx = i;
+			break;
+		}
+	}
 
-	// TODO Not quite sure what do do here yet
-	syslog(0, "gdbserver", "get_reg: %s", reg);
+	if (reg_idx == -1) {
+		syslog(0, "gdbserver", "get_reg: Unrecognised register %s.", reg);
+		return 0;
+	}
 
-	return 0;
-	//return nil;
+	uint64_t value = arch_get_reg(&ks, reg_idx);
+	return value;
 }
 
 /*
@@ -1238,8 +1249,6 @@ wmem(uint64_t dest, int pid, void *addr, int size)
 	return nil;
 }
 
-static struct state ks;
-
 void
 main(int argc, char **argv)
 {

+ 6 - 0
sys/src/cmd/gdbserver/regsaarch64.c

@@ -98,6 +98,12 @@ gdb_cmd_reg_set(struct state *ks)
 	strcpy((char *)remcom_out_buffer, "OK");
 }
 
+uint64_t
+arch_get_reg(struct state *ks, int regnum)
+{
+	return 0;
+}
+
 uint64_t
 arch_get_pc(struct state *ks)
 {

+ 15 - 0
sys/src/cmd/gdbserver/regsamd64.c

@@ -103,6 +103,21 @@ gdb_cmd_reg_set(struct state *ks)
 	strcpy((char *)remcom_out_buffer, "OK");
 }
 
+uint64_t
+arch_get_reg(struct state *ks, int regnum) {
+	uint64_t value = 0;
+	if (regnum <= GDB_PC) {
+		value = ((uint64_t*)ks->gdbregs)[regnum];
+
+	} else if (regnum <= GDB_GS) {
+		uint32_t* reg32base = (uint32_t*)&(((uint64_t*)ks->gdbregs)[GDB_PS]);
+		int reg32idx = regnum - GDB_PS;
+		value = reg32base[reg32idx];
+	}
+
+	return value;
+}
+
 uint64_t
 arch_get_pc(struct state *ks)
 {

+ 6 - 0
sys/src/cmd/gdbserver/regsriscv.c

@@ -98,6 +98,12 @@ gdb_cmd_reg_set(struct state *ks)
 	strcpy((char *)remcom_out_buffer, "OK");
 }
 
+uint64_t
+arch_get_reg(struct state *ks, int regnum)
+{
+	return 0;
+}
+
 uint64_t
 arch_get_pc(struct state *ks)
 {

+ 4 - 4
sys/src/libmach/access.c

@@ -220,14 +220,14 @@ mget(Map *map, uint64_t addr, void *buf, int size)
 	for (i = j = 0; i < 2; i++) {	/* in case read crosses page */
 		k = spread(s, (void*)((uint8_t *)buf+j), size-j, off+j);
 		if (k < 0) {
-			werrstr("can't read address %llux: %r", addr);
+			werrstr("can't read address %p: %r", addr);
 			return -1;
 		}
 		j += k;
 		if (j == size)
 			return j;
 	}
-	werrstr("partial read at address %llux (size %d j %d)", addr, size, j);
+	werrstr("partial read at address %p (size %d j %d)", addr, size, j);
 	return -1;
 }
 
@@ -250,14 +250,14 @@ mput(Map *map, uint64_t addr, void *buf, int size)
 	for (i = j = 0; i < 2; i++) {	/* in case read crosses page */
 		k = write(s->fd, buf, size-j);
 		if (k < 0) {
-			werrstr("can't write address %llux: %r", addr);
+			werrstr("can't write address %p: %r", addr);
 			return -1;
 		}
 		j += k;
 		if (j == size)
 			return j;
 	}
-	werrstr("partial write at address %llux", addr);
+	werrstr("partial write at address %p", addr);
 	return -1;
 }