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