当我们应该使用RTLD_DEEPBIND? [英] When we are supposed to use RTLD_DEEPBIND?

查看:286
本文介绍了当我们应该使用RTLD_DEEPBIND?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

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

int duplicate ='u';

int get_duplicate(){
printf(libdep看到重复为:%c\\\
,重复);
printf(libdep将重复地址视为:%x\\\
,& duplicate);
返回重复;
}
----------------------------------------- ---------------------------------------------

>> Cat dynamic.c

#include< stdio.h>

extern int duplicate;

int run(){
duplicate ='d';
printf(动态将libdep复制为:%c\\\
,重复);
printf(动态将重复地址视为:%x\\\
,& duplicate);

printf(但是libdep从main看到重复为:%c\\\
,get_duplicate());
返回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(主要看到重复为:%c\\\
,重复);
printf(main看到重复地址为:%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

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



动态看到从libdep复制为:d



dynamic将重复地址视为:5f4fb868



libdep将重复为:m



libdep将重复地址视为:600ba0



但libdep将重复地址显示为:m



请参阅相同的变量具有不同的地址。如果我们从main.c中删除RTLD_DEEPBIND,则输出如预期。



主要看到重复为:m



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



动态视为从libdep复制为:d



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



libdep看到重复为:d



libdep看到重复地址as:600ba0



但libdep从main看到重复为:d



所以我的问题是:



当我们需要使用RTLD_DEEPBIND吗?



<重复变量的地址,甚至没有定义变量d?



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

解决方案您应该使用 RTLD_DEEPBIND 来确保符号在加载库在库中启动,它是依赖关系b查找全局名称空间中的符号。



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



使用它的一个例子在 intel共享数学函数页面


当在Linux *上创建静态链接到Intel运行时库的共享库时(例如,使用-static-intel选项),期望应用程序将运行优化版本函数来自Intel提供的静态链接到共享库的函数库。例如,预计对像cos()这样的数学函数的调用会解析为libimf,这是英特尔提供的包含优化数学函数的数学库。在Linux上,默认行为是将符号解析为这些例程的GNU libm版本。


至于第二个问题 - 我们会看到重复的地址 - 这是您构建主应用程序而没有 -fPIC 选项的一个很棒的功能。如果我们在主应用程序中使用 readelf -r ,它有一行内容:

  000000600d08 001000000005 R_X86_64_COPY 0000000000600d08 duplicate + 0 

请注意这有 _COPY最后。这意味着当在 libdep.so 中找到该符号时,它将复制复制到该地址的主要可执行文件的初始数据段中。然后查找 libdep.so 中对 duplicate 的引用,它指向位于
$ b $ libdep.so 中的定义如下所示:

  0000002009b8 000e00000006 R_X86_64_GLOB_DAT 00000000002009f8重复+ 0 

GLOB_DAT - 全局数据。



当您加载 dynamic.so ,它有它自己的符号请求。因为使用 RTLD_DEEPBIND ,所以在查看主可执行文件之前,首先在该库的依赖关系中查找此定义。因此,它会从 libdep.so 中查找并使用公开的GLOB_DAT,而不是从 a.out



这是直接造成的链接到 libdep.so 作为编译 dynamic.so 。如果你没有链接到它,那么你会看到带有其他地址的符号 - 即主要exe文件中的副本。


I was trying the issue mentioned at link: https://sourceware.org/ml/libc-alpha/2009-06/msg00168.html

I did some modification in the code as mentioned below:

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

Compiling the above files:

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 sees duplicate as: m

main sees duplicate address as: 600ba0

dynamic sees duplicate from libdep as: d

dynamic sees duplicate address as: 5f4fb868

libdep sees duplicate as: m

libdep sees duplicate address as: 600ba0

but libdep sees duplicate from main as: m

See that the same variable has different addresses. And if we remove the RTLD_DEEPBIND from the main.c, the output is as expected.

main sees duplicate as: m

main sees duplicate address as: 600ba0

dynamic sees duplicate from libdep as: d

dynamic sees duplicate address as: 600ba0

libdep sees duplicate as: d

libdep sees duplicate address as: 600ba0

but libdep sees duplicate from main as: d

So My questions are:

When we have the need to use RTLD_DEEPBIND?

How come dynamic.so has different address of duplicate variable when it didn't even had the definition of variable d?

( I tried on gcc 4.2.2 and gcc 4.8.2)

解决方案

You should use RTLD_DEEPBIND when you want to ensure that symbols looked up in the loaded library start within the library, and it's dependencies before looking up the symbol in the global namespace.

This allows you to have the same named symbol being used in the library as might be available in the global namespace because of another library carrying the same definition; which may be wrong, or cause problems.

An example of a reason to use it is mentioned on the 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.

As to the second question - how come we see a different address of the duplicate - well that's a wonderful feature of you building the main application without the -fPIC option. If we use readelf -r on the main application it has a line reading:

000000600d08  001000000005 R_X86_64_COPY     0000000000600d08 duplicate + 0

Note that this has _COPY at the end. This means that when the symbol is found in libdep.so, it gets copied into the initial data segment of the main executable at that address. Then the reference to duplicate in libdep.so is looked up and it points to the copy of the symbol that's in the main executable.

The definition in libdep.so looks like:

0000002009b8  000e00000006 R_X86_64_GLOB_DAT 00000000002009f8 duplicate + 0

i.e. GLOB_DAT - global data.

When you load the dynamic.so, it has it's own request for the symbol. Because you use RTLD_DEEPBIND this definition is looked up in the dependencies of this library first, before looking in the main executable. As a result, it finds and uses the exposed GLOB_DAT from libdep.so and not the exposed data from a.out.

This is directly caused by linking to libdep.so as part of the compilation of dynamic.so. If you hadn't linked to it, then you would see the symbol with the other address - i.e. the copy in the main exe.

这篇关于当我们应该使用RTLD_DEEPBIND?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆