我在程序中的某个位置进行堆栈跟踪。使用 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);
答案 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
无法找到函数名称,我认为您的二进制文件已被删除)。