如何使dloror()报告*所有*未解析的符号从dlopen()无法加载共享库?

时间:2013-03-26 22:41:42

标签: linux dlopen

我正在尝试从共享库上的dlopen()调用失败中报告所有未解析的符号。我已尝试将RTLD_LAZY和RTLD_NOW作为dlopen调用的标志。我知道共享库有10个丢失的符号(即如果你执行了静态链接g ++ blah blah:链接将失败并丢失10个符号)。我想让dlerror()在失败的负载期间告诉我所有10个丢失的符号。

有谁知道怎么哄这个发生?我从手册页看到dlerror()返回最后一个错误;所以也许我问得太多但是想知道是否有人知道。

非常感谢,

1 个答案:

答案 0 :(得分:4)

  

我想让dlerror()在失败的负载期间告诉我所有10个丢失的符号。

您不能:加载程序一旦发现无法加载库(即一旦发现第一个丢失的符号),就会报告错误。装载机没有任何意义可以继续下去,所以它没有。

但是,您可以使用ldd -rLD_PRELOAD来模拟LD_TRACE_LOADED_OBJECTS所做的事情,以获得完整的答案。例如:

$ cat main.c
#include <dlfcn.h>
#include <stdio.h>

int main()
{
  void *p = dlopen("./foo.so", RTLD_NOW);
  if (p == NULL) {
    printf("%s\n", dlerror());
    return 1;
  }
  return 0;
}


$ cat foo.c
int bar(), baz();  // not defined anywhere
int foo() {
  return bar() + baz();
}

$ gcc main.c -ldl; gcc -fPIC -shared -o foo.so foo.c

$ ./a.out
./foo.so: undefined symbol: baz  # only the first symbol is reported

$ ldd -r ./a.out
    linux-vdso.so.1 =>  (0x00007fff52ddc000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f158e48d000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f158e0ce000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f158e6b2000)

这不起作用,因为你的程序从未执行过,因此永远不会加载foo.so。但LD_PRELOAD救援:

$ LD_BIND_NOW=1 LD_WARN=1 LD_TRACE_LOADED_OBJECTS=1 LD_PRELOAD=./foo.so ./a.out
    linux-vdso.so.1 =>  (0x00007fff3c1b6000)
    ./foo.so (0x00007ffd33212000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffd3300e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffd32c4f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffd33414000)
undefined symbol: baz   (./foo.so)
undefined symbol: bar   (./foo.so)

Voilà:现在报告所有未解决的符号。