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