summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-12-21 19:20:58 +0000
committerdg <dg@FreeBSD.org>1995-12-21 19:20:58 +0000
commitd7ff22883389d146a476c4cd22850b974be77735 (patch)
treeff704a2e693c10f01cc0543d29c4b488d6eb19fa /sys
parent5825c9cbf0978dcd05ed5a9f257764ef7683c8d2 (diff)
downloadFreeBSD-src-d7ff22883389d146a476c4cd22850b974be77735.zip
FreeBSD-src-d7ff22883389d146a476c4cd22850b974be77735.tar.gz
Rewrote most of the ddb stack traceback code. These changes are smarter
about decoding trap/syscall/interrupt frames and generally works better than the previous stuff. Removed some special (incorrect) frobbing of the frame pointer that was messing some things up with the new traceback code.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/cpu_switch.S6
-rw-r--r--sys/amd64/amd64/db_trace.c373
-rw-r--r--sys/amd64/amd64/exception.S13
-rw-r--r--sys/amd64/amd64/exception.s13
-rw-r--r--sys/amd64/amd64/swtch.s6
-rw-r--r--sys/i386/i386/db_trace.c373
-rw-r--r--sys/i386/i386/exception.s13
-rw-r--r--sys/i386/i386/swtch.s6
8 files changed, 340 insertions, 463 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index ca0ed69..3bb1463 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.22 1995/12/09 20:40:41 phk Exp $
+ * $Id: swtch.s,v 1.23 1995/12/10 13:36:30 phk Exp $
*/
#include "npx.h" /* for NNPX */
@@ -230,8 +230,8 @@ sw0: .asciz "cpu_switch"
ALIGN_TEXT
_idle:
MCOUNT
- movl $tmpstk,%ebp
- movl %ebp,%esp
+ xorl %ebp,%ebp
+ movl $tmpstk,%esp
movl _IdlePTD,%ecx
movl %ecx,%cr3
sti
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index a79f6d0..77fe236 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -23,7 +23,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: db_trace.c,v 1.11 1995/05/30 07:59:23 rgrimes Exp $
+ * $Id: db_trace.c,v 1.12 1995/11/24 13:27:24 bde Exp $
*/
#include <sys/param.h>
@@ -71,7 +71,7 @@ struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
/*
* Stack trace.
*/
-#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK)
struct i386_frame {
struct i386_frame *f_frame;
@@ -79,32 +79,14 @@ struct i386_frame {
int f_arg0;
};
+#define NORMAL 0
#define TRAP 1
#define INTERRUPT 2
#define SYSCALL 3
-static db_addr_t db_trap_symbol_value;
-static db_addr_t db_syscall_symbol_value;
-static db_addr_t db_kdintr_symbol_value;
-static boolean_t db_trace_symbols_found;
-
-static void db_find_trace_symbols __P((void));
-static void db_nextframe __P((struct i386_frame **fp, db_addr_t *ip,
- int *argp, int is_trap));
-static int db_numargs __P((struct i386_frame *fp));
-
-static void
-db_find_trace_symbols()
-{
- 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;
-}
+static void db_nextframe __P((struct i386_frame **, db_addr_t *));
+static int db_numargs __P((struct i386_frame *));
+static void db_print_stack_entry __P((char *, int, char **, int *, db_addr_t));
/*
* Figure out how many arguments were passed into the frame at "fp".
@@ -118,229 +100,202 @@ db_numargs(fp)
int args;
argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
- if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext)
- args = 5;
- 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
+ if (argp < (int *)VM_MIN_KERNEL_ADDRESS ||
+ argp > (int *)etext) {
args = 5;
+ } 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 = 5;
}
return (args);
}
+static void
+db_print_stack_entry(name, narg, argnp, argp, callpc)
+ char *name;
+ int narg;
+ char **argnp;
+ int *argp;
+ db_addr_t callpc;
+{
+ db_printf("%s(", name);
+ while (narg) {
+ if (argnp)
+ db_printf("%s=", *argnp++);
+ db_printf("%x", db_get_value((int)argp, 4, FALSE));
+ argp++;
+ if (--narg != 0)
+ db_printf(",");
+ }
+ db_printf(") at ");
+ db_printsym(callpc, DB_STGY_PROC);
+ db_printf("\n");
+}
+
/*
* 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 void
-db_nextframe(fp, ip, argp, is_trap)
+db_nextframe(fp, ip)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
- int *argp; /* in */
- int is_trap; /* in */
{
- struct i386_saved_state *saved_regs;
-
- switch (is_trap) {
- case 0:
- *ip = (db_addr_t)
- db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
- *fp = (struct i386_frame *)
- db_get_value((int) &(*fp)->f_frame, 4, FALSE);
- break;
+ struct trapframe *tf;
+ int frame_type;
+ int eip, ebp;
+ db_expr_t offset;
+ char *sym, *name;
+
+ eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
+ ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
+
+ /*
+ * Figure out frame type.
+ */
+
+ frame_type = NORMAL;
+
+ sym = db_search_symbol(eip, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ if (name != NULL) {
+ if (!strcmp(name, "calltrap")) {
+ frame_type = TRAP;
+ } else if (!strncmp(name, "Xresume", 7)) {
+ frame_type = INTERRUPT;
+ } else if (!strcmp(name, "_Xsyscall")) {
+ frame_type = SYSCALL;
+ }
+ }
+
+ /*
+ * Normal frames need no special processing.
+ */
+ if (frame_type == NORMAL) {
+ *ip = (db_addr_t) eip;
+ *fp = (struct i386_frame *) ebp;
+ return;
+ }
+
+ db_print_stack_entry(name, 0, 0, 0, eip);
+
+ /*
+ * Point to base of trapframe which is just above the
+ * current frame.
+ */
+ tf = (struct trapframe *) ((int)*fp + 8);
+
+ switch (frame_type) {
case TRAP:
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- trap %d, eip = 0x%x, ebp = 0x%x ---\n",
+ tf->tf_trapno, eip, ebp);
+ }
+ break;
+ case SYSCALL:
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- syscall %d, eip = 0x%x, ebp = 0x%x ---\n",
+ tf->tf_eax, eip, ebp);
+ }
+ break;
+ case INTERRUPT:
+ tf = (struct trapframe *)((int)*fp + 16);
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- interrupt, eip = 0x%x, ebp = 0x%x ---\n", eip, ebp);
+ }
+ break;
default:
- /*
- * We know that trap() has 1 argument and we know that
- * it is an (int *).
- */
-#if 0
- saved_regs = (struct i386_saved_state *)
- db_get_value((int)argp, 4, FALSE);
-#endif
- saved_regs = (struct i386_saved_state *)argp;
- db_printf("--- trap (number %d) ---\n",
- saved_regs->tf_trapno & 0xffff);
- db_printsym(saved_regs->tf_eip, DB_STGY_XTRN);
- db_printf(":\n");
- *fp = (struct i386_frame *)saved_regs->tf_ebp;
- *ip = (db_addr_t)saved_regs->tf_eip;
- break;
-
- case SYSCALL: {
- struct trapframe *saved_regs = (struct trapframe *)argp;
-
- db_printf("--- syscall (number %d) ---\n", saved_regs->tf_eax);
- db_printsym(saved_regs->tf_eip, DB_STGY_XTRN);
- db_printf(":\n");
- *fp = (struct i386_frame *)saved_regs->tf_ebp;
- *ip = (db_addr_t)saved_regs->tf_eip;
- }
- break;
+ break;
}
+
+ *ip = (db_addr_t) eip;
+ *fp = (struct i386_frame *) ebp;
}
void
db_stack_trace_cmd(addr, have_addr, count, modif)
- db_expr_t addr;
- boolean_t have_addr;
- db_expr_t count;
- char *modif;
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char *modif;
{
- struct i386_frame *frame, *lastframe;
- int *argp;
- db_addr_t callpc;
- int is_trap;
- boolean_t kernel_only = TRUE;
- boolean_t trace_thread = FALSE;
-
-#if 0
- if (!db_trace_symbols_found)
- db_find_trace_symbols();
-#endif
-
- {
- register char *cp = modif;
- register char c;
-
- while ((c = *cp++) != 0) {
- if (c == 't')
- trace_thread = TRUE;
- if (c == 'u')
- kernel_only = FALSE;
- }
- }
+ struct i386_frame *frame, *lastframe = NULL;
+ int *argp;
+ db_addr_t callpc;
if (count == -1)
- count = 65535;
+ count = 65535;
if (!have_addr) {
- frame = (struct i386_frame *)ddb_regs.tf_ebp;
- callpc = (db_addr_t)ddb_regs.tf_eip;
- }
- else if (trace_thread) {
- printf ("db_trace.c: can't trace thread\n");
- }
- else {
- frame = (struct i386_frame *)addr;
- callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
+ frame = (struct i386_frame *)ddb_regs.tf_ebp;
+ callpc = (db_addr_t)ddb_regs.tf_eip;
+ } else {
+ frame = (struct i386_frame *)addr;
+ callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
}
- lastframe = 0;
- while (count-- && frame != 0) {
- int narg;
- char * name;
- db_expr_t offset;
- db_sym_t sym;
+ while (count--) {
+ int narg;
+ char * name;
+ db_expr_t offset;
+ db_sym_t sym;
#define MAXNARG 16
- char *argnames[MAXNARG], **argnp = NULL;
+ char *argnames[MAXNARG], **argnp = NULL;
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
- if (lastframe == 0 && sym == NULL) {
- /* 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;
- }
- }
-#define STRCMP(s1,s2) ((s1) && (s2) && strcmp((s1), (s2)) == 0)
- if (INKERNEL((int)frame) && STRCMP(name, "_trap")) {
- narg = 1;
- is_trap = TRAP;
- }
- else
- if (INKERNEL((int)frame) && STRCMP(name, "_kdintr")) {
- is_trap = INTERRUPT;
- narg = 0;
- }
- else
- if (INKERNEL((int)frame) && STRCMP(name, "_syscall")) {
- is_trap = SYSCALL;
- narg = 0;
- }
-#undef STRCMP
- else {
- is_trap = 0;
+ argp = &frame->f_arg0;
+ if (lastframe == NULL && sym == NULL) {
+ /* Symbol not found, peek at code */
+ int instr = db_get_value(callpc, 4, FALSE);
+
+ offset = 1;
+ /* enter: pushl %ebp, movl %esp, %ebp */
+ if ((instr & 0x00ffffff) == 0x00e58955 ||
+ /* enter+1: movl %esp, %ebp */
+ (instr & 0x0000ffff) == 0x0000e589) {
+ offset = 0;
+ argp = &((struct i386_frame *)(ddb_regs.tf_esp-4))->f_arg0;
+ }
+ }
narg = MAXNARG;
- if (db_sym_numargs(sym, &narg, argnames)) {
+ if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
- }
- db_printf("%s(", name);
+ db_print_stack_entry(name, narg, argnp, argp, callpc);
- 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->f_arg0;
+ if (lastframe == NULL && offset == 0 && !have_addr) {
+ /* Frame really belongs to next callpc */
+ lastframe = (struct i386_frame *)(ddb_regs.tf_esp-4);
+ callpc = (db_addr_t)db_get_value((int)&lastframe->f_retaddr, 4, FALSE);
+ continue;
+ }
+ lastframe = frame;
- while (narg) {
- if (argnp)
- db_printf("%s=", *argnp++);
- db_printf("%x", db_get_value((int)argp, 4, FALSE));
- argp++;
- if (--narg != 0)
- db_printf(",");
- }
- db_printf(") at ");
- db_printsym(callpc, DB_STGY_PROC);
- db_printf("\n");
-
- if (lastframe == 0 && offset == 0 && !have_addr) {
- /* Frame really belongs to next callpc */
- lastframe = (struct i386_frame *)(ddb_regs.tf_esp-4);
- callpc = (db_addr_t)db_get_value((int)&lastframe->f_retaddr, 4, FALSE);
- continue;
- }
-
- lastframe = frame;
- db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);
-
- if (frame == 0) {
- /* end of chain */
- break;
- }
- if (INKERNEL((int)frame)) {
- /* staying in kernel */
- if (frame <= lastframe) {
- db_printf("Bad frame pointer: 0x%x\n", frame);
- break;
+ db_nextframe(&frame, &callpc);
+
+ if (INKERNEL((int) callpc) && !INKERNEL((int) frame)) {
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ db_print_stack_entry(name, 0, 0, 0, callpc);
+ break;
}
- }
- else if (INKERNEL((int)lastframe)) {
- /* switch from user to kernel */
- if (kernel_only)
- break; /* kernel stack only */
- }
- else {
- /* in user */
- if (frame <= lastframe) {
- db_printf("Bad user frame pointer: 0x%x\n", frame);
- break;
+ if (!INKERNEL((int) frame)) {
+ break;
}
- }
}
}
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index e7b44be..c32df17 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
+ * $Id: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $
*/
#include "npx.h" /* NNPX */
@@ -167,17 +167,6 @@ calltrap:
FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */
incl _cnt+V_TRAP
orl $SWI_AST_MASK,_cpl
-
- /*
- * Fake a call frame: point %ebp at a 2 element array consisting
- * of { trappee's %ebp, trappee's %eip }. The stack frame is in
- * the wrong order for this, but the trappee's %ebp is fortunately
- * followed by junk which we can overwrite with the trappee's %eip.
- */
- movl TF_EIP(%esp),%eax
- movl %eax,TF_ISP(%esp)
- lea TF_EBP(%esp),%ebp
-
call _trap
/*
diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s
index e7b44be..c32df17 100644
--- a/sys/amd64/amd64/exception.s
+++ b/sys/amd64/amd64/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
+ * $Id: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $
*/
#include "npx.h" /* NNPX */
@@ -167,17 +167,6 @@ calltrap:
FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */
incl _cnt+V_TRAP
orl $SWI_AST_MASK,_cpl
-
- /*
- * Fake a call frame: point %ebp at a 2 element array consisting
- * of { trappee's %ebp, trappee's %eip }. The stack frame is in
- * the wrong order for this, but the trappee's %ebp is fortunately
- * followed by junk which we can overwrite with the trappee's %eip.
- */
- movl TF_EIP(%esp),%eax
- movl %eax,TF_ISP(%esp)
- lea TF_EBP(%esp),%ebp
-
call _trap
/*
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index ca0ed69..3bb1463 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.22 1995/12/09 20:40:41 phk Exp $
+ * $Id: swtch.s,v 1.23 1995/12/10 13:36:30 phk Exp $
*/
#include "npx.h" /* for NNPX */
@@ -230,8 +230,8 @@ sw0: .asciz "cpu_switch"
ALIGN_TEXT
_idle:
MCOUNT
- movl $tmpstk,%ebp
- movl %ebp,%esp
+ xorl %ebp,%ebp
+ movl $tmpstk,%esp
movl _IdlePTD,%ecx
movl %ecx,%cr3
sti
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index a79f6d0..77fe236 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -23,7 +23,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: db_trace.c,v 1.11 1995/05/30 07:59:23 rgrimes Exp $
+ * $Id: db_trace.c,v 1.12 1995/11/24 13:27:24 bde Exp $
*/
#include <sys/param.h>
@@ -71,7 +71,7 @@ struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
/*
* Stack trace.
*/
-#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK)
struct i386_frame {
struct i386_frame *f_frame;
@@ -79,32 +79,14 @@ struct i386_frame {
int f_arg0;
};
+#define NORMAL 0
#define TRAP 1
#define INTERRUPT 2
#define SYSCALL 3
-static db_addr_t db_trap_symbol_value;
-static db_addr_t db_syscall_symbol_value;
-static db_addr_t db_kdintr_symbol_value;
-static boolean_t db_trace_symbols_found;
-
-static void db_find_trace_symbols __P((void));
-static void db_nextframe __P((struct i386_frame **fp, db_addr_t *ip,
- int *argp, int is_trap));
-static int db_numargs __P((struct i386_frame *fp));
-
-static void
-db_find_trace_symbols()
-{
- 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;
-}
+static void db_nextframe __P((struct i386_frame **, db_addr_t *));
+static int db_numargs __P((struct i386_frame *));
+static void db_print_stack_entry __P((char *, int, char **, int *, db_addr_t));
/*
* Figure out how many arguments were passed into the frame at "fp".
@@ -118,229 +100,202 @@ db_numargs(fp)
int args;
argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
- if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext)
- args = 5;
- 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
+ if (argp < (int *)VM_MIN_KERNEL_ADDRESS ||
+ argp > (int *)etext) {
args = 5;
+ } 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 = 5;
}
return (args);
}
+static void
+db_print_stack_entry(name, narg, argnp, argp, callpc)
+ char *name;
+ int narg;
+ char **argnp;
+ int *argp;
+ db_addr_t callpc;
+{
+ db_printf("%s(", name);
+ while (narg) {
+ if (argnp)
+ db_printf("%s=", *argnp++);
+ db_printf("%x", db_get_value((int)argp, 4, FALSE));
+ argp++;
+ if (--narg != 0)
+ db_printf(",");
+ }
+ db_printf(") at ");
+ db_printsym(callpc, DB_STGY_PROC);
+ db_printf("\n");
+}
+
/*
* 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 void
-db_nextframe(fp, ip, argp, is_trap)
+db_nextframe(fp, ip)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
- int *argp; /* in */
- int is_trap; /* in */
{
- struct i386_saved_state *saved_regs;
-
- switch (is_trap) {
- case 0:
- *ip = (db_addr_t)
- db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
- *fp = (struct i386_frame *)
- db_get_value((int) &(*fp)->f_frame, 4, FALSE);
- break;
+ struct trapframe *tf;
+ int frame_type;
+ int eip, ebp;
+ db_expr_t offset;
+ char *sym, *name;
+
+ eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
+ ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
+
+ /*
+ * Figure out frame type.
+ */
+
+ frame_type = NORMAL;
+
+ sym = db_search_symbol(eip, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ if (name != NULL) {
+ if (!strcmp(name, "calltrap")) {
+ frame_type = TRAP;
+ } else if (!strncmp(name, "Xresume", 7)) {
+ frame_type = INTERRUPT;
+ } else if (!strcmp(name, "_Xsyscall")) {
+ frame_type = SYSCALL;
+ }
+ }
+
+ /*
+ * Normal frames need no special processing.
+ */
+ if (frame_type == NORMAL) {
+ *ip = (db_addr_t) eip;
+ *fp = (struct i386_frame *) ebp;
+ return;
+ }
+
+ db_print_stack_entry(name, 0, 0, 0, eip);
+
+ /*
+ * Point to base of trapframe which is just above the
+ * current frame.
+ */
+ tf = (struct trapframe *) ((int)*fp + 8);
+
+ switch (frame_type) {
case TRAP:
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- trap %d, eip = 0x%x, ebp = 0x%x ---\n",
+ tf->tf_trapno, eip, ebp);
+ }
+ break;
+ case SYSCALL:
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- syscall %d, eip = 0x%x, ebp = 0x%x ---\n",
+ tf->tf_eax, eip, ebp);
+ }
+ break;
+ case INTERRUPT:
+ tf = (struct trapframe *)((int)*fp + 16);
+ if (INKERNEL((int) tf)) {
+ eip = tf->tf_eip;
+ ebp = tf->tf_ebp;
+ db_printf("--- interrupt, eip = 0x%x, ebp = 0x%x ---\n", eip, ebp);
+ }
+ break;
default:
- /*
- * We know that trap() has 1 argument and we know that
- * it is an (int *).
- */
-#if 0
- saved_regs = (struct i386_saved_state *)
- db_get_value((int)argp, 4, FALSE);
-#endif
- saved_regs = (struct i386_saved_state *)argp;
- db_printf("--- trap (number %d) ---\n",
- saved_regs->tf_trapno & 0xffff);
- db_printsym(saved_regs->tf_eip, DB_STGY_XTRN);
- db_printf(":\n");
- *fp = (struct i386_frame *)saved_regs->tf_ebp;
- *ip = (db_addr_t)saved_regs->tf_eip;
- break;
-
- case SYSCALL: {
- struct trapframe *saved_regs = (struct trapframe *)argp;
-
- db_printf("--- syscall (number %d) ---\n", saved_regs->tf_eax);
- db_printsym(saved_regs->tf_eip, DB_STGY_XTRN);
- db_printf(":\n");
- *fp = (struct i386_frame *)saved_regs->tf_ebp;
- *ip = (db_addr_t)saved_regs->tf_eip;
- }
- break;
+ break;
}
+
+ *ip = (db_addr_t) eip;
+ *fp = (struct i386_frame *) ebp;
}
void
db_stack_trace_cmd(addr, have_addr, count, modif)
- db_expr_t addr;
- boolean_t have_addr;
- db_expr_t count;
- char *modif;
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char *modif;
{
- struct i386_frame *frame, *lastframe;
- int *argp;
- db_addr_t callpc;
- int is_trap;
- boolean_t kernel_only = TRUE;
- boolean_t trace_thread = FALSE;
-
-#if 0
- if (!db_trace_symbols_found)
- db_find_trace_symbols();
-#endif
-
- {
- register char *cp = modif;
- register char c;
-
- while ((c = *cp++) != 0) {
- if (c == 't')
- trace_thread = TRUE;
- if (c == 'u')
- kernel_only = FALSE;
- }
- }
+ struct i386_frame *frame, *lastframe = NULL;
+ int *argp;
+ db_addr_t callpc;
if (count == -1)
- count = 65535;
+ count = 65535;
if (!have_addr) {
- frame = (struct i386_frame *)ddb_regs.tf_ebp;
- callpc = (db_addr_t)ddb_regs.tf_eip;
- }
- else if (trace_thread) {
- printf ("db_trace.c: can't trace thread\n");
- }
- else {
- frame = (struct i386_frame *)addr;
- callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
+ frame = (struct i386_frame *)ddb_regs.tf_ebp;
+ callpc = (db_addr_t)ddb_regs.tf_eip;
+ } else {
+ frame = (struct i386_frame *)addr;
+ callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
}
- lastframe = 0;
- while (count-- && frame != 0) {
- int narg;
- char * name;
- db_expr_t offset;
- db_sym_t sym;
+ while (count--) {
+ int narg;
+ char * name;
+ db_expr_t offset;
+ db_sym_t sym;
#define MAXNARG 16
- char *argnames[MAXNARG], **argnp = NULL;
+ char *argnames[MAXNARG], **argnp = NULL;
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
- if (lastframe == 0 && sym == NULL) {
- /* 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;
- }
- }
-#define STRCMP(s1,s2) ((s1) && (s2) && strcmp((s1), (s2)) == 0)
- if (INKERNEL((int)frame) && STRCMP(name, "_trap")) {
- narg = 1;
- is_trap = TRAP;
- }
- else
- if (INKERNEL((int)frame) && STRCMP(name, "_kdintr")) {
- is_trap = INTERRUPT;
- narg = 0;
- }
- else
- if (INKERNEL((int)frame) && STRCMP(name, "_syscall")) {
- is_trap = SYSCALL;
- narg = 0;
- }
-#undef STRCMP
- else {
- is_trap = 0;
+ argp = &frame->f_arg0;
+ if (lastframe == NULL && sym == NULL) {
+ /* Symbol not found, peek at code */
+ int instr = db_get_value(callpc, 4, FALSE);
+
+ offset = 1;
+ /* enter: pushl %ebp, movl %esp, %ebp */
+ if ((instr & 0x00ffffff) == 0x00e58955 ||
+ /* enter+1: movl %esp, %ebp */
+ (instr & 0x0000ffff) == 0x0000e589) {
+ offset = 0;
+ argp = &((struct i386_frame *)(ddb_regs.tf_esp-4))->f_arg0;
+ }
+ }
narg = MAXNARG;
- if (db_sym_numargs(sym, &narg, argnames)) {
+ if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
- }
- db_printf("%s(", name);
+ db_print_stack_entry(name, narg, argnp, argp, callpc);
- 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->f_arg0;
+ if (lastframe == NULL && offset == 0 && !have_addr) {
+ /* Frame really belongs to next callpc */
+ lastframe = (struct i386_frame *)(ddb_regs.tf_esp-4);
+ callpc = (db_addr_t)db_get_value((int)&lastframe->f_retaddr, 4, FALSE);
+ continue;
+ }
+ lastframe = frame;
- while (narg) {
- if (argnp)
- db_printf("%s=", *argnp++);
- db_printf("%x", db_get_value((int)argp, 4, FALSE));
- argp++;
- if (--narg != 0)
- db_printf(",");
- }
- db_printf(") at ");
- db_printsym(callpc, DB_STGY_PROC);
- db_printf("\n");
-
- if (lastframe == 0 && offset == 0 && !have_addr) {
- /* Frame really belongs to next callpc */
- lastframe = (struct i386_frame *)(ddb_regs.tf_esp-4);
- callpc = (db_addr_t)db_get_value((int)&lastframe->f_retaddr, 4, FALSE);
- continue;
- }
-
- lastframe = frame;
- db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);
-
- if (frame == 0) {
- /* end of chain */
- break;
- }
- if (INKERNEL((int)frame)) {
- /* staying in kernel */
- if (frame <= lastframe) {
- db_printf("Bad frame pointer: 0x%x\n", frame);
- break;
+ db_nextframe(&frame, &callpc);
+
+ if (INKERNEL((int) callpc) && !INKERNEL((int) frame)) {
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ db_print_stack_entry(name, 0, 0, 0, callpc);
+ break;
}
- }
- else if (INKERNEL((int)lastframe)) {
- /* switch from user to kernel */
- if (kernel_only)
- break; /* kernel stack only */
- }
- else {
- /* in user */
- if (frame <= lastframe) {
- db_printf("Bad user frame pointer: 0x%x\n", frame);
- break;
+ if (!INKERNEL((int) frame)) {
+ break;
}
- }
}
}
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index e7b44be..c32df17 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.12 1995/12/14 14:35:33 peter Exp $
+ * $Id: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $
*/
#include "npx.h" /* NNPX */
@@ -167,17 +167,6 @@ calltrap:
FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */
incl _cnt+V_TRAP
orl $SWI_AST_MASK,_cpl
-
- /*
- * Fake a call frame: point %ebp at a 2 element array consisting
- * of { trappee's %ebp, trappee's %eip }. The stack frame is in
- * the wrong order for this, but the trappee's %ebp is fortunately
- * followed by junk which we can overwrite with the trappee's %eip.
- */
- movl TF_EIP(%esp),%eax
- movl %eax,TF_ISP(%esp)
- lea TF_EBP(%esp),%ebp
-
call _trap
/*
diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s
index ca0ed69..3bb1463 100644
--- a/sys/i386/i386/swtch.s
+++ b/sys/i386/i386/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.22 1995/12/09 20:40:41 phk Exp $
+ * $Id: swtch.s,v 1.23 1995/12/10 13:36:30 phk Exp $
*/
#include "npx.h" /* for NNPX */
@@ -230,8 +230,8 @@ sw0: .asciz "cpu_switch"
ALIGN_TEXT
_idle:
MCOUNT
- movl $tmpstk,%ebp
- movl %ebp,%esp
+ xorl %ebp,%ebp
+ movl $tmpstk,%esp
movl _IdlePTD,%ecx
movl %ecx,%cr3
sti
OpenPOWER on IntegriCloud