Search code examples
c++linuxshared-librariesglibccoredump

Retrieve load address of unloaded shared library from linux core dump


A linux process appears to unload a shared library using dlclose while still having its functions registered as callbacks. It crashes later when the callback is called which is now invalid memory, and gdb can't unwind the stack because of it.

Short of the application explicitly storing a list of shared libraries as they are loaded, is there a way to get from the core dump the load addresses for libraries that were unloaded (at least ones loaded via dlopen) ?


Solution

  • is there a way to get from the core dump the load addresses for libraries that were unloaded

    No. The core is an in-memory image of the process at the time of the crash, and the info about libraries that were unloaded is no longer there -- there is no reason for the runtime loader to keep that info around.

    However, you can probably guess it.

    Suppose your code looks like this:

      void *h = dlopen("somelib.so", ...);
      some_struct.callback = (int(*)(void)) dlsym(h, "some_func");
      dlclose(h);  // Oops. some_struct.callback will crash if called
    

    In the core dump / GDB you should know the value of .callback. Let's say it's p == 0x7f...1234.

    You also know the address addr of some_func in libsomelib.so (from nm libsomelib.so | grep some_func).

    The load address is then p - addr, and you can use GDB add-symbol-file /path/to/libsomelib.so load_address to let GDB know where libsomelib.so used to be.

    Note however, that the load_address GDB wants is not p - addr; it's p - addr + &.text-in-libsomelib.so. You can find the address of .text with readelf -WS libsomelib.so | grep '\.text'