PERFORCE change 49001 for review

Marcel Moolenaar marcel at FreeBSD.org
Sun Mar 14 20:10:30 PST 2004


http://perforce.freebsd.org/chv.cgi?CH=49001

Change 49001 by marcel at marcel_nfs on 2004/03/14 20:09:45

	Implement the minimal (and non-optional) commands. As a
	bonus, implement '?' as well. Needs more work, but allows
	to break into the debugger and continue.

Affected files ...

.. //depot/projects/gdb/sys/gdb/gdb.h#5 edit
.. //depot/projects/gdb/sys/gdb/gdb_int.h#2 edit
.. //depot/projects/gdb/sys/gdb/gdb_main.c#4 edit
.. //depot/projects/gdb/sys/gdb/gdb_packet.c#2 edit
.. //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#2 edit

Differences ...

==== //depot/projects/gdb/sys/gdb/gdb.h#5 (text+ko) ====

@@ -61,8 +61,11 @@
 
 struct trapframe;
 
+uintmax_t gdb_cpu_getreg(int, struct trapframe *);
+ssize_t gdb_cpu_getregs(struct trapframe *, void *, size_t);
 int gdb_cpu_regsz(int);
-uintmax_t gdb_cpu_regval(int, struct trapframe *);
+void gdb_cpu_setreg(int, struct trapframe *, uintmax_t);
 int gdb_cpu_signal(int, int);
+void gdb_cpu_singlestep(int, struct trapframe *);
 
 #endif /* !_GDB_GDB_H_ */

==== //depot/projects/gdb/sys/gdb/gdb_int.h#2 (text+ko) ====

@@ -36,19 +36,30 @@
 extern struct gdb_dbgport *gdb_cur;
 
 extern char *gdb_rxp;
+extern size_t gdb_rxsz;
 extern char *gdb_txp;
 
 int gdb_rx_begin(void);
+int gdb_rx_varhex(uintmax_t *);
 
 static __inline int
 gdb_rx_char(void)
 {
-	return (*gdb_rxp++);
+	int c;
+
+	if (gdb_rxsz > 0) {
+		c = *gdb_rxp++;
+		gdb_rxsz--;
+	} else
+		c = -1;
+	return (c);
 }
 
 void gdb_tx_begin(char);
 int gdb_tx_end(void);
+int gdb_tx_memory(const unsigned char *, size_t);
 void gdb_tx_reg(int, struct trapframe *);
+int gdb_tx_regs(struct trapframe *);
 
 static __inline void
 gdb_tx_char(char c)
@@ -56,12 +67,27 @@
 	*gdb_txp++ = c;
 }
 
+static __inline int
+gdb_tx_empty(void)
+{
+	gdb_tx_begin('\0');
+	return (gdb_tx_end());
+}
+
 static __inline void
 gdb_tx_hex(uintmax_t n, int sz)
 {
 	gdb_txp += sprintf(gdb_txp, "%0*jx", sz, n);
 }
 
+static __inline int
+gdb_tx_err(int err)
+{
+	gdb_tx_begin('E');
+	gdb_tx_hex(err, 2);
+	return (gdb_tx_end());
+}
+
 static __inline void
 gdb_tx_str(const char *s)
 {

==== //depot/projects/gdb/sys/gdb/gdb_main.c#4 (text+ko) ====

@@ -32,6 +32,7 @@
 #include <sys/kdb.h>
 #include <sys/kernel.h>
 #include <sys/pcpu.h>
+#include <sys/proc.h>
 
 #include <machine/gdb_machdep.h>
 
@@ -85,7 +86,13 @@
 static int
 gdb_trap(int type, int code, struct trapframe *tf)
 {
-	const char *p;
+	struct proc *p;
+	uintmax_t addr, size;
+	int tid_cont, tid_gen;
+
+	p = curthread->td_proc;
+	tid_cont = -1;
+	tid_gen = (p != NULL) ? p->p_pid : 0;
 
 	/*
 	 * Send a T packet. We currently do not support watchpoints (the
@@ -100,14 +107,51 @@
 	gdb_tx_reg(GDB_REG_SP, tf);
 	gdb_tx_char(';');
 	gdb_tx_str("thread:");
-	gdb_tx_varhex((uintptr_t)curthread);
+	gdb_tx_varhex(tid_gen);
+	gdb_tx_char(';');
 	gdb_tx_end();			/* XXX check error condition. */
 
 	while (gdb_rx_begin() == 0) {
-		p = gdb_rxp;
+		printf("GDB: got '%s'\n", gdb_rxp);
 		switch (gdb_rx_char()) {
+		case '?':
+			gdb_tx_begin('S');
+			gdb_tx_hex(gdb_cpu_signal(type, code), 2);
+			gdb_tx_end();
+			break;
 		case 'c':	/* continue */
+			if (!gdb_rx_varhex(&addr))
+				gdb_cpu_setreg(GDB_REG_PC, tf, addr);
+			gdb_cpu_singlestep(0, tf);
+			return (1);
+		case 'g':
+			gdb_tx_regs(tf);
+			break;
+		case 'G':
+			gdb_tx_err(0);
+			break;
+		case 'm':
+			if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
+			    gdb_rx_varhex(&size))
+				gdb_tx_err(EINVAL);
+			else
+				gdb_tx_memory((char *)(uintptr_t)addr, size);
+			break;
+		case 'M':
+			gdb_tx_err(0);
+			break;
+		case 's':	/* single step */
+			if (!gdb_rx_varhex(&addr))
+				gdb_cpu_setreg(GDB_REG_PC, tf, addr);
+			gdb_cpu_singlestep(1, tf);
 			return (1);
+		case -1:
+			/* Empty command. Treat as unknown command. */
+			/* FALLTHROUGH */
+		default:
+			/* Unknown command. Send empty response. */
+			gdb_tx_empty();
+			break;
 		}
 	}
 	return (0);

==== //depot/projects/gdb/sys/gdb/gdb_packet.c#2 (text+ko) ====

@@ -29,18 +29,20 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/ctype.h>
 
 #include <gdb/gdb.h>
 #include <gdb/gdb_int.h>
 
 static char gdb_rxbuf[GDB_BUFSZ];
 char *gdb_rxp = NULL;
-static size_t gdb_rxsz = 0;
+size_t gdb_rxsz = 0;
 static char gdb_txbuf[GDB_BUFSZ];
 char *gdb_txp = NULL;			/* Used in inline functions. */
 
-#define	C2N(c)	((c < 'A') ? c - '0' : 10 + (c < 'a') ? c - 'A' : c - 'a')
-#define	N2C(n)	((n < 10) ? n + '0' : n + 'a' - 10)
+#define	C2N(c)	(((c) < 'A') ? (c) - '0' : \
+	    10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a'))
+#define	N2C(n)	(((n) < 10) ? (n) + '0' : (n) + 'a' - 10)
 
 /*
  * Functions to receive and extract from a packet.
@@ -49,7 +51,7 @@
 int
 gdb_rx_begin(void)
 {
-	unsigned char c, cksum;
+	int c, cksum;
 
 	gdb_rxp = NULL;
 	do {
@@ -71,7 +73,7 @@
 			cksum += c;
 		}
 		gdb_rxbuf[gdb_rxsz] = 0;
-		printf("GDB: got `%s'\n", gdb_rxbuf);
+		cksum &= 0xff;
 
 		/* Bail out on a buffer overflow. */
 		if (c != '#') {
@@ -80,16 +82,50 @@
 		}
 
 		c = gdb_cur->gdb_getc();
-		cksum -= C2N(c) << 4;
+		cksum -= (C2N(c) << 4) & 0xf0;
 		c = gdb_cur->gdb_getc();
-		cksum -= C2N(c);
+		cksum -= C2N(c) & 0x0f;
 		gdb_cur->gdb_putc((cksum == 0) ? '+' : '-');
+		if (cksum != 0)
+			printf("GDB: packet `%s' has invalid checksum\n",
+			    gdb_rxbuf);
 	} while (cksum != 0);
 
 	gdb_rxp = gdb_rxbuf;
 	return (0);
 }
 
+int
+gdb_rx_varhex(uintmax_t *vp)
+{
+	uintmax_t v;
+	int c, neg, valid;
+
+	c = gdb_rx_char();
+	if (c == -1)
+		return (-1);
+	neg = (c == '-') ? 1 : 0;
+	if (neg == 1)
+		c = gdb_rx_char();
+	v = 0;
+	valid = (isxdigit(c)) ? 1 : 0;
+	while (valid) {
+		v <<= 4;
+		v += C2N(c);
+		c = gdb_rx_char();
+		if (!isxdigit(c))
+			break;
+	}
+	if (!valid || c != -1) {
+		gdb_rxp -= 1 + neg - valid;
+		gdb_rxsz += 1 + neg - valid;
+	}
+	*vp = (neg) ? -v : v;
+	if (valid)
+		printf("GDB: %s: v=%jd (%jx)\n", __func__, *vp, *vp);
+	return ((valid) ? 0 : -1);
+}
+
 /*
  * Function to build and send a package.
  */
@@ -99,7 +135,25 @@
 {
 
 	gdb_txp = gdb_txbuf;
-	gdb_tx_char(tp);
+	if (tp != '\0')
+		gdb_tx_char(tp);
+}
+
+int
+gdb_tx_memory(const unsigned char *addr, size_t size)
+{
+
+	if (size > (sizeof(gdb_txbuf) << 1))
+		return (gdb_tx_err(ENOSPC));
+	gdb_tx_begin(0);
+	while (size-- > 0) {
+		*gdb_txp++ = N2C(*addr >> 4);
+		*gdb_txp++ = N2C(*addr & 0x0f);
+		addr++;
+	}
+	*gdb_txp = 0;
+	printf("`%s'\n", gdb_txbuf);
+	return (gdb_tx_end());
 }
 
 void
@@ -108,7 +162,18 @@
 
 	gdb_tx_varhex(regnum);
 	gdb_tx_char(':');
-	gdb_tx_hex(gdb_cpu_regval(regnum, tf), gdb_cpu_regsz(regnum) << 1);
+	gdb_tx_hex(gdb_cpu_getreg(regnum, tf), gdb_cpu_regsz(regnum) << 1);
+}
+
+int
+gdb_tx_regs(struct trapframe *tf)
+{
+	ssize_t regsz;
+
+	regsz = gdb_cpu_getregs(tf, gdb_rxbuf, sizeof(gdb_rxbuf));
+	if (regsz < 0)
+		return (gdb_tx_err(ENOSPC));
+	return (gdb_tx_memory(gdb_rxbuf, regsz));
 }
 
 int

==== //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#2 (text+ko) ====

@@ -34,25 +34,63 @@
 
 #include <machine/frame.h>
 #include <machine/gdb_machdep.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
 #include <machine/trap.h>
 
 #include <gdb/gdb.h>
 
+uintmax_t
+gdb_cpu_getreg(int regnum, struct trapframe *tf)
+{
+	switch (regnum) {
+	case GDB_REG_FP: return ((unsigned int)tf->tf_ebp);
+	case GDB_REG_PC: return ((unsigned int)tf->tf_eip);
+	case GDB_REG_SP: return ((unsigned int)tf->tf_esp);
+	}
+	return (0);
+}
+
+ssize_t
+gdb_cpu_getregs(struct trapframe *tf, void *buf, size_t bufsz)
+{
+	struct reg *r = buf;
+
+	if (sizeof(*r) > bufsz)
+		return (-1);
+	r->r_cs = tf->tf_cs;
+	r->r_ds = tf->tf_ds;
+	r->r_eax = tf->tf_eax;
+	r->r_ebp = tf->tf_ebp;
+	r->r_ebx = tf->tf_ebx;
+	r->r_ecx = tf->tf_ecx;
+	r->r_edi = tf->tf_edi;
+	r->r_edx = tf->tf_edx;
+	r->r_eflags = tf->tf_eflags;
+	r->r_eip = tf->tf_eip;
+	r->r_es = tf->tf_es;
+	r->r_esi = tf->tf_esi;
+	r->r_esp = tf->tf_esp;
+	r->r_fs = tf->tf_fs;
+	r->r_gs = 0;
+	r->r_ss = tf->tf_ss;
+	return (sizeof(*r));
+}
+
 int
 gdb_cpu_regsz(int regnum)
 {
 	return (4);		/* XXX not really. */
 }
 
-uintmax_t
-gdb_cpu_regval(int regnum, struct trapframe *tf)
+void
+gdb_cpu_setreg(int regnum, struct trapframe *tf, uintmax_t val)
 {
 	switch (regnum) {
-	case GDB_REG_FP: return ((unsigned int)tf->tf_ebp);
-	case GDB_REG_PC: return ((unsigned int)tf->tf_eip);
-	case GDB_REG_SP: return ((unsigned int)tf->tf_esp);
+	case GDB_REG_FP: tf->tf_ebp = val; break;
+	case GDB_REG_PC: tf->tf_eip = val; break;
+	case GDB_REG_SP: tf->tf_esp = val; break;
 	}
-	return (0);
 }
 
 int
@@ -78,3 +116,11 @@
 	}
 	return (SIGEMT);
 }
+
+void
+gdb_cpu_singlestep(int on, struct trapframe *tf)
+{
+
+	tf->tf_eflags &= ~PSL_T;
+	tf->tf_eflags |= (on) ? PSL_T : 0;
+}


More information about the p4-projects mailing list