PERFORCE change 49608 for review
Marcel Moolenaar
marcel at FreeBSD.org
Tue Mar 23 21:33:41 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=49608
Change 49608 by marcel at marcel_nfs on 2004/03/23 21:32:58
Make "info thread" work (basicly). Much has changed:
o Register context is now based on struct thread, not on struct
trapframe. A global variable, kdb_thread, is used to hold the
current thread. This means that we don't pass struct trapframe
around anymore.
o A start has been made to unify the MD functions for the gdb
backend and the ddb backend. Common MD functions have been
implemented as inline functions in <machine/kdb.h>
o Move the prototypes for the MD functions for the gdb backend
to <machine/gdb_machdep.h> where they can be implemented as
inlines.
Only i386 and ia64 have been changed for now.
Affected files ...
.. //depot/projects/gdb/sys/ddb/db_main.c#2 edit
.. //depot/projects/gdb/sys/gdb/gdb.h#7 edit
.. //depot/projects/gdb/sys/gdb/gdb_int.h#4 edit
.. //depot/projects/gdb/sys/gdb/gdb_main.c#8 edit
.. //depot/projects/gdb/sys/gdb/gdb_packet.c#4 edit
.. //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#4 edit
.. //depot/projects/gdb/sys/i386/include/gdb_machdep.h#3 edit
.. //depot/projects/gdb/sys/i386/include/kdb.h#1 add
.. //depot/projects/gdb/sys/ia64/ia64/gdb_machdep.c#4 edit
.. //depot/projects/gdb/sys/ia64/include/gdb_machdep.h#3 edit
.. //depot/projects/gdb/sys/ia64/include/kdb.h#1 add
.. //depot/projects/gdb/sys/kern/subr_kdb.c#8 edit
.. //depot/projects/gdb/sys/sys/kdb.h#6 edit
Differences ...
==== //depot/projects/gdb/sys/ddb/db_main.c#2 (text+ko) ====
@@ -37,6 +37,7 @@
#include <sys/proc.h>
#include <sys/reboot.h>
+#include <machine/kdb.h>
#include <machine/setjmp.h>
#include <ddb/ddb.h>
@@ -117,7 +118,7 @@
}
static int
-db_trap(int type, int code, struct trapframe *tf)
+db_trap(int type, int code)
{
boolean_t bkpt, watchpt;
@@ -128,10 +129,8 @@
if (cnunavailable())
return (0);
- db_cpu_trap(type, code, tf);
+ ddb_regs = *kdb_thread->td_frame;
- ddb_regs = *tf;
-
bkpt = IS_BREAKPOINT_TRAP(type, code);
watchpt = IS_WATCHPOINT_TRAP(type, code);
@@ -154,7 +153,7 @@
db_restart_at_pc(watchpt);
- *tf = ddb_regs;
+ *kdb_thread->td_frame = ddb_regs;
return (1);
}
==== //depot/projects/gdb/sys/gdb/gdb.h#7 (text+ko) ====
@@ -59,14 +59,4 @@
}; \
DATA_SET(gdb_dbgport_set, name##_gdb_dbgport)
-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);
-void gdb_cpu_setreg(int, struct trapframe *, uintmax_t);
-int gdb_cpu_signal(int, int);
-void gdb_cpu_singlestep(int, struct trapframe *);
-void gdb_cpu_trap(int, int, struct trapframe *);
-
#endif /* !_GDB_GDB_H_ */
==== //depot/projects/gdb/sys/gdb/gdb_int.h#4 (text+ko) ====
@@ -36,6 +36,7 @@
extern char *gdb_txp;
int gdb_rx_begin(void);
+int gdb_rx_equal(const char *);
int gdb_rx_varhex(uintmax_t *);
static __inline int
@@ -54,8 +55,8 @@
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 *);
+void gdb_tx_reg(int);
+int gdb_tx_regs(void);
static __inline void
gdb_tx_char(char c)
@@ -84,6 +85,14 @@
return (gdb_tx_end());
}
+static __inline int
+gdb_tx_ok(void)
+{
+ gdb_tx_begin('O');
+ gdb_tx_char('K');
+ return (gdb_tx_end());
+}
+
static __inline void
gdb_tx_str(const char *s)
{
==== //depot/projects/gdb/sys/gdb/gdb_main.c#8 (text+ko) ====
@@ -36,6 +36,7 @@
#include <sys/reboot.h>
#include <machine/gdb_machdep.h>
+#include <machine/kdb.h>
#include <gdb/gdb.h>
#include <gdb/gdb_int.h>
@@ -89,36 +90,29 @@
}
static int
-gdb_trap(int type, int code, struct trapframe *tf)
+gdb_trap(int type, int code)
{
- struct proc *p;
uintmax_t addr, size;
- int tid_cont, tid_gen;
+ struct proc *thr_iter;
- p = curthread->td_proc;
- tid_cont = -1;
- tid_gen = (p != NULL) ? p->p_pid : 0;
-
- /* Give MD code a change to set things up. */
- gdb_cpu_trap(type, code, tf);
-
/*
* Send a T packet. We currently do not support watchpoints (the
* awatch, rwatch or watch elements).
*/
gdb_tx_begin('T');
gdb_tx_hex(gdb_cpu_signal(type, code), 2);
- gdb_tx_reg(GDB_REG_PC, tf);
+ gdb_tx_reg(GDB_REG_PC);
gdb_tx_char(';');
- gdb_tx_reg(GDB_REG_FP, tf);
+ gdb_tx_reg(GDB_REG_FP);
gdb_tx_char(';');
- gdb_tx_reg(GDB_REG_SP, tf);
+ gdb_tx_reg(GDB_REG_SP);
gdb_tx_char(';');
gdb_tx_str("thread:");
- gdb_tx_varhex(tid_gen);
+ gdb_tx_varhex(kdb_thread->td_tid);
gdb_tx_char(';');
gdb_tx_end(); /* XXX check error condition. */
+ thr_iter = NULL;
while (gdb_rx_begin() == 0) {
printf("GDB: got '%s'\n", gdb_rxp);
switch (gdb_rx_char()) {
@@ -129,15 +123,27 @@
break;
case 'c': /* continue */
if (!gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, tf, addr);
- gdb_cpu_singlestep(0, tf);
+ gdb_cpu_setreg(GDB_REG_PC, addr);
+ kdb_cpu_clear_singlestep();
return (1);
case 'g':
- gdb_tx_regs(tf);
+ gdb_tx_regs();
break;
case 'G':
gdb_tx_err(0);
break;
+ case 'H': {
+ intmax_t tid;
+ gdb_rx_char();
+ gdb_rx_varhex(&tid);
+ if (tid > 0)
+ kdb_set_thread(tid);
+ gdb_tx_ok();
+ break;
+ }
+ case 'k':
+ kdb_cpu_clear_singlestep();
+ return (1);
case 'm':
if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
gdb_rx_varhex(&size))
@@ -148,10 +154,33 @@
case 'M':
gdb_tx_err(0);
break;
+ case 'q':
+ if (gdb_rx_equal("fThreadInfo")) {
+ thr_iter = LIST_FIRST(&allproc);
+ gdb_tx_begin('m');
+ gdb_tx_hex(thr_iter->p_pid, 8);
+ gdb_tx_end();
+ } else if (gdb_rx_equal("sThreadInfo")) {
+ if (thr_iter == NULL) {
+ gdb_tx_err(ENXIO);
+ break;
+ }
+ thr_iter = LIST_NEXT(thr_iter, p_list);
+ if (thr_iter != NULL) {
+ gdb_tx_begin('m');
+ gdb_tx_hex(thr_iter->p_pid, 8);
+ gdb_tx_end();
+ } else {
+ gdb_tx_begin('l');
+ gdb_tx_end();
+ }
+ } else
+ gdb_tx_empty();
+ break;
case 's': /* single step */
if (!gdb_rx_varhex(&addr))
- gdb_cpu_setreg(GDB_REG_PC, tf, addr);
- gdb_cpu_singlestep(1, tf);
+ gdb_cpu_setreg(GDB_REG_PC, addr);
+ kdb_cpu_set_singlestep();
return (1);
case -1:
/* Empty command. Treat as unknown command. */
==== //depot/projects/gdb/sys/gdb/gdb_packet.c#4 (text+ko) ====
@@ -98,6 +98,19 @@
}
int
+gdb_rx_equal(const char *str)
+{
+ int len;
+
+ len = strlen(str);
+ if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0)
+ return (0);
+ gdb_rxp += len;
+ gdb_rxsz -= len;
+ return (1);
+}
+
+int
gdb_rx_varhex(uintmax_t *vp)
{
uintmax_t v;
@@ -142,6 +155,34 @@
}
int
+gdb_tx_end(void)
+{
+ const char *p;
+ unsigned char c, cksum;
+
+ do {
+ gdb_cur->gdb_putc('$');
+
+ cksum = 0;
+ p = gdb_txbuf;
+ while (p < gdb_txp) {
+ gdb_cur->gdb_putc(*p);
+ cksum += *p++;
+ }
+
+ gdb_cur->gdb_putc('#');
+ c = cksum >> 4;
+ gdb_cur->gdb_putc(N2C(c));
+ c = cksum & 0x0f;
+ gdb_cur->gdb_putc(N2C(c));
+
+ c = gdb_cur->gdb_getc();
+ } while (c != '+');
+
+ return (0);
+}
+
+int
gdb_tx_memory(const unsigned char *addr, size_t size)
{
@@ -159,49 +200,21 @@
}
void
-gdb_tx_reg(int regnum, struct trapframe *tf)
+gdb_tx_reg(int regnum)
{
gdb_tx_varhex(regnum);
gdb_tx_char(':');
- gdb_tx_hex(gdb_cpu_getreg(regnum, tf), gdb_cpu_regsz(regnum) << 1);
+ gdb_tx_hex(gdb_cpu_getreg(regnum), gdb_cpu_regsz(regnum) << 1);
}
int
-gdb_tx_regs(struct trapframe *tf)
+gdb_tx_regs(void)
{
ssize_t regsz;
- regsz = gdb_cpu_getregs(tf, gdb_rxbuf, sizeof(gdb_rxbuf));
+ regsz = gdb_cpu_getregs(gdb_rxbuf, sizeof(gdb_rxbuf));
if (regsz < 0)
return (gdb_tx_err(ENOSPC));
return (gdb_tx_memory(gdb_rxbuf, regsz));
}
-
-int
-gdb_tx_end(void)
-{
- const char *p;
- unsigned char c, cksum;
-
- do {
- gdb_cur->gdb_putc('$');
-
- cksum = 0;
- p = gdb_txbuf;
- while (p < gdb_txp) {
- gdb_cur->gdb_putc(*p);
- cksum += *p++;
- }
-
- gdb_cur->gdb_putc('#');
- c = cksum >> 4;
- gdb_cur->gdb_putc(N2C(c));
- c = cksum & 0x0f;
- gdb_cur->gdb_putc(N2C(c));
-
- c = gdb_cur->gdb_getc();
- } while (c != '+');
-
- return (0);
-}
==== //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#4 (text+ko) ====
@@ -29,7 +29,9 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/signal.h>
#include <machine/frame.h>
@@ -40,20 +42,23 @@
#include <gdb/gdb.h>
-uintmax_t
-gdb_cpu_getreg(int regnum, struct trapframe *tf)
+register_t
+gdb_cpu_getreg(int regnum)
{
+ struct trapframe *tf = kdb_thread->td_frame;
+
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: return (tf->tf_ebp);
+ case GDB_REG_PC: return (tf->tf_eip);
+ case GDB_REG_SP: return (tf->tf_esp);
}
return (0);
}
ssize_t
-gdb_cpu_getregs(struct trapframe *tf, void *buf, size_t bufsz)
+gdb_cpu_getregs(void *buf, size_t bufsz)
{
+ struct trapframe *tf = kdb_thread->td_frame;
struct reg *r = buf;
if (sizeof(*r) > bufsz)
@@ -77,15 +82,11 @@
return (sizeof(*r));
}
-int
-gdb_cpu_regsz(int regnum)
+void
+gdb_cpu_setreg(int regnum, register_t val)
{
- return (4); /* XXX not really. */
-}
+ struct trapframe *tf = kdb_thread->td_frame;
-void
-gdb_cpu_setreg(int regnum, struct trapframe *tf, uintmax_t val)
-{
switch (regnum) {
case GDB_REG_FP: tf->tf_ebp = val; break;
case GDB_REG_PC: tf->tf_eip = val; break;
@@ -116,15 +117,3 @@
}
return (SIGEMT);
}
-
-void
-gdb_cpu_singlestep(int on, struct trapframe *tf)
-{
- tf->tf_eflags &= ~PSL_T;
- tf->tf_eflags |= (on) ? PSL_T : 0;
-}
-
-void
-gdb_cpu_trap(int type, int code, struct trapframe *tf)
-{
-}
==== //depot/projects/gdb/sys/i386/include/gdb_machdep.h#3 (text+ko) ====
@@ -35,4 +35,15 @@
#define GDB_REG_PC 8
#define GDB_REG_SP 4
+static __inline int
+gdb_cpu_regsz(int regnum)
+{
+ return (4); /* XXX not really. */
+}
+
+register_t gdb_cpu_getreg(int);
+ssize_t gdb_cpu_getregs(void *, size_t);
+void gdb_cpu_setreg(int, register_t);
+int gdb_cpu_signal(int, int);
+
#endif /* !_MACHINE_GDB_MACHDEP_H_ */
==== //depot/projects/gdb/sys/ia64/ia64/gdb_machdep.c#4 (text+ko) ====
@@ -29,7 +29,9 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kdb.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/signal.h>
#include <machine/frame.h>
@@ -38,9 +40,11 @@
#include <gdb/gdb.h>
-uintmax_t
-gdb_cpu_getreg(int regnum, struct trapframe *tf)
+register_t
+gdb_cpu_getreg(int regnum)
{
+ struct trapframe *tf = kdb_thread->td_frame;
+
switch (regnum) {
case GDB_REG_FP:
return (tf->tf_special.bspstore + tf->tf_special.ndirty);
@@ -53,8 +57,9 @@
}
ssize_t
-gdb_cpu_getregs(struct trapframe *tf, void *buf, size_t bufsz)
+gdb_cpu_getregs(void *buf, size_t bufsz)
{
+ struct trapframe *tf = kdb_thread->td_frame;
struct reg *r = buf;
if (sizeof(*r) > bufsz)
@@ -65,37 +70,13 @@
return (sizeof(*r));
}
-int
-gdb_cpu_regsz(int regnum)
+void
+gdb_cpu_setreg(int regnum, register_t val)
{
- return (8); /* XXX not really. */
-}
-void
-gdb_cpu_setreg(int regnum, struct trapframe *tf, uintmax_t val)
-{
switch (regnum) {
case GDB_REG_FP: break;
case GDB_REG_PC: break;
case GDB_REG_SP: break;
}
}
-
-int
-gdb_cpu_signal(int vector, int dummy)
-{
- return (vector);
-}
-
-void
-gdb_cpu_singlestep(int on, struct trapframe *tf)
-{
-}
-
-void
-gdb_cpu_trap(int vector, int dummy, struct trapframe *tf)
-{
- __asm __volatile("flushrs;;");
- if (vector == IA64_VEC_BREAK && tf->tf_special.ifa == IA64_FIXED_BREAK)
- tf->tf_special.psr += IA64_PSR_RI_1;
-}
==== //depot/projects/gdb/sys/ia64/include/gdb_machdep.h#3 (text+ko) ====
@@ -35,4 +35,20 @@
#define GDB_REG_PC 331
#define GDB_REG_SP 12
+static __inline int
+gdb_cpu_regsz(int regnum)
+{
+ return (8); /* XXX not really. */
+}
+
+static __inline int
+gdb_cpu_signal(int vector, int _)
+{
+ return (vector);
+}
+
+register_t gdb_cpu_getreg(int);
+ssize_t gdb_cpu_getregs(void *, size_t);
+void gdb_cpu_setreg(int, register_t);
+
#endif /* !_MACHINE_GDB_MACHDEP_H_ */
==== //depot/projects/gdb/sys/kern/subr_kdb.c#8 (text+ko) ====
@@ -32,10 +32,14 @@
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/pcpu.h>
+#include <sys/proc.h>
#include <sys/smp.h>
+#include <machine/kdb.h>
+
int kdb_active = 0;
struct kdb_dbbe *kdb_dbbe = NULL;
+struct thread *kdb_thread = NULL;
KDB_BACKEND(null, NULL, NULL, NULL);
SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
@@ -150,7 +154,24 @@
}
/*
- *
+ * Switch the current thread.
+ */
+
+int
+kdb_set_thread(pid_t tid)
+{
+ struct proc *p;
+
+ p = LIST_FIRST(&allproc);
+ while (p != NULL && p->p_pid != tid)
+ p = LIST_NEXT(p, p_list);
+ if (p != NULL)
+ kdb_thread = FIRST_THREAD_IN_PROC(p);
+ return ((p != NULL) ? 1 : 0);
+}
+
+/*
+ * Enter the debugger due to a trap.
*/
int
@@ -163,18 +184,25 @@
critical_enter();
+ kdb_active++;
+ kdb_thread = curthread;
+ kdb_thread->td_frame = tf;
+
#ifdef SMP
stop_cpus(PCPU_GET(other_cpus));
#endif
- kdb_active++;
- handled = kdb_dbbe->dbbe_trap(type, code, tf);
- kdb_active--;
+ /* Let MD code do its thing first... */
+ kdb_cpu_trap(type, code);
+
+ handled = kdb_dbbe->dbbe_trap(type, code);
#ifdef SMP
restart_cpus(stopped_cpus);
#endif
+ kdb_active--;
+
critical_exit();
return (handled);
==== //depot/projects/gdb/sys/sys/kdb.h#6 (text+ko) ====
@@ -29,11 +29,9 @@
#ifndef _SYS_KDB_H_
#define _SYS_KDB_H_
-struct trapframe;
-
typedef int dbbe_init_f(void);
typedef void dbbe_trace_f(void);
-typedef int dbbe_trap_f(int, int, struct trapframe *);
+typedef int dbbe_trap_f(int, int);
struct kdb_dbbe {
const char *dbbe_name;
@@ -52,13 +50,18 @@
}; \
DATA_SET(kdb_dbbe_set, name##_dbbe)
+struct thread;
+struct trapframe;
+
extern int kdb_active; /* Non-zero while in debugger. */
extern struct kdb_dbbe *kdb_dbbe; /* Default debugger backend or NULL. */
+extern struct thread *kdb_thread; /* Current thread. */
int kdb_alt_break(int, int *);
void kdb_backtrace(void);
void kdb_enter(const char *);
void kdb_init(void);
+int kdb_set_thread(pid_t);
int kdb_trap(int, int, struct trapframe *);
#endif /* !_SYS_KDB_H_ */
More information about the p4-projects
mailing list