Print function Call stack----backtrace principle simple realization of __ function

Source: Internet
Author: User
Tags int size

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.