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.
This commit is contained in:
dg 1995-12-21 19:20:58 +00:00
parent 5825c9cbf0
commit d7ff228833
8 changed files with 382 additions and 505 deletions

View File

@ -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

View File

@ -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);
}
/*
* 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)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
int *argp; /* in */
int is_trap; /* in */
db_print_stack_entry(name, narg, argnp, argp, callpc)
char *name;
int narg;
char **argnp;
int *argp;
db_addr_t callpc;
{
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;
case TRAP:
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;
}
}
void
db_stack_trace_cmd(addr, have_addr, count, 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;
}
}
if (count == -1)
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);
}
lastframe = 0;
while (count-- && frame != 0) {
int narg;
char * name;
db_expr_t offset;
db_sym_t sym;
#define MAXNARG 16
char *argnames[MAXNARG], **argnp = 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;
narg = MAXNARG;
if (db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
}
db_printf("%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->f_arg0;
while (narg) {
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");
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;
}
/*
* Figure out the next frame up in the call stack.
*/
static void
db_nextframe(fp, ip)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
{
struct trapframe *tf;
int frame_type;
int eip, ebp;
db_expr_t offset;
char *sym, *name;
lastframe = frame;
db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);
eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
if (frame == 0) {
/* end of chain */
/*
* 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;
}
if (INKERNEL((int)frame)) {
/* staying in kernel */
if (frame <= lastframe) {
db_printf("Bad frame pointer: 0x%x\n", frame);
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);
}
}
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;
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:
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;
{
struct i386_frame *frame, *lastframe = NULL;
int *argp;
db_addr_t callpc;
if (count == -1)
count = 65535;
if (!have_addr) {
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);
}
while (count--) {
int narg;
char * name;
db_expr_t offset;
db_sym_t sym;
#define MAXNARG 16
char *argnames[MAXNARG], **argnp = NULL;
sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
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 (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
db_print_stack_entry(name, narg, argnp, argp, callpc);
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;
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;
}
if (!INKERNEL((int) frame)) {
break;
}
}
}
}

View File

@ -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
/*

View File

@ -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
/*

View File

@ -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

View File

@ -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);
}
/*
* 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)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
int *argp; /* in */
int is_trap; /* in */
db_print_stack_entry(name, narg, argnp, argp, callpc)
char *name;
int narg;
char **argnp;
int *argp;
db_addr_t callpc;
{
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;
case TRAP:
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;
}
}
void
db_stack_trace_cmd(addr, have_addr, count, 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;
}
}
if (count == -1)
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);
}
lastframe = 0;
while (count-- && frame != 0) {
int narg;
char * name;
db_expr_t offset;
db_sym_t sym;
#define MAXNARG 16
char *argnames[MAXNARG], **argnp = 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;
narg = MAXNARG;
if (db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
}
db_printf("%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->f_arg0;
while (narg) {
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");
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;
}
/*
* Figure out the next frame up in the call stack.
*/
static void
db_nextframe(fp, ip)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
{
struct trapframe *tf;
int frame_type;
int eip, ebp;
db_expr_t offset;
char *sym, *name;
lastframe = frame;
db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);
eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
if (frame == 0) {
/* end of chain */
/*
* 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;
}
if (INKERNEL((int)frame)) {
/* staying in kernel */
if (frame <= lastframe) {
db_printf("Bad frame pointer: 0x%x\n", frame);
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);
}
}
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;
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:
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;
{
struct i386_frame *frame, *lastframe = NULL;
int *argp;
db_addr_t callpc;
if (count == -1)
count = 65535;
if (!have_addr) {
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);
}
while (count--) {
int narg;
char * name;
db_expr_t offset;
db_sym_t sym;
#define MAXNARG 16
char *argnames[MAXNARG], **argnp = NULL;
sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
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 (sym != NULL && db_sym_numargs(sym, &narg, argnames)) {
argnp = argnames;
} else {
narg = db_numargs(frame);
}
db_print_stack_entry(name, narg, argnp, argp, callpc);
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;
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;
}
if (!INKERNEL((int) frame)) {
break;
}
}
}
}

View File

@ -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
/*

View File

@ -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