libp2.c
#include <stdio.h>
void pixman()
{
printf("pixman in libp1\n");
}
libc2.c
#include <stdio.h>
void pixman();
void cairo()
{
printf("cairo2\n");
pixman();
}
main.c
#include <stdio.h>
#include <dlfcn.h>
void pixman()
{
printf("pixman in main\n");
}
int main()
{
pixman();
void* handle=NULL;
void (*callfun)();
handle=dlopen("/home/zpeng/test/so_test/libc2.so",RTLD_LAZY);
callfun = (void(*)())dlsym(handle, "cairo");
callfun();
...
}
编译
gcc -c libp2.c -fPIC -olibp2.o
rm libp2.a
ar -rs libp2.a libp2.o
gcc -shared -fPIC libc2.c ./libp2.a -o libc2.so
gcc main.c -ldl -L. -g
结果:
pixman in main
cairo2
pixman: libp2
为什么最后一个不是“pixman in main”?
我看到了符号处理(LD_DEBUG =符号),它开始于:
21180: symbol=pixman; lookup in file=./a.out
21180: symbol=pixman; lookup in file=/lib64/libdl.so.2
21180: symbol=pixman; lookup in file=/lib64/tls/libc.so.6
21180: symbol=pixman; lookup in file=/lib64/ld-linux-x86-64.so.2
21180: symbol=pixman; lookup in file=/home/zpeng/test/so_test/libc2.so
如果我在gcc main cmd中添加-lc2或-rdynamic,它将生成:
pixman in main
cairo2
pixman in main
我的问题:
为什么在没有-rdynamic和-lc2的情况下在a.out中查找符号但没有得到结果并继续搜索libc2.so?
最佳答案
为什么最后一个不是“pixman in main”?
这是因为共享库具有自己的全局偏移表或GOT。在libc2.so中使用cairo函数时,将被调用的pixman函数与最初编译.so文件时解析的函数相同。
那是:
# creates object file only -- contains first pixman implementation
gcc -c libp2.c -fPIC -olibp2.o
# just turns the object file into an archive
ar -rs libp2.a libp2.o
# creates the .so file -- all symbols in libc2.c are resolved here
# and you passed in the .a file for that purpose. The .a file containing the
# first pixman implementation gets put in libc2.so.
gcc -shared -fPIC libc2.c ./libp2.a -o libc2.so
此后,使用libc2.so的任何人都将获得存储在libc2.so中的副本。我认为您发布的查询顺序是正确的。它在a.out中查找pixman,然后在libc2.so中查找,依此类推。
为什么在没有-rdynamic和-lc2的情况下在a.out中查找符号但没有得到结果并继续搜索libc2.so?
rdynamic选项将所有符号加载到动态符号表中,而不仅仅是使用它认为的符号(lc2具有相同的效果)。加载所有这些符号时,您会遇到冲突-pixman函数。在这种情况下,使用main.c实现。正如其他人指出的那样,这可能会产生警告。
关于c - 当dlopen这样的时候,它的符号没有被主符号覆盖,为什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27339604/