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

Name of a function defined in executable (using 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() 函数,但没有帮助。

我对 man page for dladdr 的理解是它只能定位位于共享对象(即共享库)中的符号。相关部分显示(强调我的):

The function dladdr() determines whether the address specified in addr is located in one of the shared objects loaded by the calling application.

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