我正在尝试以下链接中提到的问题: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)();
  }

编译以上文件:



主看重复为:m

主看到重复的地址为:600ba0

动态将libdep中的重复项视为:d

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

libdep将重复项视为:m

libdep看到重复的地址为:600ba0

但是libdep从main看到重复的内容是:m

请参见,同一变量具有不同的地址。而且,如果我们从main.c中删除RTLD_DEEPBIND,则输出将如预期的那样。

主看重复为:m

主看到重复的地址为:600ba0

动态将libdep中的重复项视为:d

动态看到重复的地址为:600ba0

libdep将重复项视为:d

libdep看到重复的地址为:600ba0

但是libdep从main看到重复的内容是:d

所以我的问题是:

什么时候需要使用RTLD_DEEPBIND?

当没有变量d的定义时,dynamic.so如何具有重复变量的不同地址?

(我在gcc 4.2.2和gcc 4.8.2上尝试过)

最佳答案

当您要确保在加载的库中查找的符号在库中及其相关性之前开始时,应使用RTLD_DEEPBIND,然后在全局命名空间中查找符号。

这使您可以在库中使用与全局 namespace 中可用的命名符号相同的名称,因为另一个库具有相同的定义。这可能是错误的或引起问题。

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



至于第二个问题-我们怎么会看到重复的地址不同-那么,这是您构建主应用程序而没有-fPIC选项的一个奇妙功能。如果我们在主应用程序上使用readelf -r,则该行的内容为:

000000600d08  001000000005 R_X86_64_COPY     0000000000600d08 duplicate + 0

请注意,这末尾有_COPY。这意味着当在libdep.so中找到该符号时,它将复制到中,并将复制到该地址的主可执行文件的初始数据段中。然后查找对duplicate中的libdep.so的引用,它指向主可执行文件中符号的拷贝。
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文件中的拷贝。

09-28 05:55