The BackTrace function is one of the basic functions of the CallStack debugger, which enables you to see the invocation relationships of functions at all levels. In GdB, this function is called backtrace, and you can enter the BT command to see the callstack of the current function. It's a little bit interesting to realize, and here's a look.
Let's look at the basic model of the stack first.
Parameter n |
↓ High Address |
Parameters... |
The order of function arguments into stacks is related to the specific invocation method |
Parameter 3 |
Parameter 2 |
Parameter 1 |
Eip |
Returns the address of the next instruction after this call |
Ebp |
This saves the caller's EBP, and then the EBP registers point to the top of the stack at this point. |
Temporary variable 1 |
|
Temporary Variable 2 |
|
Temporary variable 3 |
|
Temporary variable ... |
|
Temp variable N |
↓ Low Address |
The stack has been pushed down the top of the stack with the depth of the function call. Each time the function is called, the first pressure function parameter (from right to left order), and then pressed into the function calls the next instruction address (completed by call). Then enter the calling function body to perform the first "PUSHL%ebp" and "Movl%esp,%EBP" (which has been added to the function header by the compiler), and then the local variable in the function body is pressed into the stack. The nesting of calls to the function is again encountered, and so on.
"Pushl%ebp" and "Movl%esp,%EBP" These two instructions are very profound meaning: first will be ebp into the stack, and then the stack top pointer esp assignment to EBP. "Movl%esp,%EBP" This instruction on the surface is to use ESP to EBP the original value of the cover, it is not-because to EBP assignment before, the original EBP value has been pressed stack (located on the top of the stack), and the new EBP is precisely pointing to the top of the stack.
At this point the EBP register is already in a very important position, the register is stored in the stack of an address (the original EBP into the stack after the top), from the address as the benchmark, up (stack bottom direction) to get the return address, parameter values, downward (stack top direction) to get the function of local variables value, The address also stores the EBP value at the time of the previous function call.
To implement callstack we need to know the following information:
1. The instruction address at the time the function was invoked (that is, the EIP at the time, which is the position of the previous (int *) ebp+1).
2. The source code location corresponding to the instruction address.
On the 1th, from the above table, you can see that the stack of all levels of EIP values, we take out on the line. Use the following code to implement:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN 4 #define EXEFILE "BT" int back
Trace_m (void **buffer, int size) {int i = 0;
unsigned int _ebp = 0;
unsigned int _eip = 0;
Char cmd[size][64];
__asm__ __volatile__ ("\ movl%%ebp,%0": "=g" (_EBP):: "Memory"
);
for (i = 0; i < size; i++) {_eip = (unsigned int) ((unsigned int*) _EBP + 1);
_EIP = * (unsigned int*) _eip;
_EBP = * (unsigned int*) _ebp;
Buffer[i] = (void*) _eip;
fprintf (stderr, "%p->", Buffer[i]);
memset (Cmd[i], 0, sizeof (cmd[i));
sprintf (Cmd[i], "Addr2line%p-e", Buffer[i]);
Strncat (Cmd[i], Exefile, strlen (exefile));
System (Cmd[i]);
return size;
} static void Test2 (void) {int i = 0;
void *buffer[len] = {0}; Backtrace_m (buffer, LEN);
Return
} static void Test1 (void) {test2 ();}
static void Test (void) {test1 ();}
int main (int argc, char *argv[]) {test ();
return 0; }
GCC 4.4.0, Ubuntu 9.04 compiled via
Program output:
0X80486B2->/home/steven/ctest/bt.c:44
0X80486BF->/home/steven/ctest/bt.c:49
0x80486cc->/home/steven/ctest/bt.c:54
0X80486D9->/home/steven/ctest/bt.c:59
This is also very simple about how to correspond the instruction address to the line number. Can be queried from the map file or Elf. Binutil with a addr2line gadget that can help you find the location of the address in the source file, provided that you need to add the-GGDB compilation option when compiling.
[Root@linux bt]# addr2line 0x804849c-e BT
/root/test/bt/bt.c:42 from: http://hi.chinaunix.net/?uid-1825075-action-viewspace-itemid-40672