Fix a problem I noticed a while back but had too many other things
in the air to deal with it. Basically, following a kernel fault (eg. dereferencing a NULL pointer in kernel mode) a DDB 'trace' did not show the function where the fault occurred. For example: db> trace _Debugger() _panic() _trap() faultstkadj() _pool_drain() _uvm_pageout() _start_pagedaemon() _proc_trampoline() db> The 'faultstkadj()' line here is bogus. It is shown because the return address to 'trap()' happens to point there, and since faultstkadj() has no stack frame, DDB assumes it was the faulting function. In this example, the _real_ function was pool_reclaim(), but you would have to look at the program counter at the time of the fault to figure that one out. This fix makes the trace command do the dirty work for you by grubbing around in 'trap()'s argument list to find the *real* PC value at the time of the fault, replacing the 'faultstkadj()' line with the real function's name.
This commit is contained in:
parent
a6a272d18a
commit
f7a019c61a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: db_trace.c,v 1.23 1999/01/15 23:15:50 thorpej Exp $ */
|
||||
/* $NetBSD: db_trace.c,v 1.24 1999/04/04 11:33:02 scw Exp $ */
|
||||
|
||||
/*
|
||||
* Mach Operating System
|
||||
|
@ -99,6 +99,8 @@ extern int curpcb;
|
|||
#define get(addr, space) \
|
||||
(db_get_value((db_addr_t)(addr), sizeof(int), FALSE))
|
||||
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
#define NREGISTERS 16
|
||||
|
||||
struct stackpos {
|
||||
|
@ -475,6 +477,7 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
|
|||
char * name;
|
||||
struct stackpos pos;
|
||||
boolean_t kernel_only = TRUE;
|
||||
int fault_pc = 0;
|
||||
|
||||
{
|
||||
char *cp = modif;
|
||||
|
@ -535,6 +538,37 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
|
|||
val = MAXINT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Since faultstkadj doesn't set up a valid stack frame,
|
||||
* we would assume it was the source of the fault. To
|
||||
* get around this we peek at the fourth argument of
|
||||
* "trap()" (the stack frame at the time of the fault)
|
||||
* to determine the _real_ value of PC when things wen
|
||||
* wrong.
|
||||
*
|
||||
* NOTE: If the argument list for 'trap()' ever changes,
|
||||
* we lose.
|
||||
*/
|
||||
if ( strcmp("_trap", name) == 0 ) {
|
||||
/* Point to 'trap()'s argument list */
|
||||
regp = pos.k_fp + FR_SAVFP + 4;
|
||||
/* Step over the arguments to the frame structure */
|
||||
regp += (4 * 4) + offsetof(struct frame, f_pc);
|
||||
/* Get the PC at the time of the fault */
|
||||
fault_pc = get(regp, DSP);
|
||||
} else
|
||||
if ( fault_pc ) {
|
||||
if ( strcmp("faultstkadj", name) == 0 ) {
|
||||
db_find_sym_and_offset(fault_pc, &name, &val);
|
||||
if (name == 0) {
|
||||
name = "?";
|
||||
val = MAXINT;
|
||||
}
|
||||
}
|
||||
fault_pc = 0;
|
||||
}
|
||||
|
||||
db_printf("%s", name);
|
||||
if (pos.k_entry != MAXINT && name) {
|
||||
char * entry_name;
|
||||
|
|
Loading…
Reference in New Issue