【问题标题】:Different offset in libc's backtrace_symbols() and libunwind's unw_get_proc_name()libc 的 backtrace_symbols() 和 libunwind 的 unw_get_proc_name() 中的不同偏移量
【发布时间】:2015-01-07 09:47:11
【问题描述】:

我在我的程序中的某个时刻进行了堆栈跟踪。一次使用 libcbacktrace_symbols() 函数,一次使用 libunwindunw_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() (0x458e4) 得到的偏移量。

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

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

回溯():

void *array[10];
size_t size;

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

libunwind:

unw_cursor_t    cursor;
unw_context_t   context;

unw_getcontext(&context);
unw_init_local(&cursor, &context);

while (unw_step(&cursor) > 0) {
    unw_word_t  offset, pc; 
    char        fname[64];

    unw_get_reg(&cursor, UNW_REG_IP, &pc);

    fname[0] = '\0';
    (void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset);

    printf ("%p : (%s+0x%x) [%p]\n", pc, fname, offset, pc);
}

【问题讨论】:

  • 您没有检查来自 unw_get_proc_name 的返回值。也许它不成功并返回错误代码?似乎没有,但海事组织你仍然应该这样做。此外,您没有显示 backtrace() 的 printf。用于 libunwind 的可能表明您的 printfs 标记错误。

标签: stack-trace libc backtrace libunwind


【解决方案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 无法找到函数名称,我认为您的二进制文件已被剥离)。

【讨论】:

  • 在文档中看到这句话,它是有道理的。但是为什么 backtrace() 能够计算真正的偏移量呢?在我看来,我的问题与另一个原因有关。
  • 嗯...我终于问自己同样的问题... :-( 我唯一确定的是在 i386/x86_64 上,无论是回溯(使用 libgcc_s.so)还是 libunwind 依赖关于.eh_frame 信息。因此,这些差异来自libunwindlibgcc_s 的实现。虽然libunwind 明确暴露了问题,但我在libgcc_s.so 中找不到任何关于此的参考。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 1970-01-01
相关资源
最近更新 更多