tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: diff: ddb: gather common code for x86
On 23:32 Wed 06 Apr, matthew green wrote:
> this file is missing it's originator copyright header, i guess?
Yes, some files were :) I've inserted the headers.
> it would be nice to abstract out these tf_rip and tf_eip (and the ones
> that also look in rbp/ebp, etc.) something like.
>
> #ifdef __x86_64__
> #define tf_ip_reg tf_rip
> #define tf_bp_reg tf_rbp
> #else
> #define tf_ip_reg tf_eip
> #define tf_bp_reg tf_ebp
> #endif
I like your idea, updated the diff.
> > +#ifdef __ELF__
> > + if (!strcmp(name, "trap_tss")) {
> [ ... ]
> > + }
> > +#else
> > + if (!strcmp(name, "_trap_tss")) {
> [ ... ]
> > + }
> > +#endif /* __ELF__ */
>
> don't bother with this part for now but we should delete the !elf case.
Great! I think further cleanups can be done later to avoid cluttering
the diff with unrelated stuff.
> > Index: i386/i386/db_trace.c
>
> this file has #ifdef __x86_64__ in it. is that right?
I actually just forgot to cvs remove that file.
> > Index: amd64/conf/GENERIC
> i guess you didn't mean to include this part?
Yes, this file has slipped from my eyes during the diff review..
I've also inlined the amd64/db_disasm.c cleanup here.
The updated version:
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 14:47:53 -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 14:47:53 -0000
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#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 14:47:53 -0000
@@ -0,0 +1,316 @@
+/* $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
+
+#ifdef __x86_64__
+#define tf_ip tf_rip
+#define tf_bp tf_rbp
+#define tf_sp tf_rsp
+#define pcb_bp pcb_rbp
+#define stackframe x86_64_frame
+#else /* __i386__ */
+#define tf_ip tf_eip
+#define tf_bp tf_ebp
+#define tf_sp tf_esp
+#define pcb_bp pcb_ebp
+#define stackframe i386_frame
+#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;
+ }
+ }
+
+ 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) {
+ frame = (long *)ddb_regs.tf_bp;
+ callpc = (db_addr_t)ddb_regs.tf_ip;
+ } else
+#endif
+ {
+ db_read_bytes((db_addr_t)&pcb->pcb_bp,
+ sizeof(frame), (char *)&frame);
+ 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 {
+ frame = (long *)ddb_regs.tf_bp;
+ callpc = (db_addr_t)ddb_regs.tf_ip;
+ }
+ 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 %sp instead
+ */
+ argp = (long *)&((struct stackframe *)
+ (ddb_regs.tf_sp - sizeof(long)))->f_arg0;
+ } 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 */
+ struct stackframe *fp = (void *)(ddb_regs.tf_sp -
sizeof(long));
+
+ 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");
+ }
+}
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 14:47:53 -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 14:47:53 -0000
@@ -0,0 +1,325 @@
+/* $NetBSD$ */
+
+/*
+ * 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_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: i386/i386/db_trace.c
diff -N i386/i386/db_trace.c
--- i386/i386/db_trace.c 25 Nov 2009 13:53:19 -0000 1.66
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,588 +0,0 @@
-/* $NetBSD: db_trace.c,v 1.66 2009/11/25 13:53:19 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.66 2009/11/25 13:53:19 rmind Exp
$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/intr.h>
-#include <sys/cpu.h>
-
-#include <machine/db_machdep.h>
-#include <machine/frame.h>
-#include <machine/trap.h>
-#include <machine/pmap.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_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 *, ...))
-{
- int *frame, *lastframe;
- int *retaddr, *arg0;
- int *argp;
- db_addr_t callpc;
- int is_trap = NONE;
- 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 = (int *)ddb_regs.tf_ebp;
- callpc = (db_addr_t)ddb_regs.tf_eip;
- } else {
- if (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 {
- (*pr)("trace: pid %d ", (int)addr);
- lwpaddr = (db_addr_t)db_proc_find((pid_t)addr);
- if (addr == 0) {
- (*pr)("not found\n");
- return;
- }
- db_read_bytes(addr, 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) {
- frame = (int *)ddb_regs.tf_ebp;
- callpc = (db_addr_t)ddb_regs.tf_eip;
- (*pr)("at %p\n", frame);
- } else
-#endif
- {
- db_read_bytes((db_addr_t)&pcb->pcb_ebp,
- sizeof(frame), (char *)&frame);
- db_read_bytes((db_addr_t)(frame + 1),
- sizeof(callpc), (char *)&callpc);
- (*pr)("at %p\n", frame);
- db_read_bytes((db_addr_t)frame,
- sizeof(frame), (char *)&frame);
- }
- } else {
- frame = (int *)addr;
- db_read_bytes((db_addr_t)(frame + 1),
- sizeof(callpc), (char *)&callpc);
- db_read_bytes((db_addr_t)frame,
- sizeof(frame), (char *)&frame);
- }
- }
- 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 */
- int instr = db_get_value(callpc, 4, false);
-
- offset = 1;
- if ((instr & 0x00ffffff) == 0x00e58955 ||
- /* enter: pushl %ebp, movl %esp, %ebp */
- (instr & 0x0000ffff) == 0x0000e589
- /* enter+1: movl %esp, %ebp */) {
- 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 %esp instead
- */
- argp = &((struct i386_frame
*)(ddb_regs.tf_esp-4))->f_arg0;
- } else {
- argp = frame + 2;
- }
-
- while (narg) {
- if (argnp)
- (*pr)("%s=", *argnp++);
- (*pr)("%lx", db_get_value((int)argp, 4, 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 i386_frame *fp = (void *)(ddb_regs.tf_esp-4);
-
- lastframe = (int *)fp;
- callpc = (db_addr_t)
- db_get_value((db_addr_t)&fp->f_retaddr, 4, false);
- continue;
- }
-
- lastframe = frame;
- lastcallpc = callpc;
- if (!db_nextframe(&frame, &retaddr, &arg0,
- &callpc, frame + 2, is_trap, pr))
- break;
-
- if (INKERNEL((int)frame)) {
- /* staying in kernel */
- if (!db_intrstack_p(frame) &&
- db_intrstack_p(lastframe)) {
- (*pr)("--- switch to interrupt stack ---\n");
- } else if (frame < lastframe ||
- (frame == lastframe && callpc == lastcallpc)) {
- (*pr)("Bad frame pointer: %p\n", frame);
- break;
- }
- } else if (INKERNEL((int)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: 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 14:47:53 -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_disasm.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/db_disasm.c,v
retrieving revision 1.14
diff -u -p -r1.14 db_disasm.c
--- amd64/amd64/db_disasm.c 18 Feb 2011 18:00:52 -0000 1.14
+++ amd64/amd64/db_disasm.c 6 Apr 2011 14:47:53 -0000
@@ -36,7 +36,6 @@
__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.14 2011/02/18 18:00:52 drochner
Exp $");
#ifndef _KERNEL
-#include "stubs.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ksyms.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 14:47:53 -0000
@@ -0,0 +1,240 @@
+/* $NetBSD$ */
+
+/*
+ * 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_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/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 14:47:53 -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 14:47:53 -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