Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.

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()
stacktrace()

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


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);
The eip of each stack frame is printed.


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;
Move to the stack frame of the function that called the current function.


0016029          }
0016030          printf("\n");
0016031 }
0016032 
0016033 /*
0016034  * $PchId: stacktrace.c,v 1.6 1996/05/07 21:11:34 philip Exp $
0016035  */