1

我在使用 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. 主程序

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

  5. gcc -o 主 -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 它促进的main:加载共享库时出错:libtest.so。无法打开共享对象文件:没有这样的文件或目录。

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

4

2 回答 2

1

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

现在构建您的默认 libtest.so 并证明nm -B您希望拦截的符号是动态链接的。

现在将 main.c 构建到 main.o 中,然后检查 main.onm以查看它对符号的外部未满足的链接要求。

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

...

现在您开始创建 LD_PRELOAD 版本。

你应该叫这个libtest2.so。您不使用-ltest2

关键是构建的人./main根本不知道 libtest2.so,没有硬链接依赖。

libtest2.so 具有替代行为,例如 make foo() 返回不同的字符串/数字),现在的目标是在运行时拦截此第二个版本,因此默认情况下(或根本不调用)第一个版本。通过使用 LD_PRELOAD 环境。

LD_PRELOAD=./libtest2.so ./main

...

祝你好运。

于 2016-02-20T15:21:28.240 回答
0

我将DSO复制并重命名为libtest2.so并将LD_PRELOAD重置为重命名的DSO(使用绝对路径),它还提示找不到libtest.so。

我认为它提示的原因是无法加载用于硬依赖的libtest.so。

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

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

感谢您的帮助@Darryl Miles

于 2016-02-25T13:43:39.620 回答