Name of a function defined in executable (using dladdr)

886 views Asked by At

I have a program (an application, not a shared library):

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();
}

I expect functionName to be "func" - the name of the function from which I make a call to unw_get_proc_name(). But unw_get_proc_name() fails. I've debugged it and found out that it uses a function dladdr() to get the name of a function:

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;
    }
  }

For some reason dyldInfo.dli_sname is 0. Why? How can I fix this?

I also use the function unw_get_proc_name() from a shared library and in this case it succeeds. So the question is why does it fail to retrieve a function name ("func" in the program above) when being called from an application (not a shared library)? And how can I fix it?

I tried to add attributes __attribute__((noinline)) and __attribute__((visibility("default"))) to my func() function, but it didn't help.

1

There are 1 answers

2
Paul Sanders On BEST ANSWER

My reading of the man page for dladdr is that it can only locate symbols located in shared objects, aka shared libraries. The relevant section reads (emphasis mine):

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

However, I found this link which suggests that linking with -Wl,-E might help, so you could try that.