gpt4 book ai didi

c++ - 我们什么时候应该使用 RTLD_DEEPBIND?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:35:23 25 4
gpt4 key购买 nike

我正在尝试链接中提到的问题:https://sourceware.org/ml/libc-alpha/2009-06/msg00168.html

我对代码做了一些修改,如下所述:

>> Cat libdep.c
#include <stdio.h>

int duplicate = 'u';

int get_duplicate() {
printf("libdep sees duplicate as: %c\n", duplicate);
printf("libdep sees duplicate address as: %x\n", &duplicate);
return duplicate;
}
--------------------------------------------------------------------------------------

>> Cat dynamic.c

#include <stdio.h>

extern int duplicate;

int run() {
duplicate = 'd';
printf("dynamic sees duplicate from libdep as: %c\n", duplicate);
printf("dynamic sees duplicate address as: %x\n", &duplicate);

printf("but libdep sees duplicate from main as: %c\n", get_duplicate());
return 0;
}
-------------------------------------------------------------------------------------------------

Cat main.c

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

extern int duplicate;

int main() {
void *h;
int (*run)();

duplicate = 'm';

printf("main sees duplicate as: %c\n", duplicate);
printf("main sees duplicate address as: %x\n", &duplicate);

h = dlopen("./dynamic.so", RTLD_LAZY | RTLD_DEEPBIND);
if (!h)
abort();

run = dlsym(h, "run");
if (!run)
abort();

(*run)();
}

编译以上文件:

gcc -ggdb3 -shared -fPIC libdep.c -o libdep.so

gcc -ggdb3 -shared -fPIC dynamic.c -Wl,-rpath,. -L. -ldep -o dynamic.so

gcc -ggdb3 main.c -Wl,-rpath,. -L. -ldep –ldl

./a.out

main 认为重复为:m

main 看到重复地址为:600ba0

dynamic 将 libdep 中的拷贝视为:d

动态看到重复地址为:5f4fb868

libdep 将重复视为:m

libdep 将重复地址视为:600ba0

但是 libdep 从 main 中看到重复项:m

看到同一个变量有不同的地址。如果我们从 main.c 中删除 RTLD_DEEPBIND,则输出符合预期。

main 认为重复为:m

main 看到重复地址为:600ba0

dynamic 将 libdep 中的拷贝视为:d

动态将重复地址视为:600ba0

libdep 将重复视为:d

libdep 将重复地址视为:600ba0

但是 libdep 从 main 中看到重复项:d

所以我的问题是:

什么时候我们有需要使用RTLD_DEEPBIND?

为什么 dynamic.so 连变量 d 的定义都没有,却有不同的重复变量地址?

(我试过 gcc 4.2.2 和 gcc 4.8.2)

最佳答案

当您要确保在加载的库中查找的符号在全局命名空间中查找符号之前在库及其依赖项中开始时,您应该使用 RTLD_DEEPBIND

这允许您在库中使用与可能在全局命名空间中可用的相同命名符号,因为另一个库带有相同的定义;这可能是错误的,或导致问题。

intel shared math functions page 中提到了使用它的原因示例

When one creates a shared library on Linux* that links in the Intel runtime libraries statically (for example, using the -static-intel option), the expectation is that the application will run the optimized version of functions from the Intel-provided libraries, which are statically linked to the shared library. For example, it is expected that calls to math functions like cos() resolve to libimf, the Intel-provided math library which contains optimized math functions. On Linux, the default behavior is to resolve the symbol to the GNU libm version of these routines.

关于第二个问题 - 我们怎么会看到重复的不同地址 - 这是你构建主应用程序的一个很棒的功能没有 -fPIC 选项.如果我们在主应用程序上使用 readelf -r,它有一行内容:

000000600d08  001000000005 R_X86_64_COPY     0000000000600d08 duplicate + 0

请注意,这在末尾有 _COPY。这意味着当在 libdep.so 中找到该符号时,它会被复制到位于该地址的主要可执行文件的初始数据段中。然后在 libdep.so 中查找对 duplicate 的引用,它指向主可执行文件中符号的拷贝。

libdep.so 中的定义如下:

0000002009b8  000e00000006 R_X86_64_GLOB_DAT 00000000002009f8 duplicate + 0

GLOB_DAT - 全局数据。

当您加载 dynamic.so 时,它有自己的符号请求。因为您使用了 RTLD_DEEPBIND,所以首先在这个库的依赖项中查找这个定义,然后再查看主可执行文件。因此,它找到并使用来自 libdep.so 的公开 GLOB_DAT,而不是来自 a.out 的公开数据。

这是 直接 由链接到 libdep.so 作为 dynamic.so 编译的一部分引起的。如果您没有链接到它,那么您会看到带有其他地址的符号 - 即主 exe 中的拷贝。

关于c++ - 我们什么时候应该使用 RTLD_DEEPBIND?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com