如何使用 -rdynamic 链接器标志?
How Do I use The -rdynamic Linker Flag?
如何使用 -rdynamic
标志来确保 glibc 的回溯函数将在回溯中报告实际的 function/symbol 名称?
我正在尝试使用 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;
}
然后编译它,我最终得到一个输出堆栈跟踪的程序,其中包括函数名称。
$ clang main.c
$ ./a.out
BACKTRACE ------------
1 a.out 0x0000000100c9fec9 foo + 9
2 a.out 0x0000000100c9fee4 main + 20
3 libdyld.dylib 0x00007fff9669f235 start + 1
----------------------
但是,如果我尝试使用 gcc 在 Ubuntu 虚拟机上编译程序,我将得不到任何函数名称。
$ 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]
----------------------
前面提到的问题说 -rdynamic 标志是我的救星,但是当我尝试那个标志时,我仍然没有在我的回溯中得到函数名称
$ 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]
我有点不知道接下来该做什么 -- 我是不是用错了旗帜?或者我是否正确使用了它,还有其他一些东西可能会阻止符号出现在这个简单的程序中。
根据上面的评论,-rdynamic
标志正常工作。问题是 MacOS 上的 clang 生成的输出格式与我的 ubuntu VM 上的 GCC 生成的输出格式不同。
函数名称一直存在。
# notice the function name `foo`
./a.out(foo+0x9) [0x400b63]
您可以考虑使用 Ian Taylor 的 libbacktrace (which is also part of recent GCC) for your backtracing goals. It wants the libraries and executables to be compiled with DWARF 信息(因此您可以使用传递给 gcc
的 -g
进行编译,并且可以与 -O2
等优化标志混合使用) .但它提供了更精确的输出(包括调用堆栈帧的行号)。
如何使用 -rdynamic
标志来确保 glibc 的回溯函数将在回溯中报告实际的 function/symbol 名称?
我正在尝试使用 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;
}
然后编译它,我最终得到一个输出堆栈跟踪的程序,其中包括函数名称。
$ clang main.c
$ ./a.out
BACKTRACE ------------
1 a.out 0x0000000100c9fec9 foo + 9
2 a.out 0x0000000100c9fee4 main + 20
3 libdyld.dylib 0x00007fff9669f235 start + 1
----------------------
但是,如果我尝试使用 gcc 在 Ubuntu 虚拟机上编译程序,我将得不到任何函数名称。
$ 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]
----------------------
前面提到的问题说 -rdynamic 标志是我的救星,但是当我尝试那个标志时,我仍然没有在我的回溯中得到函数名称
$ 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]
我有点不知道接下来该做什么 -- 我是不是用错了旗帜?或者我是否正确使用了它,还有其他一些东西可能会阻止符号出现在这个简单的程序中。
根据上面的评论,-rdynamic
标志正常工作。问题是 MacOS 上的 clang 生成的输出格式与我的 ubuntu VM 上的 GCC 生成的输出格式不同。
函数名称一直存在。
# notice the function name `foo`
./a.out(foo+0x9) [0x400b63]
您可以考虑使用 Ian Taylor 的 libbacktrace (which is also part of recent GCC) for your backtracing goals. It wants the libraries and executables to be compiled with DWARF 信息(因此您可以使用传递给 gcc
的 -g
进行编译,并且可以与 -O2
等优化标志混合使用) .但它提供了更精确的输出(包括调用堆栈帧的行号)。