我想以一种有效的方式包装库符号(即,创建一个调用原始功能的自定义覆盖(在我的二进制及其依赖的库两者上强制使用),无论我是静态链接库还是静态链接库)动态地。
如果我使用-Wl,--wrap
方法(gcc / clang),它可用于静态链接,但与动态链接一起使用不会使动态链接的库调用包装的符号。如果我创建了一个通过dlsym
调用原始函数的直接替代,则它确实会使相关的(动态)库使用包装的符号,但这需要我动态链接。
是否有一种方法可以同时使用两种链接?
下面的示例构建脚本演示了该问题:
#!/bin/sh -eu
cat > main.c <<EOF
#define _GNU_SOURCE
#include <stdio.h>
extern int puts_from_lib(void);
int nr_puts;
#if !DLSYM
//this only works with static linking
int __real_puts(char const*);
int __wrap_puts(char const*X)
{
__real_puts("OVERRIDE");
nr_puts++;
return __real_puts(X);
}
#else
//this only works with dynamic linking
#include <dlfcn.h>
int puts(char const *X)
{
int (*real_puts)(char const*)=(int(*)(char const*))dlsym(RTLD_NEXT,"puts");
real_puts("OVERRIDE");
nr_puts++;
return real_puts(X);
}
#endif
int main(int C, char **V)
{
printf("\\nV[0]=%s\n", V[0]);
puts("puts from main");
puts_from_lib();
printf("nr_puts = %d\\n", nr_puts);
}
EOF
cat > lib.c <<EOF
#include <stdio.h>
int puts_from_lib(void)
{
return puts("puts from lib");
}
EOF
mac=-DDLSYM
gcc -g -DDLSYM lib.c -c -fpic
gcc -g -DDLSYM main.c -c -fpic -o dmain.o
gcc -g main.c -c -fpic
gcc lib.o -o lib.so -shared
rm -f lib.a; ar rcs lib.a lib.o
gcc dmain.o $PWD/lib.so -o shared -ldl
gcc dmain.o lib.a -o static_with_dlsym -static -ldl
gcc main.o lib.a -Wl,--wrap=puts -o static -static
gcc main.o $PWD/lib.so -Wl,--wrap=puts -o broken_shared -ldl
./static
./shared
./broken_shared
./static_with_dlsym
构建脚本输出:
V[0]=./static
OVERRIDE
puts from main
OVERRIDE
puts from lib
nr_puts = 2
V[0]=./shared
OVERRIDE
puts from main
OVERRIDE
puts from lib
nr_puts = 2
V[0]=./broken_shared
OVERRIDE
puts from main
puts from lib
nr_puts = 1
Segmentation fault (core dumped)
发布的代码显示了__wrap_puts()的原型,但未定义例程。尝试创建与此类似的例程: