Reputation: 166106
How can I use the -rdynamic
flag to ensure glibc's backtrace functions will report the actual function/symbol names in a backtrace?
I'm trying to use C's backtrace functions to create a backtrace. On my MacOS machine, if I use the program from this question
#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
static void full_write(int fd, const char *buf, size_t len)
{
while (len > 0) {
ssize_t ret = write(fd, buf, len);
if ((ret == -1) && (errno != EINTR))
break;
buf += (size_t) ret;
len -= (size_t) ret;
}
}
void print_backtrace(void)
{
static const char start[] = "BACKTRACE ------------\n";
static const char end[] = "----------------------\n";
void *bt[1024];
int bt_size;
char **bt_syms;
int i;
bt_size = backtrace(bt, 1024);
bt_syms = backtrace_symbols(bt, bt_size);
full_write(STDERR_FILENO, start, strlen(start));
for (i = 1; i < bt_size; i++) {
size_t len = strlen(bt_syms[i]);
full_write(STDERR_FILENO, bt_syms[i], len);
full_write(STDERR_FILENO, "\n", 1);
}
full_write(STDERR_FILENO, end, strlen(end));
free(bt_syms);
}
void foo()
{
print_backtrace();
}
int main()
{
foo();
return 0;
}
and then compile it, I end up with a program that outputs a stack trace including function names.
$ clang main.c
$ ./a.out
BACKTRACE ------------
1 a.out 0x0000000100c9fec9 foo + 9
2 a.out 0x0000000100c9fee4 main + 20
3 libdyld.dylib 0x00007fff9669f235 start + 1
----------------------
However, if I attempt to compile the program on an Ubuntu virtual machine using gcc, I get no function names.
$ gcc-5 main.c
$ ./a.out
BACKTRACE ------------
./a.out() [0x4008c3]
./a.out() [0x4008d4]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7fbc9fee2830]
./a.out() [0x400649]
----------------------
The aformentioned previous question says the -rdynamic flag is my savior, but when I try that flag I still don't get function names in my backtrace
$ gcc-5 -rdynamic main.c
$ ./a.out
BACKTRACE ------------
./a.out(foo+0x9) [0x400b63]
./a.out(main+0xe) [0x400b74]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f8cbbf20830]
./a.out(_start+0x29) [0x4008e9]
I'm a little overwhelmed at what to do next -- am I using the flag wrong? Or am I using it correctly and there's something else that might prevent the symbols from showing up in this simple program.
Upvotes: 1
Views: 1415
Reputation: 1
You could consider using Ian Taylor's libbacktrace (which is also part of recent GCC) for your backtracing goals. It wants the libraries and executables to be compiled with DWARF information (so you compile with -g
passed to gcc
, and that can be mixed with optimization flags like -O2
). But it gives more precise output (including line numbers for your call stack frames).
Upvotes: 2
Reputation: 166106
Per comments above, the -rdynamic
flag was working without issue. The problem was that clang on MacOS produced its output in a different format than GCC on my ubuntu VM.
The function name was there all along.
# notice the function name `foo`
./a.out(foo+0x9) [0x400b63]
Upvotes: 3