一、preload 失效原因
1. RTLD_DEEPBIND 的使用
来自于:http://linux.die.net/man/3/dlopen
RTLD_DEEPBIND(自 glibc 2.3.4 起)将此库中符号的查找范围置于全局范围之前。这意味着自包含库将优先使用其自己的符号,而不是已加载库中包含的具有相同名称的全局符号。该标志未在 POSIX.1-2001 中指定。
可以使用 LD_DEBUG=all
查看链接的过程
2. 通过静态链接的方式
使用 gcc -static
参数可以把 libc.so
静态链接进执行程序中。但这也就意味着程序不再支持动态链接。
3. 设置执行文件的 setgid/setuid 权限
在有 SUID 权限的执行文件,系统会忽略 LD_PRELOAD 环境变量
4. 内联方式
编译器可能会某些函数进行了内联优化,并不会调用 so 库中的函数,因而通过优先加载自定义动态库的方式不可行。比如:strcmp 函数
一种解决方案:可以在编译测试程序时,添加 -fno-builtin-strcmp
关闭 strcmp 函数的优化
5. 链接库的顺序
当使用 dlsym 的 RTLD_NEXT 时,需要注意链接库的顺序。ld-linux 链接器也有 malloc、free 的实现,可能会存在 dlsym 查看到 ld-linux 内部实现的符号。
1 | void* func = dlsym(RTLD_NEXT, "malloc"); |
如果我们发现一个函数在 ld-linux 中,这时,没有直接的办法可以继续在所有其他库中搜索相同的函数名称。但是,如果您知道函数所在的特定库的名称,比如 libc.so 。则可以使用 dlopen 和 dlsym 来获取所需的指针。
1 | void* handle = dlopen("libc.so.6", RTLD_LAZY); |