BackTrace, Backtrace_symbols, Backtrace_symbols_fd-support for application self-debugging

Source: Internet
Author: User

BackTrace is an applied self-debugging function introduced by library functions.

The three functions in the series can buffer or output a stack frame.

#include <execinfo.h>

int backtrace (void **buffer, int size);

Char **backtrace_symbols (void *const *buffer, int size);

void backtrace_symbols_fd (void *const *buffer, int size, int fd);

Transferred from: http://www.linuxidc.com/Linux/2012-11/73470.htm

The usual way to see the function run-time stack is to use an external debugger such as GDB (BT command), but sometimes it is useful to print out the call stack of a function in case of a program error in order to parse the program's bug (mainly for long-running program analysis).

In the glibc header file "Execinfo.h", three functions were declared to get the function call stack of the current thread.

int BackTrace (void **buffer,int size)

The function is used to get the call stack of the current thread, and the information obtained will be stored in buffer, which is a list of pointers. The parameter size is used to specify how many void* elements can be saved in buffer. The function return value is the actual number of pointers that are obtained, up to or above size.

The pointer in buffer is actually the return address obtained from the stack, and each stack frame has a return address.

Note: Some compiler tuning options interfere with getting the correct call stack, and inline functions do not have a stack frame; Deleting a frame pointer also causes the stack contents to be parsed incorrectly

char * * BACKTRACE_SYMBOLS (void *const *buffer, int size)

Backtrace_symbols converts the information obtained from the BackTrace function into an array of strings. The parameter buffer should be an array of pointers obtained from the BackTrace function, where size is the number of elements in the array (the return value of BackTrace)

The function return value is a pointer to an array of strings that is the same size as buffer. Each string contains a printable information relative to the corresponding element in buffer. It includes the function name, the offset address of the function, and the actual return address.

only programs that use the ELF binary format can now get the function name and offset address. In other systems, only 16 binary return addresses can be obtained. In addition, you may need to pass the corresponding symbol to the linker to support function name functions ( for example, in a system that uses the GNU LD Linker, you need to pass (-rdynamic), Rdynamic can be used to inform the linker to add all the symbols to the dynamic symbol table, and if your linker supports-rdynamic, it is recommended that it be added! )

The return value of the function is the space requested by the malloc function, so the caller must use the free function to release the pointer.

Note: If you cannot get enough space for a string, the return value of the function will be null

void backtrace_symbols_fd (void *const *buffer, int size, int fd)

BACKTRACE_SYMBOLS_FD has the same function as the Backtrace_symbols function, but instead of returning a string array to the caller, it writes the result to a file with the file descriptor fd, one row for each function. It does not need to call the malloc function , so it is suitable for situations where the function may fail to be called

The following is an example in glibc (slightly modified):

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* Obtain a backtrace and print it to @code {stdout}. */
void Print_trace (void)
{
void *array[10];
size_t size;
Char **strings;
size_t i;
 
Size = BackTrace (array, 10);
strings = Backtrace_symbols (array, size);
if (NULL = = strings)
{
Perror ("Backtrace_synbols");
Exit (exit_failure);
}

printf ("obtained%ZD stack frames.\n", size);

for (i = 0; i < size; i++)
printf ("%s\n", Strings[i]);

Free (strings);
strings = NULL;
}

/* A dummy function to make the backtrace more interesting. */
void Dummy_function (void)
{
Print_trace ();
}

int main (int argc, char *argv[])
{
Dummy_function ();
return 0;
}

The output is as follows:

Obtained 4 stack frames.
./execinfo () [0X80484DD]
./execinfo () [0x8048549]
./execinfo () [0x8048556]
/lib/i386-linux-gnu/libc.so.6 (__LIBC_START_MAIN+0XF3) [0x70a113]

We can also use this backtrace to locate the wrong position of the segment.

Usually, the system sends a SIGSEGV signal to the program when the program has a segment error, and the default processing is the Exit function. We can use the signal (SIGSEGV, &your_function) function to take over the processing of the SIGSEGV signal, the program automatically calls our prepared function after a segment error, in order to get the current function call stack in that function.

Examples are as follows:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <execinfo.h>
#include <signal.h>

void dump (int signo)
{
void *buffer[30] = {0};
size_t size;
char **strings = NULL;
size_t i = 0;

Size = backtrace (buffer, 30);
fprintf (stdout, "obtained%ZD stack frames.nm\n", size);
strings = Backtrace_symbols (buffer, size);
if (strings = = NULL)
{
Perror ("Backtrace_symbols.");
Exit (Exit_failure);
}

for (i = 0; i < size; i++)
{
fprintf (stdout, "%s\n", Strings[i]);
}
Free (strings);
strings = NULL;
Exit (0);
}

void Func_c ()
{
* ((volatile char *) 0x0) = 0x9999;
}

void Func_b ()
{
Func_c ();
}

void Func_a ()
{
Func_b ();
}

int main (int argc, const char *argv[])
{
if (signal (SIGSEGV, dump) = = Sig_err)
Perror ("Can ' t catch SIGSEGV");
Func_a ();
return 0;
}

Compile the program:
Gcc-g-rdynamic test.c-o test;./test
The output is as follows:

Obtained6stackframes.nm
./backstrace_debug (dump+0x45) [0X80487C9]
[0x468400]
./backstrace_debug (func_b+0x8) [0x804888c]
./backstrace_debug (func_a+0x8) [0x8048896]
./backstrace_debug (MAIN+0X33) [0X80488CB]
/lib/i386-linux-gnu/libc.so.6 (__LIBC_START_MAIN+0XF3) [0x129113]

Then:
objdump-d Test > Test.s
Search for 804888c in Test.s as follows:

8048884 <func_b>:
8048884:55 Push%EBP
8048885:89 e5 mov%esp,%ebp
8048887:E8 EB FF FF ff call 8048877 <func_c>
804888C:5D Pop%EBP
804888D:C3 ret

Where 80488c is called (call 8048877) C function after the address, although not directly to the C function, through the assembly code, the basic can be introduced is the C function problem (pop instructions will not lead to segment error).
We can also use Addr2line to view

Addr2line 0X804888C-E backstrace_debug-f

Output:

Func_b
/home/astrol/c/backstrace_debug.c:57

BackTrace, Backtrace_symbols, Backtrace_symbols_fd-support for application self-debugging

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.