0

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

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() 函数中,但它没有帮助。

4

1 回答 1

1

我对手册页的dladdr阅读是它只能定位位于共享对象(即共享库)中的符号。相关部分内容为(强调我的):

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

但是,我发现这个链接表明链接-Wl,-E可能会有所帮助,所以你可以尝试一下。

于 2019-03-25T13:52:21.943 回答