libc的backtrace_symbols()和libunwind的unw_get_proc_name()中的不同偏移量

时间:2015-01-07 09:47:11

标签: stack-trace libc backtrace libunwind

我在程序中的某个位置进行堆栈跟踪。使用 libc backtrace_symbols()功能一次,使用 libunwind unw_get_proc_name()一次。

backtrace_symbols()输出:

/home/jj/test/mylib.so(+0x97004)[0x7f6b47ce9004]

unw_get_proc_name()输出:

ip: 0x7f6b47ce9004, offset: 0x458e4

在这里您可以看到指令指针地址(0x7f6b47ce9004)是相同且正确的。来自 backtrace_symbols()的函数偏移0x97004也正确但我从 unw_get_proc_name()({{1> }})。

是否有人知道这里发生了什么以及可能导致抵消差异的原因?

两种方法都使用类似的代码,如下例所示:

回溯():

0x458e4

libunwind:

void *array[10];
size_t size;

size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);

1 个答案:

答案 0 :(得分:1)

我认为unw_get_proc_name计算来自未命名内部框架的偏移量。

例如:

void f() {
   int i;
   while (...) {
     int j;
   }
}

请注意,循环块内部有一个变量声明。在这种情况下(并且取决于优化级别),编译器可以为循环创建帧(以及相关的展开信息)。因此,unw_get_proc_name计算此循环的偏移量而不是函数的开始值。

这在unw_get_proc_name手册页中解释:

  

请注意,在某些平台上没有可靠的区分方法   程序名称和普通标签之间。此外,如果符号   信息已从程序中删除,程序名称可能是   完全不可用或可能仅限于通过   动态符号表。在这种情况下,unw_get_proc_name()可能会返回   标签名称或前面(附近)程序。

您可以尝试再次测试但不剥离二进制文件(因为unw_get_proc_name无法找到函数名称,我认为您的二进制文件已被删除)。