From owner-p4-projects@FreeBSD.ORG Tue Mar 23 21:33:41 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E7B5A16A4D0; Tue, 23 Mar 2004 21:33:40 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B67FA16A4CE for ; Tue, 23 Mar 2004 21:33:40 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id A9C9643D31 for ; Tue, 23 Mar 2004 21:33:40 -0800 (PST) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i2O5XeGe049509 for ; Tue, 23 Mar 2004 21:33:40 -0800 (PST) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i2O5XeMV049506 for perforce@freebsd.org; Tue, 23 Mar 2004 21:33:40 -0800 (PST) (envelope-from marcel@freebsd.org) Date: Tue, 23 Mar 2004 21:33:40 -0800 (PST) Message-Id: <200403240533.i2O5XeMV049506@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Subject: PERFORCE change 49608 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Mar 2004 05:33:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=49608 Change 49608 by marcel@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 o Move the prototypes for the MD functions for the gdb backend to 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 #include +#include #include #include @@ -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 #include +#include #include #include @@ -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 #include +#include #include +#include #include #include @@ -40,20 +42,23 @@ #include -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 #include +#include #include +#include #include #include @@ -38,9 +40,11 @@ #include -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 #include #include +#include #include +#include + 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_ */