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
) ?
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'