在可执行文件中定义的函数名称(使用dladdr)

时间:2019-03-25 12:36:44

标签: c++ linux dll symbol-table dladdr

我有一个程序(一个应用程序,而不是一个共享库):

void func() {
    int RESULT = UNW_ESUCCESS;
    unw_context_t context;
    unw_getcontext(&context);

    unw_cursor_t cursor;
    RESULT = unw_init_local(&cursor, &context);
    assert(RESULT == UNW_ESUCCESS);

    const int BUFFER_SIZE = 512;
    char functionName[BUFFER_SIZE] = {"<unknown>"};
    unw_word_t offset;
    RESULT = unw_get_proc_name(&cursor, functionName, BUFFER_SIZE, &offset);
}

int main() {
    func();
}

我希望functionName为“ func”-我从中调用unw_get_proc_name()的函数的名称。但是unw_get_proc_name()失败。我已经对其进行调试,发现它使用函数dladdr()来获取函数名称:

Dl_info dyldInfo;
if (dladdr((void *)addr, &dyldInfo)) {
    if (dyldInfo.dli_sname != NULL) {
      snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
      *offset = (addr - (pint_t) dyldInfo.dli_saddr);
      return true;
    }
  }

由于某种原因,dyldInfo.dli_sname为0。为什么?我该如何解决?

我还使用共享库中的函数unw_get_proc_name(),在这种情况下,它会成功。因此,问题是为什么当从应用程序(而不是共享库)中调用函数名时,为什么无法检索函数名(上述程序中的“ func”)?我该如何解决?

我试图将属性__attribute __((noinline))和__attribute __(( visibility (“ default”)))添加到func()函数,但这没有帮助。

1 个答案:

答案 0 :(得分:1)

我对man page for dladdr的理解是,它只能定位位于共享库(也称为共享库)中的符号。相关部分内容如下(强调我的意思):

  

函数dladdr()确定在addr中指定的地址是否位于调用应用程序加载的共享对象之一中。

但是,我发现this link暗示与-Wl,-E的链接可能会有所帮助,因此您可以尝试一下。