从Linux核心转储中检索已卸载共享库的加载地址

pnwntuvh  于 2023-05-16  发布在  Linux
关注(0)|答案(1)|浏览(137)

一个linux进程似乎使用dlclose卸载了一个共享库,同时仍然将其函数注册为回调。当回调被调用时,它会崩溃,现在它是无效的内存,gdb因此无法展开堆栈。
除了应用程序在加载时显式地存储共享库的列表之外,是否有一种方法可以从核心转储中获得卸载的库的加载地址(至少是通过dlopen加载的库)?

vecaoik1

vecaoik11#

有没有一种方法可以从核心转储中获取已卸载的库的加载地址
没有。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.sosome_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的地址

相关问题