c - 当 dlopen one 时,它​​的符号没有被主符号覆盖,为什么?

标签 c linux compiler-errors ld

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();
}

ma​​in.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=symbols),它开始于:

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

如果我将 -lc2 或 -rdynamic 添加到 gcc main cmd ,它将生成:

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 的,我相信这是正确的。它在 a.out 中寻找 pixman,然后是 libc2.so,依此类推。

为什么在没有-rdynamic 和-lc2 的情况下在a.out 中查找符号却得不到结果并继续搜索libc2.so? rdynamic 选项将所有符号加载到动态符号表——而不仅仅是它认为使用的符号(lc2 具有相同的效果)。当您加载所有这些符号时,就会发生冲突——pixman 函数。在这种情况下使用 main.c 实现。正如其他人所指出的,这可能会产生警告。

关于c - 当 dlopen one 时,它​​的符号没有被主符号覆盖,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27339604/

相关文章:

c - gcc 警告 volatile 双数组

C int数组与指针交互

c - 在C中搜索子字符串的位置时如何允许字符串中存在空格?

c - 为什么 qsort 中的排序方法改变了我的数组?

linux - 如何绕过 Linux "Too Many Arguments"限制

linux - 在ubuntu上使用人机界面驱动程序

C# 错误 : Unassigned local variable error when using "switch"?

c++ - 为什么我会从 'int'到 'int*'的无效转换错误以及其他错误?

java - 这样做的正确方法是什么?初始化/符号未找到错误

c - 如何定位类型和变量首次使用 gdb 声明的位置