如何使 dlerror() 报告 dlopen() 加载共享库失败导致的*所有*未解析的符号?

use*_*569 1 linux dlopen

我试图报告共享库上对 dlopen() 调用失败的所有未解析符号。我已经尝试将 RTLD_LAZY 和 RTLD_NOW 作为 dlopen 调用的标志。我知道共享库缺少 10 个符号(即,如果您执行静态链接 g++ blah blah :链接将因缺少 10 个符号而失败)。我想让 dlerror() 告诉我加载失败期间丢失的所有 10 个符号。

有谁知道如何诱使这种情况发生?我从手册页中看到 dlerror() 返回最后一个错误;所以也许我问得太多了,但想知道是否有人知道。

非常感谢,

Emp*_*ian 5

\n

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

\n
\n\n

你不能:加载器一旦发现无法加载库(即一旦发现第一个丢失的符号)就会报告错误。加载程序没有必要继续前进,因此它不会继续前进。

\n\n

但是,您可以ldd -r通过使用LD_PRELOAD和 来模拟什么LD_TRACE_LOADED_OBJECTS,以获得完整的答案。例子:

\n\n
$ cat main.c\n#include <dlfcn.h>\n#include <stdio.h>\n\nint main()\n{\n  void *p = dlopen("./foo.so", RTLD_NOW);\n  if (p == NULL) {\n    printf("%s\\n", dlerror());\n    return 1;\n  }\n  return 0;\n}\n\n\n$ cat foo.c\nint bar(), baz();  // not defined anywhere\nint foo() {\n  return bar() + baz();\n}\n\n$ gcc main.c -ldl; gcc -fPIC -shared -o foo.so foo.c\n\n$ ./a.out\n./foo.so: undefined symbol: baz  # only the first symbol is reported\n\n$ ldd -r ./a.out\n    linux-vdso.so.1 =>  (0x00007fff52ddc000)\n    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f158e48d000)\n    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f158e0ce000)\n    /lib64/ld-linux-x86-64.so.2 (0x00007f158e6b2000)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是行不通的,因为你的程序从未执行过,因此也从未加载过foo.so。但LD_PRELOAD为了救援:

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

Voil\xc3\xa0:现在报告所有未解析的符号。

\n