tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

diff: ddb: gather common code for x86



Hello, tech-kern@!

Here's the diff for ddb(4):
        - reuse the common code for stack traces
                (and rely on sizeof(long) in most cases)
        - use db_read_* api to be usable from crash(8).

I need this for crash(8) amd64 support diff which I'll send
in the next letter.

I'm using this on amd64, survived a kernel build on i386, tests
are welcome!

Index: x86/conf/files.x86
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.66
diff -u -p -r1.66 files.x86
--- x86/conf/files.x86  4 Apr 2011 21:33:49 -0000       1.66
+++ x86/conf/files.x86  6 Apr 2011 11:24:14 -0000
@@ -67,6 +67,7 @@ file  arch/x86/x86/bus_space.c
 file   arch/x86/x86/consinit.c
 file   arch/x86/x86/core_machdep.c     coredump
 file   arch/x86/x86/cpu_topology.c
+file   arch/x86/x86/db_trace.c         ddb
 file   arch/x86/x86/errata.c
 file   arch/x86/x86/genfb_machdep.c
 file   arch/x86/x86/identcpu.c
Index: x86/include/db_machdep.h
===================================================================
RCS file: x86/include/db_machdep.h
diff -N x86/include/db_machdep.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ x86/include/db_machdep.h    6 Apr 2011 11:24:14 -0000
@@ -0,0 +1,24 @@
+#ifndef _X86_DB_MACHDEP_H_
+#define _X86_DB_MACHDEP_H_
+
+#define        INKERNEL(va)    (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+
+#define NONE           0
+#define TRAP           1
+#define SYSCALL                2
+#define INTERRUPT      3
+#define INTERRUPT_TSS  4
+#define TRAP_TSS       5
+
+#define MAXNARG                16
+
+struct db_variable;
+
+int db_x86_regop(const struct db_variable *, db_expr_t *, int);
+int db_numargs(long *);
+int db_nextframe(long **, long **, long **, db_addr_t *, long *, int,
+                void (*) (const char *, ...));
+db_sym_t db_frame_info(long *, db_addr_t, const char **, db_expr_t *,
+                       int *, int *);
+
+#endif /* _X86_DB_MACHDEP_H_ */
Index: x86/x86/db_trace.c
===================================================================
RCS file: x86/x86/db_trace.c
diff -N x86/x86/db_trace.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ x86/x86/db_trace.c  6 Apr 2011 11:24:14 -0000
@@ -0,0 +1,323 @@
+/*     $NetBSD: db_trace.c,v 1.18 2010/07/01 02:38:27 rmind Exp $      */
+
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  
Software.Distribution%CS.CMU.EDU@localhost
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.18 2010/07/01 02:38:27 rmind Exp 
$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <machine/intrdefs.h>
+
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_access.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_user.h>
+#include <ddb/db_proc.h>
+#include <ddb/db_command.h>
+#include <x86/db_machdep.h>
+
+int
+db_x86_regop(const struct db_variable *vp, db_expr_t *val, int opcode)
+{
+        db_expr_t *regaddr =
+            (db_expr_t *)(((uint8_t *)DDB_REGS) + ((size_t)vp->valuep));
+        
+        switch (opcode) {
+        case DB_VAR_GET:
+                *val = *regaddr;
+                break;
+        case DB_VAR_SET:
+                *regaddr = *val;
+                break;
+        default:
+               db_printf("db_x86_regop: unknown op %d", opcode);
+               db_error(NULL);
+        }
+        return 0;
+}
+
+/*
+ * Stack trace.
+ */
+
+#if 0
+db_addr_t      db_trap_symbol_value = 0;
+db_addr_t      db_syscall_symbol_value = 0;
+db_addr_t      db_kdintr_symbol_value = 0;
+bool           db_trace_symbols_found = false;
+
+void db_find_trace_symbols(void);
+
+void
+db_find_trace_symbols(void)
+{
+       db_expr_t       value;
+
+       if (db_value_of_name("_trap", &value))
+               db_trap_symbol_value = (db_addr_t) value;
+       if (db_value_of_name("_kdintr", &value))
+               db_kdintr_symbol_value = (db_addr_t) value;
+       if (db_value_of_name("_syscall", &value))
+               db_syscall_symbol_value = (db_addr_t) value;
+       db_trace_symbols_found = true;
+}
+#endif
+
+void
+db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
+                    const char *modif, void (*pr)(const char *, ...))
+{
+       long            *frame, *lastframe;
+       long            *retaddr, *arg0;
+       long            *argp;
+       db_addr_t        callpc;
+       int              is_trap;
+       bool             kernel_only = true;
+       bool             trace_thread = false;
+       bool             lwpaddr = false;
+
+#if 0
+       if (!db_trace_symbols_found)
+               db_find_trace_symbols();
+#endif
+
+       {
+               const char *cp = modif;
+               char c;
+
+               while ((c = *cp++) != 0) {
+                       if (c == 'a') {
+                               lwpaddr = true;
+                               trace_thread = true;
+                       }
+                       if (c == 't')
+                               trace_thread = true;
+                       if (c == 'u')
+                               kernel_only = false;
+               }
+       }
+
+#ifdef __x86_64__
+#define set_frame_callpc() do {                                \
+               frame = (long *)ddb_regs.tf_rbp;        \
+               callpc = (db_addr_t)ddb_regs.tf_rip;    \
+       } while (0)
+#else
+#define set_frame_callpc() do {                                \
+               frame = (long *)ddb_regs.tf_ebp;        \
+               callpc = (db_addr_t)ddb_regs.tf_eip;    \
+       } while (0)
+#endif
+
+       if (have_addr && trace_thread) {
+               struct pcb *pcb;
+               proc_t p;
+               lwp_t l;
+
+               if (lwpaddr) {
+                       db_read_bytes(addr, sizeof(l),
+                           (char *)&l);
+                       db_read_bytes((db_addr_t)l.l_proc,
+                           sizeof(p), (char *)&p);
+                       (*pr)("trace: pid %d ", p.p_pid);
+               } else {
+                       proc_t  *pp;
+
+                       (*pr)("trace: pid %d ", (int)addr);
+                       if ((pp = db_proc_find((pid_t)addr)) == 0) {
+                               (*pr)("not found\n");
+                               return;
+                       }
+                       db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
+                       db_read_bytes((db_addr_t)p.p_lwps.lh_first,
+                           sizeof(l), (char *)&l);
+               }
+               (*pr)("lid %d ", l.l_lid);
+               pcb = lwp_getpcb(&l);
+#ifdef _KERNEL
+               if (l.l_proc == curproc && (lwp_t *)lwpaddr == curlwp)
+                       set_frame_callpc();
+               else
+#endif
+               {
+#ifdef __x86_64__
+                       db_read_bytes((db_addr_t)&pcb->pcb_rbp,
+                           sizeof(frame), (char *)&frame);
+#else
+                       db_read_bytes((db_addr_t)&pcb->pcb_ebp,
+                           sizeof(frame), (char *)&frame);
+#endif
+                       db_read_bytes((db_addr_t)(frame + 1),
+                           sizeof(callpc), (char *)&callpc);
+                       db_read_bytes((db_addr_t)frame,
+                           sizeof(frame), (char *)&frame);
+               }
+               (*pr)("at %p\n", frame);
+       } else if (have_addr) {
+               frame = (long *)addr;
+               db_read_bytes((db_addr_t)(frame + 1),
+                   sizeof(callpc), (char *)&callpc);
+               db_read_bytes((db_addr_t)frame,
+                   sizeof(frame), (char *)&frame);
+       } else
+               set_frame_callpc();
+       retaddr = frame + 1;
+       arg0 = frame + 2;
+
+       lastframe = 0;
+       while (count && frame != 0) {
+               int             narg;
+               const char *    name;
+               db_expr_t       offset;
+               db_sym_t        sym;
+               char    *argnames[MAXNARG], **argnp = NULL;
+               db_addr_t       lastcallpc;
+
+               name = "?";
+               is_trap = NONE;
+               offset = 0;
+               sym = db_frame_info(frame, callpc, &name, &offset, &is_trap,
+                                   &narg);
+
+               if (lastframe == 0 && sym == (db_sym_t)0 && callpc != 0) {
+                       /* Symbol not found, peek at code */
+                       u_long  instr = db_get_value(callpc, 4, false);
+
+                       offset = 1;
+                       if (
+#ifdef __x86_64__
+                           instr == 0xe5894855 ||
+                                       /* enter: pushq %rbp, movq %rsp, %rbp */
+                           (instr & 0x00ffffff) == 0x0048e589
+                                       /* enter+1: movq %rsp, %rbp */)
+#else
+                           (instr & 0x00ffffff) == 0x00e58955 ||
+                                       /* enter: pushl %ebp, movl %esp, %ebp */
+                           (instr & 0x0000ffff) == 0x0000e589
+                                       /* enter+1: movl %esp, %ebp */)
+#endif
+                       {
+                               offset = 0;
+                       }
+               }
+
+               if (is_trap == NONE) {
+                       if (db_sym_numargs(sym, &narg, argnames))
+                               argnp = argnames;
+                       else
+                               narg = db_numargs(frame);
+               }
+
+               (*pr)("%s(", name);
+
+               if (lastframe == 0 && offset == 0 && !have_addr) {
+                       /*
+                        * We have a breakpoint before the frame is set up
+                        * Use %[er]sp instead
+                        */
+#ifdef __x86_64__
+                       argp = &((struct x86_64_frame 
*)(ddb_regs.tf_rsp-sizeof(long)))->f_arg0;
+#else
+                       argp = (long *)&((struct i386_frame 
*)(ddb_regs.tf_esp-sizeof(long)))->f_arg0;
+#endif
+               } else {
+                       argp = frame + 2;
+               }
+
+               while (narg) {
+                       if (argnp)
+                               (*pr)("%s=", *argnp++);
+                       (*pr)("%lx", db_get_value((long)argp, sizeof(long), 
false));
+                       argp++;
+                       if (--narg != 0)
+                               (*pr)(",");
+               }
+               (*pr)(") at ");
+               db_printsym(callpc, DB_STGY_PROC, pr);
+               (*pr)("\n");
+
+               if (lastframe == 0 && offset == 0 && !have_addr) {
+                       /* Frame really belongs to next callpc */
+#ifdef __x86_64__
+                       struct x86_64_frame *fp = (void 
*)(ddb_regs.tf_rsp-sizeof(long));
+#else
+                       struct i386_frame *fp = (void 
*)(ddb_regs.tf_esp-sizeof(long));
+#endif
+                       lastframe = (long *)fp;
+                       callpc = (db_addr_t)
+                           db_get_value((db_addr_t)&fp->f_retaddr, 
sizeof(long), false);
+
+                       continue;
+               }
+
+               lastframe = frame;
+               lastcallpc = callpc;
+               if (!db_nextframe(&frame, &retaddr, &arg0,
+                  &callpc, frame + 2, is_trap, pr))
+                       break;
+
+               if (INKERNEL((long)frame)) {
+                       /* staying in kernel */
+#ifdef __i386__
+                       if (!db_intrstack_p(frame)
+                           && db_intrstack_p(lastframe)) {
+                               (*pr)("--- switch to interrupt stack ---\n");
+                       } else
+#endif
+                       if (frame < lastframe ||
+                           (frame == lastframe && callpc == lastcallpc)) {
+                               (*pr)("Bad frame pointer: %p\n", frame);
+                               break;
+                       }
+               } else if (INKERNEL((long)lastframe)) {
+                       /* switch from user to kernel */
+                       if (kernel_only)
+                               break;  /* kernel stack only */
+               } else {
+                       /* in user */
+                       if (frame <= lastframe) {
+                               (*pr)("Bad user frame pointer: %p\n", frame);
+                               break;
+                       }
+               }
+               --count;
+       }
+
+       if (count && is_trap != NONE) {
+               db_printsym(callpc, DB_STGY_XTRN, pr);
+               (*pr)(":\n");
+       }
+#undef set_frame_callpc
+}
Index: i386/conf/files.i386
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/files.i386,v
retrieving revision 1.356
diff -u -p -r1.356 files.i386
--- i386/conf/files.i386        24 Feb 2011 10:56:01 -0000      1.356
+++ i386/conf/files.i386        6 Apr 2011 11:24:14 -0000
@@ -67,8 +67,8 @@ file  arch/i386/i386/cpu_in_cksum.S   (inet
 file   arch/i386/i386/db_dbgreg.S      ddb | kstack_check_dr0
 file   arch/i386/i386/db_disasm.c      ddb
 file   arch/i386/i386/db_interface.c   ddb
+file   arch/i386/i386/db_machdep.c     ddb
 file   arch/i386/i386/db_memrw.c       ddb | kgdb
-file   arch/i386/i386/db_trace.c       ddb
 file   arch/i386/i386/dumpsys.c
 file   kern/subr_disk_mbr.c            disk
 file   kern/subr_spldebug.c            spldebug
Index: i386/i386/db_machdep.c
===================================================================
RCS file: i386/i386/db_machdep.c
diff -N i386/i386/db_machdep.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ i386/i386/db_machdep.c      6 Apr 2011 11:24:14 -0000
@@ -0,0 +1,299 @@
+/*     $NetBSD$        */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <machine/intrdefs.h>
+
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_access.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_user.h>
+#include <ddb/db_proc.h>
+#include <ddb/db_command.h>
+#include <ddb/db_cpu.h>
+#include <x86/db_machdep.h>
+
+#define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
+
+const struct db_variable db_regs[] = {
+       { "ds",         dbreg(ds),     db_x86_regop, NULL },
+       { "es",         dbreg(es),     db_x86_regop, NULL },
+       { "fs",         dbreg(fs),     db_x86_regop, NULL },
+       { "gs",         dbreg(gs),     db_x86_regop, NULL },
+       { "edi",        dbreg(edi),    db_x86_regop, NULL },
+       { "esi",        dbreg(esi),    db_x86_regop, NULL },
+       { "ebp",        dbreg(ebp),    db_x86_regop, NULL },
+       { "ebx",        dbreg(ebx),    db_x86_regop, NULL },
+       { "edx",        dbreg(edx),    db_x86_regop, NULL },
+       { "ecx",        dbreg(ecx),    db_x86_regop, NULL },
+       { "eax",        dbreg(eax),    db_x86_regop, NULL },
+       { "eip",        dbreg(eip),    db_x86_regop, NULL },
+       { "cs",         dbreg(cs),     db_x86_regop, NULL },
+       { "eflags",     dbreg(eflags), db_x86_regop, NULL },
+       { "esp",        dbreg(esp),    db_x86_regop, NULL },
+       { "ss",         dbreg(ss),     db_x86_regop, NULL },
+};
+const struct db_variable * const db_eregs =
+    db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+/*
+ * Figure out how many arguments were passed into the frame at "fp".
+ */
+int
+db_numargs(long *retaddrp)
+{
+       int     *argp;
+       int     inst;
+       int     args;
+       extern char     etext[];
+
+       argp = (int *)db_get_value((int)retaddrp, 4, false);
+       if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext) {
+               args = 10;
+       } else {
+               inst = db_get_value((int)argp, 4, false);
+               if ((inst & 0xff) == 0x59)      /* popl %ecx */
+                       args = 1;
+               else if ((inst & 0xffff) == 0xc483)     /* addl %n, %esp */
+                       args = ((inst >> 16) & 0xff) / 4;
+               else
+                       args = 10;
+       }
+       return (args);
+}
+
+db_sym_t
+db_frame_info(long *frame, db_addr_t callpc, const char **namep, db_expr_t 
*offp,
+             int *is_trap, int *nargp)
+{
+       db_expr_t       offset;
+       db_sym_t        sym;
+       int narg;
+       const char *name;
+
+       sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+       db_symbol_values(sym, &name, NULL);
+       if (sym == (db_sym_t)0)
+               return (db_sym_t)0;
+
+       *is_trap = NONE;
+       narg = MAXNARG;
+
+       if (INKERNEL((int)frame) && name) {
+               /*
+                * XXX traps should be based off of the Xtrap*
+                * locations rather than on trap, since some traps
+                * (e.g., npxdna) don't go through trap()
+                */
+#ifdef __ELF__
+               if (!strcmp(name, "trap_tss")) {
+                       *is_trap = TRAP_TSS;
+                       narg = 0;
+               } else if (!strcmp(name, "trap")) {
+                       *is_trap = TRAP;
+                       narg = 0;
+               } else if (!strcmp(name, "syscall_plain") ||
+                          !strcmp(name, "syscall_fancy")) {
+                       *is_trap = SYSCALL;
+                       narg = 0;
+               } else if (name[0] == 'X') {
+                       if (!strncmp(name, "Xintr", 5) ||
+                           !strncmp(name, "Xresume", 7) ||
+                           !strncmp(name, "Xstray", 6) ||
+                           !strncmp(name, "Xhold", 5) ||
+                           !strncmp(name, "Xrecurse", 8) ||
+                           !strcmp(name, "Xdoreti") ||
+                           !strncmp(name, "Xsoft", 5)) {
+                               *is_trap = INTERRUPT;
+                               narg = 0;
+                       } else if (!strncmp(name, "Xtss_", 5)) {
+                               *is_trap = INTERRUPT_TSS;
+                               narg = 0;
+                       }
+               }
+#else
+               if (!strcmp(name, "_trap_tss")) {
+                       *is_trap = TRAP_TSS;
+                       narg = 0;
+               } else if (!strcmp(name, "_trap")) {
+                       *is_trap = TRAP;
+                       narg = 0;
+               } else if (!strcmp(name, "_syscall")) {
+                       *is_trap = SYSCALL;
+                       narg = 0;
+               } else if (name[0] == '_' && name[1] == 'X') {
+                       if (!strncmp(name, "_Xintr", 6) ||
+                           !strncmp(name, "_Xresume", 8) ||
+                           !strncmp(name, "_Xstray", 7) ||
+                           !strncmp(name, "_Xhold", 6) ||
+                           !strncmp(name, "_Xrecurse", 9) ||
+                           !strcmp(name, "_Xdoreti") ||
+                           !strncmp(name, "_Xsoft", 6)) {
+                               *is_trap = INTERRUPT;
+                               narg = 0;
+                       } else if (!strncmp(name, "_Xtss_", 6)) {
+                               *is_trap = INTERRUPT_TSS;
+                               narg = 0;
+                       }
+               }
+#endif /* __ELF__ */
+       }
+
+       if (offp != NULL)
+               *offp = offset;
+       if (nargp != NULL)
+               *nargp = narg;
+       if (namep != NULL)
+               *namep = name;
+       return sym;
+}
+
+/* 
+ * Figure out the next frame up in the call stack.  
+ * For trap(), we print the address of the faulting instruction and 
+ *   proceed with the calling frame.  We return the ip that faulted.
+ *   If the trap was caused by jumping through a bogus pointer, then
+ *   the next line in the backtrace will list some random function as 
+ *   being called.  It should get the argument list correct, though.  
+ *   It might be possible to dig out from the next frame up the name
+ *   of the function that faulted, but that could get hairy.
+ */
+
+int
+db_nextframe(
+    long **nextframe,  /* IN/OUT */
+    long **retaddr,    /* IN/OUT */
+    long **arg0,               /* OUT */
+    db_addr_t *ip,     /* OUT */
+    long *argp,                /* IN */
+    int is_trap, void (*pr)(const char *, ...))
+{
+       static struct trapframe tf;
+       static struct i386tss tss;
+       struct i386_frame *fp;
+       struct intrframe *ifp;
+       int traptype, trapno, err, i;
+       uintptr_t ptr;
+
+       switch (is_trap) {
+           case NONE:
+               *ip = (db_addr_t)
+                       db_get_value((int)*retaddr, 4, false);
+               fp = (struct i386_frame *)
+                       db_get_value((int)*nextframe, 4, false);
+               if (fp == NULL)
+                       return 0;
+               *nextframe = (long *)&fp->f_frame;
+               *retaddr = (long *)&fp->f_retaddr;
+               *arg0 = (long *)&fp->f_arg0;
+               break;
+
+           case TRAP_TSS:
+           case INTERRUPT_TSS:
+               ptr = db_get_value((int)argp, 4, false);
+               db_read_bytes((db_addr_t)ptr, sizeof(tss), (char *)&tss);
+               *ip = tss.__tss_eip;
+               fp = (struct i386_frame *)tss.tss_ebp;
+               if (fp == NULL)
+                       return 0;
+               *nextframe = (long *)&fp->f_frame;
+               *retaddr = (long *)&fp->f_retaddr;
+               *arg0 = (long *)&fp->f_arg0;
+               if (is_trap == INTERRUPT_TSS)
+                       (*pr)("--- interrupt via task gate ---\n");
+               else
+                       (*pr)("--- trap via task gate ---\n");
+               break;
+
+           case TRAP:
+           case SYSCALL:
+           case INTERRUPT:
+           default:
+               /* The only argument to trap() or syscall() is the trapframe. */
+               ptr = db_get_value((int)argp, 4, false);
+               db_read_bytes((db_addr_t)ptr, sizeof(tf), (char *)&tf);
+               switch (is_trap) {
+               case TRAP:
+                       (*pr)("--- trap (number %d) ---\n", tf.tf_trapno);
+                       break;
+               case SYSCALL:
+                       (*pr)("--- syscall (number %d) ---\n", tf.tf_eax);
+                       break;
+               case INTERRUPT:
+                       (*pr)("--- interrupt ---\n");
+                       /*
+                        * Get intrframe address as saved when switching
+                        * to interrupt stack, and convert to trapframe
+                        * (add 4).  See frame.h.
+                        */
+                       ptr = db_get_value((int)(argp - 1) + 4, 4, false);
+                       db_read_bytes((db_addr_t)ptr, sizeof(tf), (char *)&tf);
+                       break;
+               }
+               *ip = (db_addr_t)tf.tf_eip;
+               fp = (struct i386_frame *)tf.tf_ebp;
+               if (fp == NULL)
+                       return 0;
+               *nextframe = (long *)&fp->f_frame;
+               *retaddr = (long *)&fp->f_retaddr;
+               *arg0 = (long *)&fp->f_arg0;
+               break;
+       }
+
+       /*
+        * A bit of a hack. Since %ebp may be used in the stub code,
+        * walk the stack looking for a valid interrupt frame. Such
+        * a frame can be recognized by always having
+        * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
+        */
+       if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
+           NULL) != (db_sym_t)0
+           && traptype == INTERRUPT) {
+               for (i = 0; i < 4; i++) {
+                       ifp = (struct intrframe *)(argp + i);
+                       err = db_get_value((int)&ifp->__if_err, 4, false);
+                       trapno = db_get_value((int)&ifp->__if_trapno, 4, false);
+                       if ((err == 0 || err == IREENT_MAGIC) && trapno == 
T_ASTFLT) {
+                               *nextframe = (long *)ifp - 1;
+                               break;
+                       }
+               }
+               if (i == 4) {
+                       (*pr)("DDB lost frame for ");
+                       db_printsym(*ip, DB_STGY_ANY, pr);
+                       (*pr)(", trying %p\n",argp);
+                       *nextframe = argp;
+               }
+       }
+       return 1;
+}
+
+bool
+db_intrstack_p(const void *vp)
+{
+       struct cpu_info *ci;
+       const char *cp;
+
+       for (ci = db_cpu_first(); ci != NULL; ci = db_cpu_next(ci)) {
+               db_read_bytes((db_addr_t)&ci->ci_intrstack, sizeof(cp),
+                   (char *)&cp);
+               if (cp == NULL) {
+                       continue;
+               }
+               if ((cp - INTRSTACKSIZE + 4) <= (const char *)vp &&
+                   (const char *)vp <= cp) {
+                       return true;
+               }
+       }
+       return false;
+}
Index: i386/i386/db_trace.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/db_trace.c,v
retrieving revision 1.66
diff -u -p -r1.66 db_trace.c
--- i386/i386/db_trace.c        25 Nov 2009 13:53:19 -0000      1.66
+++ i386/i386/db_trace.c        6 Apr 2011 11:24:14 -0000
@@ -50,348 +50,6 @@ __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v
 #include <ddb/db_cpu.h>
 #include <ddb/db_command.h>
 
-/*
- * Machine set.
- */
-
-#define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
-
-static int db_i386_regop(const struct db_variable *, db_expr_t *, int);
-
-const struct db_variable db_regs[] = {
-       { "ds",         dbreg(ds),     db_i386_regop, NULL },
-       { "es",         dbreg(es),     db_i386_regop, NULL },
-       { "fs",         dbreg(fs),     db_i386_regop, NULL },
-       { "gs",         dbreg(gs),     db_i386_regop, NULL },
-       { "edi",        dbreg(edi),    db_i386_regop, NULL },
-       { "esi",        dbreg(esi),    db_i386_regop, NULL },
-       { "ebp",        dbreg(ebp),    db_i386_regop, NULL },
-       { "ebx",        dbreg(ebx),    db_i386_regop, NULL },
-       { "edx",        dbreg(edx),    db_i386_regop, NULL },
-       { "ecx",        dbreg(ecx),    db_i386_regop, NULL },
-       { "eax",        dbreg(eax),    db_i386_regop, NULL },
-       { "eip",        dbreg(eip),    db_i386_regop, NULL },
-       { "cs",         dbreg(cs),     db_i386_regop, NULL },
-       { "eflags",     dbreg(eflags), db_i386_regop, NULL },
-       { "esp",        dbreg(esp),    db_i386_regop, NULL },
-       { "ss",         dbreg(ss),     db_i386_regop, NULL },
-};
-const struct db_variable * const db_eregs =
-    db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
-
-static int
-db_i386_regop (const struct db_variable *vp, db_expr_t *val, int opcode)
-{
-       db_expr_t *regaddr =
-           (db_expr_t *)(((uint8_t *)DDB_REGS) + ((size_t)vp->valuep));
-       
-       switch (opcode) {
-       case DB_VAR_GET:
-               *val = *regaddr;
-               break;
-       case DB_VAR_SET:
-               *regaddr = *val;
-               break;
-       default:
-               db_printf("db_i386_regop: unknown op %d", opcode);
-               db_error(NULL);
-       }
-       return 0;
-}
-
-/*
- * Stack trace.
- */
-#define        INKERNEL(va)    (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
-
-struct i386_frame {
-       struct i386_frame       *f_frame;
-       int                     f_retaddr;
-       int                     f_arg0;
-};
-
-#define        NONE            0
-#define        TRAP            1
-#define        SYSCALL         2
-#define        INTERRUPT       3
-#define INTERRUPT_TSS  4
-#define TRAP_TSS       5
-
-#define MAXNARG        16
-
-db_addr_t      db_trap_symbol_value = 0;
-db_addr_t      db_syscall_symbol_value = 0;
-db_addr_t      db_kdintr_symbol_value = 0;
-bool           db_trace_symbols_found = false;
-
-#if 0
-static void
-db_find_trace_symbols(void)
-{
-       db_expr_t       value;
-
-       if (db_value_of_name("_trap", &value))
-               db_trap_symbol_value = (db_addr_t) value;
-       if (db_value_of_name("_kdintr", &value))
-               db_kdintr_symbol_value = (db_addr_t) value;
-       if (db_value_of_name("_syscall", &value))
-               db_syscall_symbol_value = (db_addr_t) value;
-       db_trace_symbols_found = true;
-}
-#endif
-
-/*
- * Figure out how many arguments were passed into the frame at "fp".
- */
-static int
-db_numargs(int *retaddrp)
-{
-       int     *argp;
-       int     inst;
-       int     args;
-       extern char     etext[];
-
-       argp = (int *)db_get_value((int)retaddrp, 4, false);
-       if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext) {
-               args = 10;
-       } else {
-               inst = db_get_value((int)argp, 4, false);
-               if ((inst & 0xff) == 0x59)      /* popl %ecx */
-                       args = 1;
-               else if ((inst & 0xffff) == 0xc483)     /* addl %n, %esp */
-                       args = ((inst >> 16) & 0xff) / 4;
-               else
-                       args = 10;
-       }
-       return (args);
-}
-
-static db_sym_t
-db_frame_info(int *frame, db_addr_t callpc, const char **namep, db_expr_t 
*offp,
-             int *is_trap, int *nargp)
-{
-       db_expr_t       offset;
-       db_sym_t        sym;
-       int narg;
-       const char *name;
-
-       sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
-       db_symbol_values(sym, &name, NULL);
-       if (sym == (db_sym_t)0)
-               return (db_sym_t)0;
-
-       *is_trap = NONE;
-       narg = MAXNARG;
-
-       if (INKERNEL((int)frame) && name) {
-               /*
-                * XXX traps should be based off of the Xtrap*
-                * locations rather than on trap, since some traps
-                * (e.g., npxdna) don't go through trap()
-                */
-#ifdef __ELF__
-               if (!strcmp(name, "trap_tss")) {
-                       *is_trap = TRAP_TSS;
-                       narg = 0;
-               } else if (!strcmp(name, "trap")) {
-                       *is_trap = TRAP;
-                       narg = 0;
-               } else if (!strcmp(name, "syscall_plain") ||
-                          !strcmp(name, "syscall_fancy")) {
-                       *is_trap = SYSCALL;
-                       narg = 0;
-               } else if (name[0] == 'X') {
-                       if (!strncmp(name, "Xintr", 5) ||
-                           !strncmp(name, "Xresume", 7) ||
-                           !strncmp(name, "Xstray", 6) ||
-                           !strncmp(name, "Xhold", 5) ||
-                           !strncmp(name, "Xrecurse", 8) ||
-                           !strcmp(name, "Xdoreti") ||
-                           !strncmp(name, "Xsoft", 5)) {
-                               *is_trap = INTERRUPT;
-                               narg = 0;
-                       } else if (!strncmp(name, "Xtss_", 5)) {
-                               *is_trap = INTERRUPT_TSS;
-                               narg = 0;
-                       }
-               }
-#else
-               if (!strcmp(name, "_trap_tss")) {
-                       *is_trap = TRAP_TSS;
-                       narg = 0;
-               } else if (!strcmp(name, "_trap")) {
-                       *is_trap = TRAP;
-                       narg = 0;
-               } else if (!strcmp(name, "_syscall")) {
-                       *is_trap = SYSCALL;
-                       narg = 0;
-               } else if (name[0] == '_' && name[1] == 'X') {
-                       if (!strncmp(name, "_Xintr", 6) ||
-                           !strncmp(name, "_Xresume", 8) ||
-                           !strncmp(name, "_Xstray", 7) ||
-                           !strncmp(name, "_Xhold", 6) ||
-                           !strncmp(name, "_Xrecurse", 9) ||
-                           !strcmp(name, "_Xdoreti") ||
-                           !strncmp(name, "_Xsoft", 6)) {
-                               *is_trap = INTERRUPT;
-                               narg = 0;
-                       } else if (!strncmp(name, "_Xtss_", 6)) {
-                               *is_trap = INTERRUPT_TSS;
-                               narg = 0;
-                       }
-               }
-#endif /* __ELF__ */
-       }
-
-       if (offp != NULL)
-               *offp = offset;
-       if (nargp != NULL)
-               *nargp = narg;
-       if (namep != NULL)
-               *namep = name;
-       return sym;
-}
-
-/* 
- * Figure out the next frame up in the call stack.  
- * For trap(), we print the address of the faulting instruction and 
- *   proceed with the calling frame.  We return the ip that faulted.
- *   If the trap was caused by jumping through a bogus pointer, then
- *   the next line in the backtrace will list some random function as 
- *   being called.  It should get the argument list correct, though.  
- *   It might be possible to dig out from the next frame up the name
- *   of the function that faulted, but that could get hairy.
- */
-
-static int
-db_nextframe(
-    int **nextframe,   /* IN/OUT */
-    int **retaddr,     /* IN/OUT */
-    int **arg0,                /* OUT */
-    db_addr_t *ip,     /* OUT */
-    int *argp,         /* IN */
-    int is_trap, void (*pr)(const char *, ...))
-{
-       static struct trapframe tf;
-       static struct i386tss tss;
-       struct i386_frame *fp;
-       struct intrframe *ifp;
-       int traptype, trapno, err, i;
-       uintptr_t ptr;
-
-       switch (is_trap) {
-           case NONE:
-               *ip = (db_addr_t)
-                       db_get_value((int)*retaddr, 4, false);
-               fp = (struct i386_frame *)
-                       db_get_value((int)*nextframe, 4, false);
-               if (fp == NULL)
-                       return 0;
-               *nextframe = (int *)&fp->f_frame;
-               *retaddr = (int *)&fp->f_retaddr;
-               *arg0 = (int *)&fp->f_arg0;
-               break;
-
-           case TRAP_TSS:
-           case INTERRUPT_TSS:
-               ptr = db_get_value((int)argp, 4, false);
-               db_read_bytes((db_addr_t)ptr, sizeof(tss), (char *)&tss);
-               *ip = tss.__tss_eip;
-               fp = (struct i386_frame *)tss.tss_ebp;
-               if (fp == NULL)
-                       return 0;
-               *nextframe = (int *)&fp->f_frame;
-               *retaddr = (int *)&fp->f_retaddr;
-               *arg0 = (int *)&fp->f_arg0;
-               if (is_trap == INTERRUPT_TSS)
-                       (*pr)("--- interrupt via task gate ---\n");
-               else
-                       (*pr)("--- trap via task gate ---\n");
-               break;
-
-           case TRAP:
-           case SYSCALL:
-           case INTERRUPT:
-           default:
-               /* The only argument to trap() or syscall() is the trapframe. */
-               ptr = db_get_value((int)argp, 4, false);
-               db_read_bytes((db_addr_t)ptr, sizeof(tf), (char *)&tf);
-               switch (is_trap) {
-               case TRAP:
-                       (*pr)("--- trap (number %d) ---\n", tf.tf_trapno);
-                       break;
-               case SYSCALL:
-                       (*pr)("--- syscall (number %d) ---\n", tf.tf_eax);
-                       break;
-               case INTERRUPT:
-                       (*pr)("--- interrupt ---\n");
-                       /*
-                        * Get intrframe address as saved when switching
-                        * to interrupt stack, and convert to trapframe
-                        * (add 4).  See frame.h.
-                        */
-                       ptr = db_get_value((int)(argp - 1) + 4, 4, false);
-                       db_read_bytes((db_addr_t)ptr, sizeof(tf), (char *)&tf);
-                       break;
-               }
-               *ip = (db_addr_t)tf.tf_eip;
-               fp = (struct i386_frame *)tf.tf_ebp;
-               if (fp == NULL)
-                       return 0;
-               *nextframe = (int *)&fp->f_frame;
-               *retaddr = (int *)&fp->f_retaddr;
-               *arg0 = (int *)&fp->f_arg0;
-               break;
-       }
-
-       /*
-        * A bit of a hack. Since %ebp may be used in the stub code,
-        * walk the stack looking for a valid interrupt frame. Such
-        * a frame can be recognized by always having
-        * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
-        */
-       if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
-           NULL) != (db_sym_t)0
-           && traptype == INTERRUPT) {
-               for (i = 0; i < 4; i++) {
-                       ifp = (struct intrframe *)(argp + i);
-                       err = db_get_value((int)&ifp->__if_err, 4, false);
-                       trapno = db_get_value((int)&ifp->__if_trapno, 4, false);
-                       if ((err == 0 || err == IREENT_MAGIC) && trapno == 
T_ASTFLT) {
-                               *nextframe = (int *)ifp - 1;
-                               break;
-                       }
-               }
-               if (i == 4) {
-                       (*pr)("DDB lost frame for ");
-                       db_printsym(*ip, DB_STGY_ANY, pr);
-                       (*pr)(", trying %p\n",argp);
-                       *nextframe = argp;
-               }
-       }
-       return 1;
-}
-
-static bool
-db_intrstack_p(const void *vp)
-{
-       struct cpu_info *ci;
-       const char *cp;
-
-       for (ci = db_cpu_first(); ci != NULL; ci = db_cpu_next(ci)) {
-               db_read_bytes((db_addr_t)&ci->ci_intrstack, sizeof(cp),
-                   (char *)&cp);
-               if (cp == NULL) {
-                       continue;
-               }
-               if ((cp - INTRSTACKSIZE + 4) <= (const char *)vp &&
-                   (const char *)vp <= cp) {
-                       return true;
-               }
-       }
-       return false;
-}
-
 void
 db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
                     const char *modif, void (*pr)(const char *, ...))
@@ -427,8 +85,11 @@ db_stack_trace_print(db_expr_t addr, boo
        }
 
        if (!have_addr) {
+#ifdef __x86_64__
                frame = (int *)ddb_regs.tf_ebp;
                callpc = (db_addr_t)ddb_regs.tf_eip;
+#else
+#endif
        } else {
                if (trace_thread) {
                        struct pcb *pcb;
Index: i386/include/db_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/db_machdep.h,v
retrieving revision 1.27
diff -u -p -r1.27 db_machdep.h
--- i386/include/db_machdep.h   7 Mar 2009 22:02:16 -0000       1.27
+++ i386/include/db_machdep.h   6 Apr 2011 11:24:14 -0000
@@ -44,6 +44,13 @@ typedef      vaddr_t         db_addr_t;      /* address -
 typedef        long            db_expr_t;      /* expression - signed */
 
 typedef struct trapframe db_regs_t;
+
+struct i386_frame {
+       struct i386_frame       *f_frame;
+       int                     f_retaddr;
+       int                     f_arg0;
+};
+
 #ifndef MULTIPROCESSOR
 extern db_regs_t ddb_regs;     /* register state */
 #define        DDB_REGS        (&ddb_regs)
@@ -142,4 +149,7 @@ extern void db_machine_init(void);
 
 extern void cpu_debug_dump(void);
 
+/* i386/db_machdep.c */
+bool db_intrstack_p(const void *);
+
 #endif /* _I386_DB_MACHDEP_H_ */
Index: amd64/amd64/db_machdep.c
===================================================================
RCS file: amd64/amd64/db_machdep.c
diff -N amd64/amd64/db_machdep.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ amd64/amd64/db_machdep.c    6 Apr 2011 11:24:14 -0000
@@ -0,0 +1,214 @@
+/*     $NetBSD$        */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: db_machdep.c$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <machine/intrdefs.h>
+
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_access.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_user.h>
+#include <ddb/db_proc.h>
+#include <ddb/db_command.h>
+#include <x86/db_machdep.h>
+
+#define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
+
+/*
+ * Machine register set.
+ */
+const struct db_variable db_regs[] = {
+       { "ds",         dbreg(ds),     db_x86_regop, NULL },
+       { "es",         dbreg(es),     db_x86_regop, NULL },
+       { "fs",         dbreg(fs),     db_x86_regop, NULL },
+       { "gs",         dbreg(gs),     db_x86_regop, NULL },
+       { "rdi",        dbreg(rdi),    db_x86_regop, NULL },
+       { "rsi",        dbreg(rsi),    db_x86_regop, NULL },
+       { "rbp",        dbreg(rbp),    db_x86_regop, NULL },
+       { "rbx",        dbreg(rbx),    db_x86_regop, NULL },
+       { "rdx",        dbreg(rdx),    db_x86_regop, NULL },
+       { "rcx",        dbreg(rcx),    db_x86_regop, NULL },
+       { "rax",        dbreg(rax),    db_x86_regop, NULL },
+       { "r8",         dbreg(r8),     db_x86_regop, NULL },
+       { "r9",         dbreg(r9),     db_x86_regop, NULL },
+       { "r10",        dbreg(r10),    db_x86_regop, NULL },
+       { "r11",        dbreg(r11),    db_x86_regop, NULL },
+       { "r12",        dbreg(r12),    db_x86_regop, NULL },
+       { "r13",        dbreg(r13),    db_x86_regop, NULL },
+       { "r14",        dbreg(r14),    db_x86_regop, NULL },
+       { "r15",        dbreg(r15),    db_x86_regop, NULL },
+       { "rip",        dbreg(rip),    db_x86_regop, NULL },
+       { "cs",         dbreg(cs),     db_x86_regop, NULL },
+       { "rflags",     dbreg(rflags), db_x86_regop, NULL },
+       { "rsp",        dbreg(rsp),    db_x86_regop, NULL },
+       { "ss",         dbreg(ss),     db_x86_regop, NULL },
+};
+const struct db_variable * const db_eregs =
+       db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+/*
+ * Figure out how many arguments were passed into the frame at "fp".
+ * We can probably figure out how many arguments where passed above
+ * the first 6 (which are in registers), but since we can't
+ * reliably determine the values currently, just return 0.
+ */
+int
+db_numargs(long *retaddrp)
+{
+       return 0;
+}
+
+/* 
+ * Figure out the next frame up in the call stack.  
+ * For trap(), we print the address of the faulting instruction and 
+ *   proceed with the calling frame.  We return the ip that faulted.
+ *   If the trap was caused by jumping through a bogus pointer, then
+ *   the next line in the backtrace will list some random function as 
+ *   being called.  It should get the argument list correct, though.  
+ *   It might be possible to dig out from the next frame up the name
+ *   of the function that faulted, but that could get hairy.
+ */
+int
+db_nextframe(long **nextframe, long **retaddr, long **arg0, db_addr_t *ip,
+            long *argp, int is_trap, void (*pr)(const char *, ...))
+{
+       struct trapframe *tf;
+       struct x86_64_frame *fp;
+       struct intrframe *ifp;
+       int traptype, trapno, err, i;
+
+       switch (is_trap) {
+           case NONE:
+               *ip = (db_addr_t)
+                       db_get_value((long)*retaddr, 8, false);
+               fp = (struct x86_64_frame *)
+                       db_get_value((long)*nextframe, 8, false);
+               if (fp == NULL)
+                       return 0;
+               *nextframe = (long *)&fp->f_frame;
+               *retaddr = (long *)&fp->f_retaddr;
+               *arg0 = (long *)&fp->f_arg0;
+               break;
+
+           case TRAP:
+           case SYSCALL:
+           case INTERRUPT:
+           default:
+
+               /* The only argument to trap() or syscall() is the trapframe. */
+               tf = *(struct trapframe **)argp;
+               switch (is_trap) {
+               case TRAP:
+                       (*pr)("--- trap (number %d) ---\n", tf->tf_trapno);
+                       break;
+               case SYSCALL:
+                       (*pr)("--- syscall (number %ld) ---\n", tf->tf_rax);
+                       break;
+               case INTERRUPT:
+                       (*pr)("--- interrupt ---\n");
+                       tf = (struct trapframe *)argp;
+                       break;
+               }
+               *ip = (db_addr_t)tf->tf_rip;
+               fp = (struct x86_64_frame *)tf->tf_rbp;
+               if (fp == NULL)
+                       return 0;
+               *nextframe = (long *)&fp->f_frame;
+               *retaddr = (long *)&fp->f_retaddr;
+               *arg0 = (long *)&fp->f_arg0;
+               break;
+       }
+
+       /*
+        * A bit of a hack. Since %rbp may be used in the stub code,
+        * walk the stack looking for a valid interrupt frame. Such
+        * a frame can be recognized by always having
+        * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
+        */
+       if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
+           NULL) != (db_sym_t)0
+           && traptype == INTERRUPT) {
+               for (i = 0; i < 4; i++) {
+                       ifp = (struct intrframe *)(argp + i);
+                       err = db_get_value((long)&ifp->if_tf.tf_err,
+                           sizeof(long), false);
+                       trapno = db_get_value((long)&ifp->if_tf.tf_trapno,
+                           sizeof(long), false);
+                       if ((err == 0 || err == IREENT_MAGIC)
+                           && trapno == T_ASTFLT) {
+                               *nextframe = (long *)ifp - 1;
+                               break;
+                       }
+               }
+               if (i == 4) {
+                       (*pr)("DDB lost frame for ");
+                       db_printsym(*ip, DB_STGY_ANY, pr);
+                       (*pr)(", trying %p\n",argp);
+                       *nextframe = argp;
+               }
+       }
+       return 1;
+}
+
+db_sym_t
+db_frame_info(long *frame, db_addr_t callpc, const char **namep,
+             db_expr_t *offp, int *is_trap, int *nargp)
+{
+       db_expr_t       offset;
+       db_sym_t        sym;
+       int narg;
+       const char *name;
+
+       sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+       db_symbol_values(sym, &name, NULL);
+       if (sym == (db_sym_t)0)
+               return (db_sym_t)0;
+
+       *is_trap = NONE;
+       narg = 0;
+
+       if (INKERNEL((long)frame) && name) {
+               /*
+                * XXX traps should be based off of the Xtrap*
+                * locations rather than on trap, since some traps
+                * (e.g., npxdna) don't go through trap()
+                */
+               if (!strcmp(name, "trap")) {
+                       *is_trap = TRAP;
+                       narg = 0;
+               } else if (!strcmp(name, "syscall_plain") ||
+                          !strcmp(name, "syscall_fancy")) {
+                       *is_trap = SYSCALL;
+                       narg = 0;
+               } else if (name[0] == 'X') {
+                       if (!strncmp(name, "Xintr", 5) ||
+                           !strncmp(name, "Xresume", 7) ||
+                           !strncmp(name, "Xstray", 6) ||
+                           !strncmp(name, "Xhold", 5) ||
+                           !strncmp(name, "Xrecurse", 8) ||
+                           !strcmp(name, "Xdoreti") ||
+                           !strncmp(name, "Xsoft", 5)) {
+                               *is_trap = INTERRUPT;
+                               narg = 0;
+                       }
+               }
+       }
+
+       if (offp != NULL)
+               *offp = offset;
+       if (nargp != NULL)
+               *nargp = narg;
+       if (namep != NULL)
+               *namep = name;
+       return sym;
+}
Index: amd64/amd64/db_trace.c
===================================================================
RCS file: amd64/amd64/db_trace.c
diff -N amd64/amd64/db_trace.c
--- amd64/amd64/db_trace.c      1 Jul 2010 02:38:27 -0000       1.18
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,480 +0,0 @@
-/*     $NetBSD: db_trace.c,v 1.18 2010/07/01 02:38:27 rmind Exp $      */
-
-/* 
- * Mach Operating System
- * Copyright (c) 1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- * 
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- * 
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- * 
- * Carnegie Mellon requests users of this software to return to
- * 
- *  Software Distribution Coordinator  or  
Software.Distribution%CS.CMU.EDU@localhost
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- * 
- * any improvements or extensions that they make and grant Carnegie the
- * rights to redistribute these changes.
- */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.18 2010/07/01 02:38:27 rmind Exp 
$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-
-#include <machine/db_machdep.h>
-#include <machine/frame.h>
-#include <machine/trap.h>
-
-#include <ddb/db_sym.h>
-#include <ddb/db_access.h>
-#include <ddb/db_variables.h>
-#include <ddb/db_output.h>
-#include <ddb/db_interface.h>
-
-#define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
-
-static int db_x86_64_regop(const struct db_variable *, db_expr_t *, int);
-
-/*
- * Machine register set.
- */
-const struct db_variable db_regs[] = {
-       { "ds",         dbreg(ds),     db_x86_64_regop, NULL },
-       { "es",         dbreg(es),     db_x86_64_regop, NULL },
-       { "fs",         dbreg(fs),     db_x86_64_regop, NULL },
-       { "gs",         dbreg(gs),     db_x86_64_regop, NULL },
-       { "rdi",        dbreg(rdi),    db_x86_64_regop, NULL },
-       { "rsi",        dbreg(rsi),    db_x86_64_regop, NULL },
-       { "rbp",        dbreg(rbp),    db_x86_64_regop, NULL },
-       { "rbx",        dbreg(rbx),    db_x86_64_regop, NULL },
-       { "rdx",        dbreg(rdx),    db_x86_64_regop, NULL },
-       { "rcx",        dbreg(rcx),    db_x86_64_regop, NULL },
-       { "rax",        dbreg(rax),    db_x86_64_regop, NULL },
-       { "r8",         dbreg(r8),     db_x86_64_regop, NULL },
-       { "r9",         dbreg(r9),     db_x86_64_regop, NULL },
-       { "r10",        dbreg(r10),    db_x86_64_regop, NULL },
-       { "r11",        dbreg(r11),    db_x86_64_regop, NULL },
-       { "r12",        dbreg(r12),    db_x86_64_regop, NULL },
-       { "r13",        dbreg(r13),    db_x86_64_regop, NULL },
-       { "r14",        dbreg(r14),    db_x86_64_regop, NULL },
-       { "r15",        dbreg(r15),    db_x86_64_regop, NULL },
-       { "rip",        dbreg(rip),    db_x86_64_regop, NULL },
-       { "cs",         dbreg(cs),     db_x86_64_regop, NULL },
-       { "rflags",     dbreg(rflags), db_x86_64_regop, NULL },
-       { "rsp",        dbreg(rsp),    db_x86_64_regop, NULL },
-       { "ss",         dbreg(ss),     db_x86_64_regop, NULL },
-};
-const struct db_variable * const db_eregs =
-       db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
-
-static int
-db_x86_64_regop(const struct db_variable *vp, db_expr_t *val, int opcode)
-{
-        db_expr_t *regaddr =
-            (db_expr_t *)(((uint8_t *)DDB_REGS) + ((size_t)vp->valuep));
-        
-        switch (opcode) {
-        case DB_VAR_GET:
-                *val = *regaddr;
-                break;
-        case DB_VAR_SET:
-                *regaddr = *val;
-                break;
-        default:
-                panic("db_x86_64_regop: unknown op %d", opcode);
-        }
-        return 0;
-}
-
-/*
- * Stack trace.
- */
-#define        INKERNEL(va)    (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
-
-struct x86_64_frame {
-       struct x86_64_frame     *f_frame;
-       long                    f_retaddr;
-       long                    f_arg0;
-};
-
-#define        NONE            0
-#define        TRAP            1
-#define        SYSCALL         2
-#define        INTERRUPT       3
-
-db_addr_t      db_trap_symbol_value = 0;
-db_addr_t      db_syscall_symbol_value = 0;
-db_addr_t      db_kdintr_symbol_value = 0;
-bool           db_trace_symbols_found = false;
-
-void db_find_trace_symbols(void);
-int db_numargs(long *);
-int db_nextframe(long **, long **, long **, db_addr_t *, long *, int,
-    void (*) (const char *, ...));
-db_sym_t db_frame_info(long *, db_addr_t, const char **, db_expr_t *,
-                       int *, int *);
-
-
-void
-db_find_trace_symbols(void)
-{
-       db_expr_t       value;
-
-       if (db_value_of_name("_trap", &value))
-               db_trap_symbol_value = (db_addr_t) value;
-       if (db_value_of_name("_kdintr", &value))
-               db_kdintr_symbol_value = (db_addr_t) value;
-       if (db_value_of_name("_syscall", &value))
-               db_syscall_symbol_value = (db_addr_t) value;
-       db_trace_symbols_found = true;
-}
-
-/*
- * Figure out how many arguments were passed into the frame at "fp".
- * We can probably figure out how many arguments where passed above
- * the first 6 (which are in registers), but since we can't
- * reliably determine the values currently, just return 0.
- */
-int
-db_numargs(long *retaddrp)
-{
-       return 0;
-}
-
-/* 
- * Figure out the next frame up in the call stack.  
- * For trap(), we print the address of the faulting instruction and 
- *   proceed with the calling frame.  We return the ip that faulted.
- *   If the trap was caused by jumping through a bogus pointer, then
- *   the next line in the backtrace will list some random function as 
- *   being called.  It should get the argument list correct, though.  
- *   It might be possible to dig out from the next frame up the name
- *   of the function that faulted, but that could get hairy.
- */
-int
-db_nextframe(long **nextframe, long **retaddr, long **arg0, db_addr_t *ip,
-            long *argp, int is_trap, void (*pr)(const char *, ...))
-{
-       struct trapframe *tf;
-       struct x86_64_frame *fp;
-       struct intrframe *ifp;
-       int traptype, trapno, err, i;
-
-       switch (is_trap) {
-           case NONE:
-               *ip = (db_addr_t)
-                       db_get_value((long)*retaddr, 8, false);
-               fp = (struct x86_64_frame *)
-                       db_get_value((long)*nextframe, 8, false);
-               if (fp == NULL)
-                       return 0;
-               *nextframe = (long *)&fp->f_frame;
-               *retaddr = (long *)&fp->f_retaddr;
-               *arg0 = (long *)&fp->f_arg0;
-               break;
-
-           case TRAP:
-           case SYSCALL:
-           case INTERRUPT:
-           default:
-
-               /* The only argument to trap() or syscall() is the trapframe. */
-               tf = *(struct trapframe **)argp;
-               switch (is_trap) {
-               case TRAP:
-                       (*pr)("--- trap (number %d) ---\n", tf->tf_trapno);
-                       break;
-               case SYSCALL:
-                       (*pr)("--- syscall (number %ld) ---\n", tf->tf_rax);
-                       break;
-               case INTERRUPT:
-                       (*pr)("--- interrupt ---\n");
-                       tf = (struct trapframe *)argp;
-                       break;
-               }
-               *ip = (db_addr_t)tf->tf_rip;
-               fp = (struct x86_64_frame *)tf->tf_rbp;
-               if (fp == NULL)
-                       return 0;
-               *nextframe = (long *)&fp->f_frame;
-               *retaddr = (long *)&fp->f_retaddr;
-               *arg0 = (long *)&fp->f_arg0;
-               break;
-       }
-
-       /*
-        * A bit of a hack. Since %rbp may be used in the stub code,
-        * walk the stack looking for a valid interrupt frame. Such
-        * a frame can be recognized by always having
-        * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
-        */
-       if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
-           NULL) != (db_sym_t)0
-           && traptype == INTERRUPT) {
-               for (i = 0; i < 4; i++) {
-                       ifp = (struct intrframe *)(argp + i);
-                       err = db_get_value((long)&ifp->if_tf.tf_err, 8, false);
-                       trapno = db_get_value((long)&ifp->if_tf.tf_trapno,
-                           8, false);
-                       if ((err == 0 || err == IREENT_MAGIC) && trapno == 
T_ASTFLT) {
-                               *nextframe = (long *)ifp - 1;
-                               break;
-                       }
-               }
-               if (i == 4) {
-                       (*pr)("DDB lost frame for ");
-                       db_printsym(*ip, DB_STGY_ANY, pr);
-                       (*pr)(", trying %p\n",argp);
-                       *nextframe = argp;
-               }
-       }
-       return 1;
-}
-
-db_sym_t
-db_frame_info(long *frame, db_addr_t callpc, const char **namep, db_expr_t 
*offp,
-             int *is_trap, int *nargp)
-{
-       db_expr_t       offset;
-       db_sym_t        sym;
-       int narg;
-       const char *name;
-
-       sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
-       db_symbol_values(sym, &name, NULL);
-       if (sym == (db_sym_t)0)
-               return (db_sym_t)0;
-
-       *is_trap = NONE;
-       narg = 0;
-
-       if (INKERNEL((long)frame) && name) {
-               /*
-                * XXX traps should be based off of the Xtrap*
-                * locations rather than on trap, since some traps
-                * (e.g., npxdna) don't go through trap()
-                */
-               if (!strcmp(name, "trap")) {
-                       *is_trap = TRAP;
-                       narg = 0;
-               } else if (!strcmp(name, "syscall_plain") ||
-                          !strcmp(name, "syscall_fancy")) {
-                       *is_trap = SYSCALL;
-                       narg = 0;
-               } else if (name[0] == 'X') {
-                       if (!strncmp(name, "Xintr", 5) ||
-                           !strncmp(name, "Xresume", 7) ||
-                           !strncmp(name, "Xstray", 6) ||
-                           !strncmp(name, "Xhold", 5) ||
-                           !strncmp(name, "Xrecurse", 8) ||
-                           !strcmp(name, "Xdoreti") ||
-                           !strncmp(name, "Xsoft", 5)) {
-                               *is_trap = INTERRUPT;
-                               narg = 0;
-                       }
-               }
-       }
-
-       if (offp != NULL)
-               *offp = offset;
-       if (nargp != NULL)
-               *nargp = narg;
-       if (namep != NULL)
-               *namep = name;
-       return sym;
-}
-
-
-void
-db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
-                    const char *modif, void (*pr)(const char *, ...))
-{
-       long *frame, *lastframe;
-       long *retaddr, *arg0;
-       long            *argp;
-       db_addr_t       callpc;
-       int             is_trap;
-       bool            kernel_only = true;
-       bool            trace_thread = false;
-       bool            lwpaddr = false;
-
-#if 0
-       if (!db_trace_symbols_found)
-               db_find_trace_symbols();
-#endif
-
-       {
-               const char *cp = modif;
-               char c;
-
-               while ((c = *cp++) != 0) {
-                       if (c == 'a') {
-                               lwpaddr = true;
-                               trace_thread = true;
-                       }
-                       if (c == 't')
-                               trace_thread = true;
-                       if (c == 'u')
-                               kernel_only = false;
-               }
-       }
-
-       if (!have_addr) {
-               frame = (long *)ddb_regs.tf_rbp;
-               callpc = (db_addr_t)ddb_regs.tf_rip;
-       } else {
-               if (trace_thread) {
-                       struct proc *p;
-                       struct pcb *pcb;
-                       struct lwp *l;
-                       if (lwpaddr) {
-                               l = (struct lwp *)addr;
-                               p = l->l_proc;
-                               (*pr)("trace: pid %d ", p->p_pid);
-                       } else {
-                               (*pr)("trace: pid %d ", (int)addr);
-                               p = proc_find_raw(addr);
-                               if (p == NULL) {
-                                       (*pr)("not found\n");
-                                       return;
-                               }
-                               l = LIST_FIRST(&p->p_lwps);
-                               KASSERT(l != NULL);
-                       }
-                       (*pr)("lid %d ", l->l_lid);
-                       pcb = lwp_getpcb(l);
-                       if (p == curproc && l == curlwp) {
-                               frame = (long *)ddb_regs.tf_rbp;
-                               callpc = (db_addr_t)ddb_regs.tf_rip;
-                               (*pr)("at %p\n", frame);
-                       } else {
-                               frame = (long *)pcb->pcb_rbp;
-                               callpc = (db_addr_t)
-                                   db_get_value((long)(frame + 1), 8, false);
-                               (*pr)("at %p\n", frame);
-                               frame = (long *)*frame; /* XXXfvdl 
db_get_value? */
-                       }
-               } else {
-                       frame = (long *)addr;
-                       callpc = (db_addr_t)
-                           db_get_value((long)(frame + 1), 8, false);
-                       frame = (long *)*frame; /* XXXfvdl db_get_value? */
-               }
-       }
-       retaddr = frame + 1;
-       arg0 = frame + 2;
-
-       lastframe = 0;
-       while (count && frame != 0) {
-               int             narg;
-               const char *    name;
-               db_expr_t       offset;
-               db_sym_t        sym;
-               char    *argnames[16], **argnp = NULL;
-               db_addr_t       lastcallpc;
-
-               name = "?";
-               is_trap = NONE;
-               offset = 0;
-               sym = db_frame_info(frame, callpc, &name, &offset, &is_trap,
-                                   &narg);
-
-               if (lastframe == 0 && sym == (db_sym_t)0) {
-                       /* Symbol not found, peek at code */
-                       u_long  instr = db_get_value(callpc, 4, false);
-
-                       offset = 1;
-                       if (instr  == 0xe5894855 ||
-                                       /* enter: pushq %rbp, movq %rsp, %rbp */
-                           (instr & 0x00ffffff) == 0x0048e589
-                                       /* enter+1: movq %rsp, %rbp */) {
-                               offset = 0;
-                       }
-               }
-
-               if (is_trap == NONE) {
-                       if (db_sym_numargs(sym, &narg, argnames))
-                               argnp = argnames;
-                       else
-                               narg = db_numargs(frame);
-               }
-
-               (*pr)("%s(", name);
-
-               if (lastframe == 0 && offset == 0 && !have_addr) {
-                       /*
-                        * We have a breakpoint before the frame is set up
-                        * Use %rsp instead
-                        */
-                       argp = &((struct x86_64_frame 
*)(ddb_regs.tf_rsp-8))->f_arg0;
-               } else {
-                       argp = frame + 2;
-               }
-
-               while (narg) {
-                       if (argnp)
-                               (*pr)("%s=", *argnp++);
-                       (*pr)("%lx", db_get_value((long)argp, 8, false));
-                       argp++;
-                       if (--narg != 0)
-                               (*pr)(",");
-               }
-               (*pr)(") at ");
-               db_printsym(callpc, DB_STGY_PROC, pr);
-               (*pr)("\n");
-
-               if (lastframe == 0 && offset == 0 && !have_addr) {
-                       /* Frame really belongs to next callpc */
-                       struct x86_64_frame *fp = (void *)(ddb_regs.tf_rsp-8);
-
-                       lastframe = (long *)fp;
-                       callpc = (db_addr_t)
-                           db_get_value((db_addr_t)&fp->f_retaddr, 8, false);
-                       continue;
-               }
-
-               lastframe = frame;
-               lastcallpc = callpc;
-               if (!db_nextframe(&frame, &retaddr, &arg0,
-                  &callpc, frame + 2, is_trap, pr))
-                       break;
-
-               if (INKERNEL((long)frame)) {
-                       /* staying in kernel */
-                       if (frame < lastframe ||
-                           (frame == lastframe && callpc == lastcallpc)) {
-                               (*pr)("Bad frame pointer: %p\n", frame);
-                               break;
-                       }
-               } else if (INKERNEL((long)lastframe)) {
-                       /* switch from user to kernel */
-                       if (kernel_only)
-                               break;  /* kernel stack only */
-               } else {
-                       /* in user */
-                       if (frame <= lastframe) {
-                               (*pr)("Bad user frame pointer: %p\n",
-                                         frame);
-                               break;
-                       }
-               }
-               --count;
-       }
-
-       if (count && is_trap != NONE) {
-               db_printsym(callpc, DB_STGY_XTRN, pr);
-               (*pr)(":\n");
-       }
-}
Index: amd64/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.318
diff -u -p -r1.318 GENERIC
--- amd64/conf/GENERIC  1 Apr 2011 12:11:17 -0000       1.318
+++ amd64/conf/GENERIC  6 Apr 2011 11:24:14 -0000
@@ -104,6 +104,7 @@ makeoptions         COPTS="-O2 -fno-omit-frame-
 options        DDB             # in-kernel debugger
 #options       DDB_ONPANIC=1   # see also sysctl(8): `ddb.onpanic'
 options        DDB_HISTORY_SIZE=512    # enable history editing in DDB
+options                DDB_TEE_MSGBUF=1
 #options       KGDB            # remote debugger
 #options       KGDB_DEVNAME="\"com\"",KGDB_DEVADDR=0x3f8,KGDB_DEVRATE=9600
 #makeoptions   DEBUG="-g"      # compile full symbol table
@@ -656,7 +657,7 @@ age*        at pci? dev ? function ?        # Attansic
 alc*   at pci? dev ? function ?        # Attansic/Atheros L1C/L2C Ethernet
 ale*   at pci? dev ? function ?        # Attansic/Atheros L1E Ethernet
 an*    at pci? dev ? function ?        # Aironet PC4500/PC4800 (802.11)
-ath*   at pci? dev ? function ?        # Atheros 5210/5211/5212 802.11
+#ath*  at pci? dev ? function ?        # Atheros 5210/5211/5212 802.11
 atw*   at pci? dev ? function ?        # ADMtek ADM8211 (802.11)
 bce*   at pci? dev ? function ?        # Broadcom 440x 10/100 Ethernet
 bge*   at pci? dev ? function ?        # Broadcom 570x gigabit Ethernet
@@ -730,7 +731,7 @@ com*        at mhzc?
 sm*    at mhzc?
 
 # CardBus network cards
-ath*   at cardbus? function ?  # Atheros 5210/5211/5212 802.11
+#ath*  at cardbus? function ?  # Atheros 5210/5211/5212 802.11
 atw*   at cardbus? function ?  # ADMtek ADM8211 (802.11)
 ex*    at cardbus? function ?  # 3Com 3C575TX
 fxp*   at cardbus? function ?  # Intel i8255x
Index: amd64/conf/files.amd64
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/files.amd64,v
retrieving revision 1.71
diff -u -p -r1.71 files.amd64
--- amd64/conf/files.amd64      4 Apr 2011 21:35:31 -0000       1.71
+++ amd64/conf/files.amd64      6 Apr 2011 11:24:14 -0000
@@ -34,9 +34,9 @@ file  arch/amd64/amd64/busfunc.S
 file   arch/amd64/amd64/cpu_in_cksum.S         (inet | inet6) & cpu_in_cksum
 file   arch/amd64/amd64/cpufunc.S
 file   arch/amd64/amd64/db_disasm.c            ddb
-file   arch/amd64/amd64/db_interface.c ddb
+file   arch/amd64/amd64/db_interface.c         ddb
+file   arch/amd64/amd64/db_machdep.c           ddb
 file   arch/amd64/amd64/db_memrw.c             ddb | kgdb
-file   arch/amd64/amd64/db_trace.c             ddb
 file   arch/amd64/amd64/kobj_machdep.c         modular
 file   arch/amd64/amd64/kgdb_machdep.c         kgdb
 file   kern/subr_disk_mbr.c                    disk
Index: amd64/include/db_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/db_machdep.h,v
retrieving revision 1.9
diff -u -p -r1.9 db_machdep.h
--- amd64/include/db_machdep.h  14 Mar 2009 14:45:54 -0000      1.9
+++ amd64/include/db_machdep.h  6 Apr 2011 11:24:14 -0000
@@ -44,6 +44,13 @@ typedef      vaddr_t         db_addr_t;      /* address -
 typedef        long            db_expr_t;      /* expression - signed */
 
 typedef struct trapframe db_regs_t;
+
+struct x86_64_frame {
+       struct x86_64_frame     *f_frame;
+       long                    f_retaddr;
+       long                    f_arg0;
+};
+
 #ifndef MULTIPROCESSOR
 extern db_regs_t ddb_regs;     /* register state */
 #define        DDB_REGS        (&ddb_regs)
@@ -125,10 +132,12 @@ void              db_task_name(/* task_t */);
 
 int kdb_trap(int, int, db_regs_t *);
 
+#ifdef _KERNEL
 /*
  * We define some of our own commands
  */
 #define DB_MACHINE_COMMANDS
+#endif
 
 #define        DB_ELF_SYMBOLS
 #define        DB_ELFSIZE      64


Home | Main Index | Thread Index | Old Index