我有以下库:
shared4.c
:
int get_another_int(void){
return 10;
}
和二进制文件:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int get_another_int(void);
int main(void){
void *handle = dlopen("/home/me/c/build/libshar4.so", RTLD_GLOBAL | RTLD_NOW);
if(!handle){
exit(EXIT_FAILURE);
}
printf("handle = %p\n", handle);
printf("another_int = %d\n", get_another_int());
}
我没有将二进制文件与库链接,并添加了一个 ld
选项来忽略找不到符号的错误:
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
有了这些选项,二进制编译和链接就“正常”了。
plt
部分如下所示:
$ objdump -d -j .plt ./build/bin_shared
./build/bin_shared: file format elf64-x86-64
Disassembly of section .plt:
00000000000005e0 <.plt>:
5e0: ff 35 22 0a 20 00 pushq 0x200a22(%rip) # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
5e6: ff 25 24 0a 20 00 jmpq *0x200a24(%rip) # 201010 <_GLOBAL_OFFSET_TABLE_+0x10>
5ec: 0f 1f 40 00 nopl 0x0(%rax)
...
0000000000000600 <dlopen@plt>:
600: ff 25 1a 0a 20 00 jmpq *0x200a1a(%rip) # 201020 <dlopen@GLIBC_2.2.5>
606: 68 00 00 00 00 pushq $0x0
60b: e9 d0 ff ff ff jmpq 5e0 <.plt>
0000000000000610 <__printf_chk@plt>:
610: ff 25 12 0a 20 00 jmpq *0x200a12(%rip) # 201028 <__printf_chk@GLIBC_2.3.4>
616: 68 01 00 00 00 pushq $0x1
61b: e9 c0 ff ff ff jmpq 5e0 <.plt>
0000000000000620 <exit@plt>:
620: ff 25 0a 0a 20 00 jmpq *0x200a0a(%rip) # 201030 <exit@GLIBC_2.2.5>
626: 68 02 00 00 00 pushq $0x2
62b: e9 b0 ff ff ff jmpq 5e0 <.plt>
我检查了 objdump
并注意到了以下 main
片段:
66b: e8 a0 ff ff ff callq 610 <__printf_chk@plt>
670: e8 7b ff ff ff callq 5f0 <.plt+0x10>
但应用程序启动失败,出现以下错误:
$ ./build/bin_shared
./build/bin_shared: error while loading shared libraries: unexpected PLT reloc type 0x00
我查看了所有重定位类型:
$ objdump -R ./build/bin_shared
./build/bin_shared: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0000000000200dd8 R_X86_64_RELATIVE *ABS*+0x00000000000007a0
0000000000200de0 R_X86_64_RELATIVE *ABS*+0x0000000000000760
0000000000201040 R_X86_64_RELATIVE *ABS*+0x0000000000201040
0000000000200fd8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable
0000000000200fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.2.5
0000000000200fe8 R_X86_64_GLOB_DAT __gmon_start__
0000000000200ff0 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable
0000000000200ff8 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5
0000000000201020 R_X86_64_JUMP_SLOT dlopen@GLIBC_2.2.5
0000000000201028 R_X86_64_JUMP_SLOT __printf_chk@GLIBC_2.3.4
0000000000201030 R_X86_64_JUMP_SLOT exit@GLIBC_2.2.5
0000000000000000 R_X86_64_NONE *ABS* //<---- This relocation
有没有办法解决这个问题,并从加载了 dlopen
的库中创建符号,但在链接期间没有与 ld
链接以供使用动态链接器,以便我上面显示的应用程序能够按预期运行?
最佳答案
Is there a way to workaround this
链接器必须知道该符号将来自某个共享库,并且需要知道这是什么种类的符号,以便正确地构建动态主要可执行文件中该符号的符号引用。
由于您不想(或不能)在链接时提供 libshar4.so
,您的另一个选择是假装您做链接提供这个符号。
例如,由于您使用 dlopen
,您可以创建一个 dlopen_stub.so
,它同时提供 dlopen
和 get_another_int
(stub中任一函数的实际实现都可以为空),将这个stub库的SONAME
设置为libdl.so.2
(或者你真正的 libdl.so
使用的任何 SONAME
),并将你的二进制文件与该 stub 链接(而不是与 -ldl
链接) .
在运行时,假设 LD_BIND_NOW
未生效,二进制文件将不会尝试解析 get_another_int
,直到您加载 libshar4.so
,届时符号将可用。
关于c - 抑制 ld symbol not found 错误以便稍后在运行时解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58162190/