Backtrace in C
#) Printing backtrace through C code, defined as macro
#include <stdio.h>
#include <execinfo.h> //For backtrace functions
#include <stdlib.h> //For free()
#define BT_FUNC_PTR_COUNT 10
#define BT_PRINT { \
int i, nFuncPtrs; \
void *btFuncPtrs[BT_FUNC_PTR_COUNT]; \
char **btFuncName; \
\
nFuncPtrs = backtrace(btFuncPtrs, BT_FUNC_PTR_COUNT); \
\
btFuncName = backtrace_symbols(btFuncPtrs, nFuncPtrs); \
if (btFuncName) { \
printf("Backtrace: \n"); \
for( i = 0; i < nFuncPtrs; i++) { \
printf("\t %s\n", btFuncName[i]); \
} \
printf("\n"); \
free(btFuncName); \
} \
}
Example output:
./a.out() [0x400884]
./a.out() [0x400924]
./a.out() [0x400956]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x3c4a21ed1d]
./a.out() [0x400799]
Description of these thread-safe functions,
- backtrace(): Returns set of addresses
- backtrace_symbols(): Translates the set of addresses into an array of strings that describe the address symbolically. Returns the address of the array of string pointers. This array is malloc()ed by backtrace_symbols(), and must be freed by the caller. (NOTE: The individual strings pointed to by the array of pointers need not and should not be freed.)
#) Flag for backtrace with function name
Currently, the function name and offset can only be obtained on systems that use the ELF binary format for programs and libraries.
On other systems, only the hexadecimal return address will be present. It need to pass additional flags to the linker to make the function names available to the program. (For example, on systems using GNU ld, must pass '-rdynamic'. The flag '-export-dynamic' to the ELF linker, on targets that support it).
These flags instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of 'dlopen' or to allow obtaining backtraces from within a program.
NOTE: "static" means don't export the symbol. (For static function)
Example output:
./a.out(func2+0x30) [0x400884]
./a.out(func1+0x25) [0x400924]
./a.out(main+0x30) [0x400956]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x3c4a21ed1d]
./a.out() [0x400799]
Example output in case of 'static' function func1():
./a.out(func2+0x30) [0x400884]
./a.out() [0x400924]
./a.out(main+0x30) [0x400956]
/lib64/libc.so.6(__libc_start_main+0xfd) [0x3c4a21ed1d]
./a.out() [0x400799]
#) Alternative to obtain function name
Even 'addr2line' command can be used to map executable addresses to source code filename+line number. 'addr2line' with '-f' option to get function names as well.
Example output:
addr2line -e a.out -fCi 0x400924
func1
??:0