Coherent4.2.10/i386/user_bt.c
/*
* user_bt.c - console display of user eip stack backtrace.
*/
#include <common/_gregset.h>
#include <sys/types.h>
#include <sys/cmn_err.h>
#define _KERNEL 1
#include <kernel/reg.h>
#include <sys/seg.h>
#include <sys/proc.h>
#include <sys/mmu.h>
extern unsigned char do_user_bt;
/* User backtrace. */
void
user_bt (regsetp)
gregset_t * regsetp;
{
unsigned bp, next_bp;
unsigned text_addr;
register SEG * segp;
unsigned splo;
unsigned bt_limit;
/* Only do the user backtrace stuff if the feature is enabled. */
if (do_user_bt == 0)
return;
/* Only bother with COFF's - no l.out's for now. */
if (__xmode_286 (regsetp)) {
return;
}
/* Get user stack limits, to make sure we stay inside them. */
segp = SELF->p_segl [SISTACK].sr_segp;
splo = (unsigned) (__xmode_286 (regsetp) ? ISP_286 : ISP_386);
splo -= segp->s_size;
/* Print user eip. */
cmn_err (CE_CONT, "User backtrace (COFF): %x ", regsetp->_i386._eip);
/*
* Loop as long as it looks as if we're tracking user stack frame.
*
* User stack frames look like this:
* ...
* arguments for function foo
* return address on return from foo
* ebp->previous stack frame
* ...
*/
bp = (unsigned) (regsetp->_i386._ebp);
for (bt_limit = 0 ; bt_limit < 50 ; bt_limit ++) {
/* Stop backtrace if frame pointer aims outside stack. */
if (bp < splo || bp >= 0x80000000)
break;
/* Fetch and print a return address. */
if (copyin((caddr_t)(bp + 4), & text_addr, 4))
break;
cmn_err (CE_CONT, " -> %x", text_addr);
/* Stop backtrace if text pointer goes out of range. */
/* Sorry about the magic constants - hal */
if (text_addr < 0xA8 || text_addr >= 0x400000)
break;
/* Advance to the next older stack frame. */
if (copyin((caddr_t) bp, & next_bp, 4))
break;
/* Stop backtrace if frame pointer goes down instead of up. */
if (next_bp <= bp)
break;
bp = next_bp;
}
if (bt_limit == 50)
cmn_err (CE_CONT, " ... (there's more)");
cmn_err (CE_CONT, "\n");
}