0016001 /*
0016002 stacktrace.c
0016003
0016004 Created: Jan 19, 1993 by Philip Homburg
0016005
0016006 Copyright 1995 Philip Homburg
0016007 */
0016008
0016009 #include "inet.h"
0016010
0016011 PUBLIC void stacktrace()
0016012 {
0016013 typedef unsigned int reg_t;
0016014 reg_t bp, pc, hbp;
0016015 extern reg_t get_bp ARGS(( void ));
0016016
0016017 bp= get_bp();
get_bp() is implemented in src/lib/i386/misc/get_bp.s:
! return EBP in EAX
!
! Created: Sep 7, 1992 by Philip Homburg
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define _get_bp
_get_bp:
mov eax, ebp
ret
get_bp() returns ebp, the base pointer of the current stack (i.e., the base pointer of the stack of the function most recently called).
0016018 while(bp)
0016019 {
A typical stack is shown below:
. . . <------+
|
|
--------------- |
| pc | |
--------------- |
+-> | hbp | --+
| --------------- .
| / \
| |
| . . . |
| +
| memory
| ---------------
| | parameter 2 |
| ---------------
| | parameter 1 |
| ---------------
| | pc | <== eip
| ---------------
+-- | hbp | <== ebp
---------------
| local var 1 |
---------------
| local var 2 |
---------------
At any time, the ebp register points to the base address of the stack of the last function called (in the case above, the stack frame at the bottom) and the value at this address points to the base address of the stack of the next-to-last function called and so on until the stack frame of crtso()/main() (for a full description of the stack immediately before main() starts executing, see section 4.7.5 of Operating Systems, Design and Implementation, Second Edition) is encountered (at which time, hbp will be null).
0016020 pc= ((reg_t *)bp)[1];
0016021 hbp= ((reg_t *)bp)[0];
0016022 printf("0x%lx ", (unsigned long)pc);
0016023 if (hbp != 0 && hbp <= bp)
As shown in the figure, the next stack frame should be at a higher memory location than the current stack frame.
0016024 {
0016025 printf("???");
0016026 break;
0016027 }
0016028 bp= hbp;
0016029 }
0016030 printf("\n");
0016031 }
0016032
0016033 /*
0016034 * $PchId: stacktrace.c,v 1.6 1996/05/07 21:11:34 philip Exp $
0016035 */
stacktrace() is a primitive debugger which is called by panic(). stacktrace() returns the addresses of the functions that were called prior to the call to panic(). stacktrace() can be used in combination with the nm utility (which displays the symbol table of the executable; the symbol table includes address to function name mappings) and a disassembler (the disassembler is needed to determine the exact instruction corresponding to each function call; nm can only be used to determine the names of the functions).
Below is example output of panic(). The values after the string "inet stacktrace" are the addresses of the functions called prior to the call to panic().
-----
panic at mnx_eth.c, 44: unable to find task RTL8139: -3
inet stacktrace 0x29a 0xa02 0x547d 0x254 0x61 0x49
Hit ESC to reboot, F-keys for debug dumps
-----