Date: Sun, 14 Mar 2004 20:10:27 -0800 (PST) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 49001 for review Message-ID: <200403150410.i2F4ARZp028033@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=49001 Change 49001 by marcel@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; +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403150410.i2F4ARZp028033>