加载了 LD_PRELOAD 的库是否会在最后卸载

Will libraries loaded with LD_PRELOAD be unload in the last

我正在写一个内存泄漏跟踪器,想在库卸载时打印被跟踪程序中的统计消息。

这个库将与LD_PRELOAD技巧一起使用,我们的程序有静态变量会很晚才被销毁,所以我想确保统计消息将在所有静态变量之后打印为避免误报,程序已被销毁

加载了 LD_PRELOAD 的库会在最后卸载(晚于被黑程序)吗?

Will libraries loaded with LD_PRELOAD be unload in the last

您假设 LD_PRELOADED 库将被卸载,但完全不能保证一定会发生。

这是一个测试用例:

// main.c
#include <unistd.h>

int main(int argc, char *argv[]) {
  if (argc > 1) _exit(0);
  return 0;
}

// preload.c
#include <stdio.h>

__attribute__((constructor)) void init() { fprintf(stderr, "Init\n"); }
__attribute__((destructor)) void fini() { fprintf(stderr, "Fini\n"); }

像这样构建它们:

gcc main.c && gcc -fPIC -shared -o preload.so preload.c

现在观察初始化和结束的顺序:

LD_DEBUG=files LD_PRELOAD=./preload.so ./a.out |& grep 'calling .*ini'
     18310:     calling init: /lib/x86_64-linux-gnu/libc.so.6
     18310:     calling init: ./preload.so
     18310:     calling fini: ./a.out [0]
     18310:     calling fini: ./preload.so [0]

LD_DEBUG=files LD_PRELOAD=./preload.so ./a.out 1 |& grep 'calling .*ini'
     18312:     calling init: /lib/x86_64-linux-gnu/libc.so.6
     18312:     calling init: ./preload.so

请注意,在 _exit() 的情况下,库根本没有完成。

另请注意,任何共享库将依赖于libc.so.6,因此将在之前完成libc.so.6.

但是缺少信号或 _exit() 终止,是的:库将以其初始化的相反顺序完成(加载和卸载并不是这里使用的正确术语),这确实意味着LD_PRELOADed 库将最后完成。