无法加载 LD_PRELOAD 指定的库

lib specified by LD_PRELOAD can not be loaded

我在使用 LD_PRELOAD 加载我的 so 时遇到了一些问题。

步骤如下:

  1. libtest.c:

    void fun()
    {
        return 
    }
    
  2. gcc -o libtest.so libtest.c -fPIC --shared

  3. 导出LD_PRELOAD=pwd/libtest.so

  4. main.c

    extern void fun(); void main() { fun() }

  5. gcc -o main -L。 main.c-ltest

  6. 然后ldd main

    ldd main linux-vdso.so.1=>(0x00007ffff7ffd000) /home/shiyanlou/Code/libtest.so(0x00007ffff7df9000) libtest.so=>not found libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6 (0x00007ffffa29000) /lib64/ld-linux-x86-64.so.2 (0x0000555555554000)

  7. 执行主程序./main 它促进: 加载共享 library:libtest.so 时出错。无法打开共享对象 file:No 这样的文件或目录。

不知为什么导出LD_PRELOAD变量后提示找不到libtest.so。但是,我也尝试使用 LD_PRELOAD 指定不同的共享库(而不是 "libc.so")来注入 malloc 函数,它有效! 为什么LD_PRELOAD只适用于链接时未使用的共享库???

您需要创建 2 个版本的 *.so。一个具有默认行为并通过“-ltest”加载和硬 linked。

现在构建您的默认 libtest.so 并用 nm -B 证明您期望拦截的符号是动态 linked.

现在将 main.c 构建到 main.o,然后检查 main.o 和 nm 也可以看到它在符号上有一个 extern unsatisfied linkage 要求.

现在 link ./main 与 main.o 和 libtest.so 然后 运行 它。 默认情况下,./main 需要使用此副本 运行,演示默认行为,并通过 ldd 命令显示正确 DSO 的正确路径。

...

现在您开始创建 LD_PRELOAD 版本。

你应该称之为libtest2.so。您不使用 -ltest2

关键是建造 ./main 的人根本不知道 libtest2.so,没有硬性 link 年龄依赖性。

libtest2.so 具有替代行为,例如使 foo() returns 不同 string/number),现在的目标是在 运行 时拦截此第二个版本,所以默认情况下(或根本不调用)第一个版本。通过使用 LD_PRELOAD 环境。

LD_PRELOAD=./libtest2.so ./main

...

祝你好运。

我把DSO复制重命名为libtest2.so,将LD_PRELOAD重置为重命名后的DSO(带绝对路径),同样提示找不到libtest.so。

我认为之所以会提示,是因为硬依赖的libtest.so无法加载。

也就是说LD_PRELOAD已经加载了,但是硬依赖无法满足,所以也无法执行./main

现在我可以得出结论,执行./main时,必须满足硬依赖DSO,因为每一个硬依赖DSO也必须加载(虽然这个DSO应该被完全替换!),否则会提示DSO可以找不到!

感谢@Darryl Miles 的帮助