BackTrace
"Use" user-state or kernel-state program to backtrack stack information when exiting abnormally
"principle" by analyzing the current stack, backtracking the upper function's frame address in the current stack until the top-level function. A frame address is a memory space in which a local variable, a function return address, and a register value exist in the stack. Because different processor stacks are implemented differently (up and down), the implementation of this feature is the compiler's built-in __buildin_frame_address and __buildin_return_address functions. If the compiler does not support this function, you can implement it yourself.
"Interface description" specific instructions can refer to man backtrace Help documentation
Execinfo.h
int BackTrace (void **buffer, int size)
The BackTrace function obtains a backtrace for the current thread, as a list of pointers, and places the information into buffer.
char * * Backtrace_symbols (void *const *buffer, int size)
The Backtrace_symbols function translates the information obtained from the BackTrace function to an array of strings. The argument buffer should is a pointer to an array of addresses obtained via the BackTrace function, and siz E is the number of entries in that array (the return value of BackTrace).
void backtrace_symbols_fd (void *const *buffer, int size, int fd)
Instance
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define Print_debug
#define MAX_BACKTRACE_LEVEL 10
#define BACKTRACE_LOG_NAME "Backtrace.log"
static void Show_reason (int sig, siginfo_t *info, void *secret) {
void *array[max_backtrace_level];
size_t size;
#ifdef Print_debug
Char **strings;
size_t i;
Size = BackTrace (array, max_backtrace_level);
strings = Backtrace_symbols (array, size);
printf ("Obtain%ZD stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", Strings[i]);
Free (strings);
#else
int fd = open (Backstrace_log_name, O_creat | O_WRONLY);
Size = BackTrace (array, max_backtrace_level);
BACKTRACE_SYMBOLS_FD (array, size, FD);
Close (FD);
#endif
Exit (0);
}
void Die () {
Char *str1;
Char *str2;
Char *STR3;
char *STR4 = NULL;
strcpy (STR4, "AB");
}
void Let_it_die () {
Die ();
}
int main (int argc, char **argv) {
struct Sigaction Act;
Act.sa_sigaction = Show_reason;
Sigemptyset (&act.sa_mask);
Act.sa_flags = Sa_restart | Sa_siginfo;
Sigaction (SIGSEGV, &act, NULL);
Sigaction (SIGUSR1, &act, NULL);
Sigaction (SIGFPE, &act, NULL);
Sigaction (Sigill, &act, NULL);
Sigaction (Sigbus, &act, NULL);
Sigaction (SIGABRT, &act, NULL);
Sigaction (Sigsys, &act, NULL);
Let_it_die ();
return 0;
}
Debugging
1) compiling
[Email protected]:~/test$ gcc backtrace_test.c-o backtrace_test-g–rdynamic
(Note:-rdynamic, this option is passed to linker, linker will place the symbol in the. Dydym table so backtrace_symbols can get the symbol corresponding to the address.) So even if you use the-G to compile the program, if you do not use-rdynamic, Backtrace_symbols can not find the address corresponding to the symbol. This is a flaw in the BackTrace series function)
2) Run
[Email protected]:~/test$./backtrace_test
Obtain 7 stack frames.
./backtrace_test () [0x40096e]
/lib/x86_64-linux-gnu/libc.so.6 (+0x364a0) [0x7f2ff171c4a0]
./backtrace_test (die+0x18) [0X400A03]
./backtrace_test (LET_IT_DIE+0XE) [0x400a1d]
./backtrace_test (Main+0xf6) [0X400B15]
/lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xed) [0x7f2ff170776d]
./backtrace_test () [0x400889]
Summary of Linux kernel debugging methods BackTrace