Fix stack tracing once again.

Also check for trap frame boundaries when fetching the return address.
This commit is contained in:
pk 2003-01-13 19:44:06 +00:00
parent ced7282b45
commit 167ce8e6d3
1 changed files with 27 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_trace.c,v 1.17 2002/12/23 13:21:10 pk Exp $ */
/* $NetBSD: db_trace.c,v 1.18 2003/01/13 19:44:06 pk Exp $ */
/*
* Mach Operating System
@ -37,6 +37,10 @@
#include <ddb/db_output.h>
#define INKERNEL(va) (((vaddr_t)(va)) >= USRSTACK)
#define ONINTSTACK(fr) ( \
(u_int)(fr) < (u_int)ddb_cpuinfo->eintstack && \
(u_int)(fr) >= (u_int)ddb_cpuinfo->eintstack - INT_STACK_SIZE \
)
void
db_stack_trace_print(addr, have_addr, count, modif, pr)
@ -46,12 +50,15 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
char *modif;
void (*pr)(const char *, ...);
{
struct frame *frame;
struct frame *frame, *prevframe;
db_addr_t pc;
boolean_t kernel_only = TRUE;
boolean_t trace_thread = FALSE;
char c, *cp = modif;
if (ddb_cpuinfo == NULL)
ddb_cpuinfo = curcpu();
while ((c = *cp++) != 0) {
if (c == 't')
trace_thread = TRUE;
@ -90,22 +97,28 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
int i;
db_expr_t offset;
char *name;
db_addr_t opc;
db_addr_t prevpc;
#define FR(framep,field) (INKERNEL(framep) \
? (u_int)(framep)->##field \
: fuword(&(framep)->##field))
/* Fetch return address */
opc = (db_addr_t)FR(frame, fr_pc);
/* Fetch return address and arguments frame */
prevpc = (db_addr_t)FR(frame, fr_pc);
prevframe = (struct frame *)FR(frame, fr_fp);
/*
* Switch to frame that contains arguments
*/
frame = (struct frame *)FR(frame, fr_fp);
if (frame == NULL || (!INKERNEL(frame) && kernel_only))
if (prevframe == NULL || (!INKERNEL(prevframe) && kernel_only))
return;
if ((ONINTSTACK(frame) && !ONINTSTACK(prevframe)) ||
(INKERNEL(frame) && !INKERNEL(prevframe))) {
/* We're crossing a trap frame; pc = %l1 */
prevpc = (db_addr_t)FR(frame, fr_local[1]);
}
name = NULL;
if (INKERNEL(pc))
db_find_sym_and_offset(pc, &name, &offset);
@ -121,8 +134,13 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
for (i = 0; i < 6; i++)
(*pr)("0x%x%s", FR(frame, fr_arg[i]),
(i < 5) ? ", " : ") at ");
db_printsym(opc, DB_STGY_PROC, pr);
if (INKERNEL(prevpc))
db_printsym(prevpc, DB_STGY_PROC, pr);
else
(*pr)("0x%lx", prevpc);
(*pr)("\n");
pc = opc;
pc = prevpc;
frame = prevframe;
}
}