当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《什么时候我们应该使用RTLD_DEEPBIND?》经验,为你挑选了1个好方法。

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

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

>> Cat libdep.c
#include 

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 

  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 
  #include 
  #include 

  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

动态从libdep看到副本为:d

dynamic将重复地址视为:5f4fb868

libdep将副本视为:m

libdep将重复地址视为:600ba0

但是libdep看到来自main的副本为:m

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

main看起来像副本:m

main看到重复地址为:600ba0

动态从libdep看到副本为:d

dynamic将重复地址视为:600ba0

libdep将副本视为:d

libdep将重复地址视为:600ba0

但是libdep看到来自main的副本为:d

所以我的问题是:

当我们需要使用RTLD_DEEPBIND时?

为什么dynamic.so在没有变量d的定义时有不同的重复变量地址?

(我试过gcc 4.2.2和gcc 4.8.2)



1> Petesh..:

RTLD_DEEPBIND当你想要确保在加载的库中查找符号时,你应该使用它,并且在查找全局命名空间中的符号之前它是依赖关系.

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

在intel共享数学函数页面上提到了使用它的原因的示例

当一个人在Linux*上创建一个静态链接在英特尔运行时库中的共享库(例如,使用-static-intel选项)时,期望应用程序将运行英特尔提供的库中的优化版本的函数,它们静态链接到共享库.例如,期望对诸如cos()之类的数学函数的调用解析为libimf,这是Intel提供的包含优化数学函数的数学库.在Linux上,默认行为是将符号解析为这些例程的GNU libm版本.

至于第二个问题-为什么我们看到重复的不同的地址-嗯,这是你构建的主要应用一个奇妙的功能,而不-fPIC选项.如果我们readelf -r在主应用程序上使用它有一个行读数:

000000600d08  001000000005 R_X86_64_COPY     0000000000600d08 duplicate + 0

请注意,这已经_COPY结束了.这意味着当找到符号时libdep.so,它将被复制到该地址的主可执行文件的初始数据段中.然后查找对duplicatein 的引用libdep.so,它指向主可执行文件中的符号副本.

定义libdep.so如下:

0000002009b8  000e00000006 R_X86_64_GLOB_DAT 00000000002009f8 duplicate + 0

GLOB_DAT- 全球数据.

加载时dynamic.so,它有自己的符号请求.因为RTLD_DEEPBIND在查看主可执行文件之前,首先在此库的依赖项中查找此定义.因此,它查找并使用公开的GLOB_DAT,libdep.so而不是公开的数据a.out.

这是直接由链接到libdep.so编译的一部分引起的dynamic.so.如果你没有链接到它,那么你会看到带有另一个地址的符号 - 即主exe中的副本.

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有