Date: Wed, 24 Mar 2004 23:56:47 -0800 (PST) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 49655 for review Message-ID: <200403250756.i2P7ulA6036529@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=49655 Change 49655 by marcel@marcel_nfs on 2004/03/24 23:56:09 Save a pointer to the trapframe (or intrframe on i386) on every kernel entry. We save the pointer in td_last_frame. This way, we always have the right context in the debugger without having to muck around with td_frame itself. I like only having td_frame better, but I only got panics so it needs more thought. This way I can at least make progress. Introduce the global variable kdb_frame, which normally caches kdb_thread->td_last_frame, but when the thread has never run, will cache kdb_thread->td_frame. We don't need this global variable if we only have td_frame of course. A thread list of my ia64 kernel with an i386 cross-debugger, now gives: (gdb) target remote /dev/uart1 Remote debugging using /dev/uart1 0xe000000004294161 in kdb_enter ( msg=0x9c1632009c16320 <Address 0x9c1632009c16320 out of bounds>) at machine/cpufunc.h:47 47 __asm __volatile("break.m %0" :: "i"(IA64_FIXED_BREAK)); (gdb) info thread 56 Thread 10 critical_exit () at machine/cpufunc.h:197 55 Thread 1 0x2000000000018740 in ?? () 54 Thread 11 0xe000000004294161 in kdb_enter ( msg=0x9c1632009c16320 <Address 0x9c1632009c16320 out of bounds>) at machine/cpufunc.h:47 53 Thread 12 DELAY (n=166888144) at machine/ia64_cpu.h:320 52 Thread 13 0x0000000000000000 in ?? () 51 Thread 14 critical_exit () at machine/cpufunc.h:197 50 Thread 2 critical_exit () at machine/cpufunc.h:197 49 Thread 3 critical_exit () at machine/cpufunc.h:197 48 Thread 4 g_io_schedule_down (tp=0x9c142b409c142b4) at ../../../geom/geom_io.c:311 47 Thread 15 SHA256_Transform (context=0x9bf412c09bf412c, data=0x9bf42f409bf42f4) at ../../../crypto/sha2/sha2.c:476 : The arguments are bogus, but that's because of something else. Thread 13 has never run, and thread 1 is in userland. Rewrite the way we get registers. All regisers are identified by the gdb register number. The gdb_cpu_getreg() function returns a pointer to the register's value, or NULL if the register is unavailable. The advantage of this is that we encode register values in the same way we encode memory contents and we can tell gdb about unavailable registers. This also means that there's less MD code. Still only i386 and ia64 for now. Affected files ... .. //depot/projects/gdb/sys/ddb/db_main.c#3 edit .. //depot/projects/gdb/sys/gdb/gdb_int.h#5 edit .. //depot/projects/gdb/sys/gdb/gdb_main.c#9 edit .. //depot/projects/gdb/sys/gdb/gdb_packet.c#6 edit .. //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#5 edit .. //depot/projects/gdb/sys/i386/i386/intr_machdep.c#2 edit .. //depot/projects/gdb/sys/i386/i386/trap.c#6 edit .. //depot/projects/gdb/sys/i386/include/gdb_machdep.h#4 edit .. //depot/projects/gdb/sys/i386/include/kdb.h#2 edit .. //depot/projects/gdb/sys/ia64/ia64/gdb_machdep.c#5 edit .. //depot/projects/gdb/sys/ia64/ia64/interrupt.c#3 edit .. //depot/projects/gdb/sys/ia64/ia64/trap.c#5 edit .. //depot/projects/gdb/sys/ia64/include/gdb_machdep.h#4 edit .. //depot/projects/gdb/sys/ia64/include/kdb.h#2 edit .. //depot/projects/gdb/sys/kern/subr_kdb.c#9 edit .. //depot/projects/gdb/sys/sys/kdb.h#7 edit .. //depot/projects/gdb/sys/sys/proc.h#5 edit Differences ... ==== //depot/projects/gdb/sys/ddb/db_main.c#3 (text+ko) ==== @@ -129,7 +129,7 @@ if (cnunavailable()) return (0); - ddb_regs = *kdb_thread->td_frame; + ddb_regs = *kdb_frame; bkpt = IS_BREAKPOINT_TRAP(type, code); watchpt = IS_WATCHPOINT_TRAP(type, code); @@ -153,7 +153,7 @@ db_restart_at_pc(watchpt); - *kdb_thread->td_frame = ddb_regs; + *kdb_frame = ddb_regs; return (1); } ==== //depot/projects/gdb/sys/gdb/gdb_int.h#5 (text+ko) ==== @@ -54,9 +54,8 @@ void gdb_tx_begin(char); int gdb_tx_end(void); -int gdb_tx_memory(const unsigned char *, size_t); +void gdb_tx_mem(const unsigned char *, size_t); void gdb_tx_reg(int); -int gdb_tx_regs(void); static __inline void gdb_tx_char(char c) ==== //depot/projects/gdb/sys/gdb/gdb_main.c#9 (text+ko) ==== @@ -92,7 +92,6 @@ static int gdb_trap(int type, int code) { - uintmax_t addr, size; struct proc *thr_iter; /* @@ -101,12 +100,10 @@ */ gdb_tx_begin('T'); gdb_tx_hex(gdb_cpu_signal(type, code), 2); + gdb_tx_varhex(GDB_REG_PC); + gdb_tx_char(':'); gdb_tx_reg(GDB_REG_PC); gdb_tx_char(';'); - gdb_tx_reg(GDB_REG_FP); - gdb_tx_char(';'); - gdb_tx_reg(GDB_REG_SP); - gdb_tx_char(';'); gdb_tx_str("thread:"); gdb_tx_varhex(kdb_thread->td_tid); gdb_tx_char(';'); @@ -121,14 +118,21 @@ gdb_tx_hex(gdb_cpu_signal(type, code), 2); gdb_tx_end(); break; - case 'c': /* continue */ + case 'c': { /* continue */ + uintmax_t addr; if (!gdb_rx_varhex(&addr)) gdb_cpu_setreg(GDB_REG_PC, addr); kdb_cpu_clear_singlestep(); return (1); - case 'g': - gdb_tx_regs(); + } + case 'g': { + size_t r; + gdb_tx_begin(0); + for (r = 0; r < GDB_NREGS; r++) + gdb_tx_reg(r); + gdb_tx_end(); break; + } case 'G': gdb_tx_err(0); break; @@ -144,13 +148,18 @@ case 'k': kdb_cpu_clear_singlestep(); return (1); - case 'm': + case 'm': { + uintmax_t addr, size; if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || - gdb_rx_varhex(&size)) + gdb_rx_varhex(&size)) { gdb_tx_err(EINVAL); - else - gdb_tx_memory((char *)(uintptr_t)addr, size); + break; + } + gdb_tx_begin(0); + gdb_tx_mem((char *)(uintptr_t)addr, size); + gdb_tx_end(); break; + } case 'M': gdb_tx_err(0); break; @@ -177,11 +186,13 @@ } else gdb_tx_empty(); break; - case 's': /* single step */ + case 's': { /* single step */ + uintmax_t addr; if (!gdb_rx_varhex(&addr)) gdb_cpu_setreg(GDB_REG_PC, addr); kdb_cpu_set_singlestep(); return (1); + } case -1: /* Empty command. Treat as unknown command. */ /* FALLTHROUGH */ ==== //depot/projects/gdb/sys/gdb/gdb_packet.c#6 (text+ko) ==== @@ -226,39 +226,30 @@ return (0); } -int -gdb_tx_memory(const unsigned char *addr, size_t size) +void +gdb_tx_mem(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 gdb_tx_reg(int regnum) { + unsigned char *regp; + size_t regsz; - gdb_tx_varhex(regnum); - gdb_tx_char(':'); - gdb_tx_hex(gdb_cpu_getreg(regnum), gdb_cpu_regsz(regnum) << 1); -} - -int -gdb_tx_regs(void) -{ - ssize_t regsz; - - regsz = gdb_cpu_getregs(gdb_rxbuf, sizeof(gdb_rxbuf)); - if (regsz < 0) - return (gdb_tx_err(ENOSPC)); - return (gdb_tx_memory(gdb_rxbuf, regsz)); + regp = gdb_cpu_getreg(regnum, ®sz); + if (regp == NULL) { + /* Register unavailable. */ + while (regsz--) { + gdb_tx_char('x'); + gdb_tx_char('x'); + } + } else + gdb_tx_mem(regp, regsz); } ==== //depot/projects/gdb/sys/i386/i386/gdb_machdep.c#5 (text+ko) ==== @@ -42,55 +42,38 @@ #include <gdb/gdb.h> -register_t -gdb_cpu_getreg(int regnum) +void * +gdb_cpu_getreg(int regnum, size_t *regsz) { - struct trapframe *tf = kdb_thread->td_frame; + struct trapframe *tf = kdb_frame; + *regsz = gdb_cpu_regsz(regnum); switch (regnum) { - case GDB_REG_FP: return (tf->tf_ebp); - case GDB_REG_PC: return (tf->tf_eip); - case GDB_REG_SP: return (tf->tf_esp); + case 0: return (&tf->tf_eax); + case 1: return (&tf->tf_ecx); + case 2: return (&tf->tf_edx); + case 3: return (&tf->tf_ebx); + case 4: return (&tf->tf_esp); + case 5: return (&tf->tf_ebp); + case 6: return (&tf->tf_esi); + case 7: return (&tf->tf_edi); + case 8: return (&tf->tf_eip); + case 9: return (&tf->tf_eflags); + case 10: return (&tf->tf_cs); + case 11: return (&tf->tf_ss); + case 12: return (&tf->tf_ds); + case 13: return (&tf->tf_es); } - return (0); + return (NULL); } -ssize_t -gdb_cpu_getregs(void *buf, size_t bufsz) -{ - struct trapframe *tf = kdb_thread->td_frame; - 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)); -} - void gdb_cpu_setreg(int regnum, register_t val) { - struct trapframe *tf = kdb_thread->td_frame; + struct trapframe *tf = kdb_frame; switch (regnum) { - 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; } } ==== //depot/projects/gdb/sys/i386/i386/intr_machdep.c#2 (text+ko) ==== @@ -147,6 +147,7 @@ int error, vector; td = curthread; + td->td_last_frame = INTR_TO_TRAPFRAME(iframe); td->td_intr_nesting_level++; /* ==== //depot/projects/gdb/sys/i386/i386/trap.c#6 (text+ko) ==== @@ -188,6 +188,7 @@ atomic_add_int(&cnt.v_trap, 1); type = frame.tf_trapno; + td->td_last_frame = &frame; #ifdef KDB if (kdb_active) { @@ -929,6 +930,7 @@ sticks = td->td_sticks; td->td_frame = &frame; + td->td_last_frame = &frame; if (td->td_ucred != p->p_ucred) cred_update_thread(td); if (p->p_flag & P_SA) ==== //depot/projects/gdb/sys/i386/include/gdb_machdep.h#4 (text+ko) ==== @@ -30,19 +30,16 @@ #define _MACHINE_GDB_MACHDEP_H_ #define GDB_BUFSZ 400 - -#define GDB_REG_FP 5 +#define GDB_NREGS 14 #define GDB_REG_PC 8 -#define GDB_REG_SP 4 -static __inline int +static __inline size_t gdb_cpu_regsz(int regnum) { - return (4); /* XXX not really. */ + return (sizeof(int)); } -register_t gdb_cpu_getreg(int); -ssize_t gdb_cpu_getregs(void *, size_t); +void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, register_t); int gdb_cpu_signal(int, int); ==== //depot/projects/gdb/sys/i386/include/kdb.h#2 (text+ko) ==== @@ -35,13 +35,13 @@ static __inline void kdb_cpu_clear_singlestep(void) { - kdb_thread->td_frame->tf_eflags &= ~PSL_T; + kdb_frame->tf_eflags &= ~PSL_T; } static __inline void kdb_cpu_set_singlestep(void) { - kdb_thread->td_frame->tf_eflags |= PSL_T; + kdb_frame->tf_eflags |= PSL_T; } static __inline void ==== //depot/projects/gdb/sys/ia64/ia64/gdb_machdep.c#5 (text+ko) ==== @@ -40,43 +40,85 @@ #include <gdb/gdb.h> -register_t -gdb_cpu_getreg(int regnum) +void * +gdb_cpu_getreg(int regnum, size_t *regsz) { - struct trapframe *tf = kdb_thread->td_frame; + struct trapframe *tf = kdb_frame; + static uint64_t bsp; + *regsz = gdb_cpu_regsz(regnum); switch (regnum) { - case GDB_REG_FP: - return (tf->tf_special.bspstore + tf->tf_special.ndirty); - case GDB_REG_PC: - return (tf->tf_special.iip + ((tf->tf_special.psr >> 41) & 3)); - case GDB_REG_SP: - return (tf->tf_special.sp); + /* Registers 0-127: general registers. */ + case 1: return (&tf->tf_special.gp); + case 2: return (&tf->tf_scratch.gr2); + case 3: return (&tf->tf_scratch.gr3); + case 8: return (&tf->tf_scratch.gr8); + case 9: return (&tf->tf_scratch.gr9); + case 10: return (&tf->tf_scratch.gr10); + case 11: return (&tf->tf_scratch.gr11); + case 12: return (&tf->tf_special.sp); + case 13: return (&tf->tf_special.tp); + case 14: return (&tf->tf_scratch.gr14); + case 15: return (&tf->tf_scratch.gr15); + case 16: return (&tf->tf_scratch.gr16); + case 17: return (&tf->tf_scratch.gr17); + case 18: return (&tf->tf_scratch.gr18); + case 19: return (&tf->tf_scratch.gr19); + case 20: return (&tf->tf_scratch.gr20); + case 21: return (&tf->tf_scratch.gr21); + case 22: return (&tf->tf_scratch.gr22); + case 23: return (&tf->tf_scratch.gr23); + case 24: return (&tf->tf_scratch.gr24); + case 25: return (&tf->tf_scratch.gr25); + case 26: return (&tf->tf_scratch.gr26); + case 27: return (&tf->tf_scratch.gr27); + case 28: return (&tf->tf_scratch.gr28); + case 29: return (&tf->tf_scratch.gr29); + case 30: return (&tf->tf_scratch.gr30); + case 31: return (&tf->tf_scratch.gr31); + /* Registers 128-255: floating-point registers. */ + case 134: return (&tf->tf_scratch_fp.fr6); + case 135: return (&tf->tf_scratch_fp.fr7); + case 136: return (&tf->tf_scratch_fp.fr8); + case 137: return (&tf->tf_scratch_fp.fr9); + case 138: return (&tf->tf_scratch_fp.fr10); + case 139: return (&tf->tf_scratch_fp.fr11); + case 140: return (&tf->tf_scratch_fp.fr12); + case 141: return (&tf->tf_scratch_fp.fr13); + case 142: return (&tf->tf_scratch_fp.fr14); + case 143: return (&tf->tf_scratch_fp.fr15); + /* Registers 320-327: branch registers. */ + case 320: return (&tf->tf_special.rp); + case 326: return (&tf->tf_scratch.br6); + case 327: return (&tf->tf_scratch.br7); + /* Registers 328-333: misc. other registers. */ + case 330: return (&tf->tf_special.pr); + case 331: return (&tf->tf_special.iip); + case 332: return (&tf->tf_special.psr); + case 333: return (&tf->tf_special.cfm); + /* Registers 334-461: application registers. */ + case 350: return (&tf->tf_special.rsc); + case 352: return (&tf->tf_special.bspstore); + case 353: return (&tf->tf_special.rnat); + case 359: return (&tf->tf_scratch.csd); + case 360: return (&tf->tf_scratch.ssd); + case 366: return (&tf->tf_scratch.ccv); + case 370: return (&tf->tf_special.unat); + case 374: return (&tf->tf_special.fpsr); + case 398: return (&tf->tf_special.pfs); + /* Synthesized registers. */ + case 351: + bsp = tf->tf_special.bspstore + tf->tf_special.ndirty; + return (&bsp); } - return (0); + return (NULL); } -ssize_t -gdb_cpu_getregs(void *buf, size_t bufsz) -{ - struct trapframe *tf = kdb_thread->td_frame; - struct reg *r = buf; - - if (sizeof(*r) > bufsz) - return (-1); - r->r_special = tf->tf_special; - r->r_scratch = tf->tf_scratch; - bzero(&r->r_preserved, sizeof(r->r_preserved)); - return (sizeof(*r)); -} - void gdb_cpu_setreg(int regnum, register_t val) { switch (regnum) { - case GDB_REG_FP: break; case GDB_REG_PC: break; - case GDB_REG_SP: break; } } ==== //depot/projects/gdb/sys/ia64/ia64/interrupt.c#3 (text+ko) ==== @@ -133,6 +133,7 @@ int count; td = curthread; + td->td_last_frame = tf; atomic_add_int(&td->td_intr_nesting_level, 1); /* ==== //depot/projects/gdb/sys/ia64/ia64/trap.c#5 (text+ko) ==== @@ -365,6 +365,7 @@ atomic_add_int(&cnt.v_trap, 1); td = curthread; + td->td_last_frame = tf; p = td->td_proc; ucode = 0; @@ -901,9 +902,10 @@ atomic_add_int(&cnt.v_syscall, 1); td = curthread; + td->td_frame = tf; + td->td_last_frame = tf; p = td->td_proc; - td->td_frame = tf; sticks = td->td_sticks; if (td->td_ucred != p->p_ucred) cred_update_thread(td); ==== //depot/projects/gdb/sys/ia64/include/gdb_machdep.h#4 (text+ko) ==== @@ -29,16 +29,15 @@ #ifndef _MACHINE_GDB_MACHDEP_H_ #define _MACHINE_GDB_MACHDEP_H_ -#define GDB_BUFSZ 4096 +#define GDB_NREGS 462 +#define GDB_REG_PC 331 -#define GDB_REG_FP 328 -#define GDB_REG_PC 331 -#define GDB_REG_SP 12 +#define GDB_BUFSZ (GDB_NREGS*16+128*16) -static __inline int +static __inline size_t gdb_cpu_regsz(int regnum) { - return (8); /* XXX not really. */ + return ((regnum >= 128 && regnum < 256) ? 16 : 8); } static __inline int @@ -47,8 +46,7 @@ return (vector); } -register_t gdb_cpu_getreg(int); -ssize_t gdb_cpu_getregs(void *, size_t); +void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, register_t); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ ==== //depot/projects/gdb/sys/ia64/include/kdb.h#2 (text+ko) ==== @@ -47,8 +47,8 @@ __asm __volatile("flushrs;;"); if (vector == IA64_VEC_BREAK && - kdb_thread->td_frame->tf_special.ifa == IA64_FIXED_BREAK) - kdb_thread->td_frame->tf_special.psr += IA64_PSR_RI_1; + kdb_frame->tf_special.ifa == IA64_FIXED_BREAK) + kdb_frame->tf_special.psr += IA64_PSR_RI_1; } #endif /* _MACHINE_KDB_H_ */ ==== //depot/projects/gdb/sys/kern/subr_kdb.c#9 (text+ko) ==== @@ -40,6 +40,7 @@ int kdb_active = 0; struct kdb_dbbe *kdb_dbbe = NULL; struct thread *kdb_thread = NULL; +struct trapframe *kdb_frame = NULL; KDB_BACKEND(null, NULL, NULL, NULL); SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe); @@ -165,8 +166,12 @@ p = LIST_FIRST(&allproc); while (p != NULL && p->p_pid != tid) p = LIST_NEXT(p, p_list); - if (p != NULL) + if (p != NULL) { kdb_thread = FIRST_THREAD_IN_PROC(p); + kdb_frame = kdb_thread->td_last_frame; + if (kdb_frame == NULL) + kdb_frame = kdb_thread->td_frame; + } return ((p != NULL) ? 1 : 0); } @@ -186,7 +191,7 @@ kdb_active++; kdb_thread = curthread; - kdb_thread->td_frame = tf; + kdb_frame = tf; #ifdef SMP stop_cpus(PCPU_GET(other_cpus)); ==== //depot/projects/gdb/sys/sys/kdb.h#7 (text+ko) ==== @@ -56,6 +56,7 @@ 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. */ +extern struct trapframe *kdb_frame; /* Current frame. */ int kdb_alt_break(int, int *); void kdb_backtrace(void); ==== //depot/projects/gdb/sys/sys/proc.h#5 (text+ko) ==== @@ -275,6 +275,7 @@ int td_inhibitors; /* (j) Why can not run. */ int td_pflags; /* (k) Private thread (TDP_*) flags. */ int td_tid; /* XXX currently unused. */ + struct trapframe *td_last_frame; struct kse *td_last_kse; /* (j) Previous value of td_kse. */ struct kse *td_kse; /* (j) Current KSE if running. */ int td_dupfd; /* (k) Ret value from fdopen. XXX */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403250756.i2P7ulA6036529>