0

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.

embedc
  • 1,485
  • 1
  • 6
  • 20

1 Answers1

1

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.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • Thank you very much! That works! But the problem is that the return name is mangled. Is it somehow possible to demangle it (programmatically)? – embedc Apr 03 '19 at 11:30
  • Apparently, you can call `abi::__cxa_demangle`, as described [here](https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html) – Paul Sanders Apr 03 '19 at 12:13