一个linux进程似乎使用dlclose卸载了一个共享库,同时仍然将其函数注册为回调。当回调被调用时,它会崩溃,现在它是无效的内存,gdb因此无法展开堆栈。除了应用程序在加载时显式地存储共享库的列表之外,是否有一种方法可以从核心转储中获得卸载的库的加载地址(至少是通过dlopen加载的库)?
dlclose
dlopen
vecaoik11#
有没有一种方法可以从核心转储中获取已卸载的库的加载地址没有。core是崩溃时进程的内存映像,关于卸载的库的信息 * 不再存在 *-运行时加载器没有理由保留这些信息。但是,你可能会猜到。假设你的代码看起来像这样:
core
void *h = dlopen("somelib.so", ...); some_struct.callback = (int(*)(void)) dlsym(h, "some_func"); dlclose(h); // Oops. some_struct.callback will crash if called
在core dump / GDB中,您应该知道.callback的值。假设它是p == 0x7f...1234。您还知道libsomelib.so中some_func的地址addr(来自nm libsomelib.so | grep some_func)。然后加载地址是p - addr,您可以使用GDB add-symbol-file /path/to/libsomelib.so load_address让GDB知道libsomelib.so的位置。但是请注意,GDB需要的load_address是 * 而不是 * p - addr;是p - addr + &.text-in-libsomelib.so您可以使用readelf -WS libsomelib.so | grep '\.text'查找.text的地址
.callback
p == 0x7f...1234
libsomelib.so
some_func
addr
nm libsomelib.so | grep some_func
p - addr
add-symbol-file /path/to/libsomelib.so load_address
load_address
p - addr + &.text-in-libsomelib.so
readelf -WS libsomelib.so | grep '\.text'
.text
1条答案
按热度按时间vecaoik11#
有没有一种方法可以从核心转储中获取已卸载的库的加载地址
没有。
core
是崩溃时进程的内存映像,关于卸载的库的信息 * 不再存在 *-运行时加载器没有理由保留这些信息。但是,你可能会猜到。
假设你的代码看起来像这样:
在
core
dump / GDB中,您应该知道.callback
的值。假设它是p == 0x7f...1234
。您还知道
libsomelib.so
中some_func
的地址addr
(来自nm libsomelib.so | grep some_func
)。然后加载地址是
p - addr
,您可以使用GDBadd-symbol-file /path/to/libsomelib.so load_address
让GDB知道libsomelib.so
的位置。但是请注意,GDB需要的
load_address
是 * 而不是 *p - addr
;是p - addr + &.text-in-libsomelib.so
您可以使用readelf -WS libsomelib.so | grep '\.text'
查找.text
的地址