c - 如何使用 -rdynamic 链接器标志?

标签 c gcc glibc backtrace

我如何使用 -rdynamic 标志来确保 glibc 的回溯函数将报告回溯中的实际函数/符号名称?

我正在尝试使用 C's backtrace functions创建回溯。在我的 MacOS 机器上,如果我使用程序 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]

关于c - 如何使用 -rdynamic 链接器标志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48083494/

相关文章:

c - 使用内部 union 初始化结构体

c - 如何解决C程序中的 'undefined reference to'?

c - c中的运算是什么意思

python - 在 mac 上 easy_install lxml 不工作

linux - 枚举通过 dlopen(RTLD_GLOBAL) 加载的共享库

ubuntu - 无法打开链接描述文件 libgcc_s.so.1 : Too many open files

c - 数组不在 C 中存储/显示整个字符串

c - 使用 fork() 运行太多次来遍历目录的递归函数

linux - Linux 内核中的 likely/unlikely 宏是如何工作的,它们有什么好处?

c - 使用 sscanf 解析十进制字符串