抑制 ld symbol not found 错误以便稍后在运行时解决
Supress ld symbol not found error to resolve later in runtime
我有以下图书馆:
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());
}
我没有 link 库中的二进制文件,并添加了一个 ld
选项来忽略找不到符号的错误:
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
使用这些选项编译二进制文件并link编辑"fine"。
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 [=13=]x0
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 [=13=]x1
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 [=13=]x2
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
的库中制作符号,但在 [=47] 期间不使用 ld
linked =] 时间可用于动态 linker 所以我上面显示的应用程序将 运行 如预期的那样?
Is there a way to workaround this
linker 必须 知道该符号将来自某个共享库,并且需要知道 kind 符号这是为了在主要可执行文件中正确构建该符号的动态符号引用。
由于您不想(或不能)在 link 时提供 libshar4.so
,您的另一个选择是 假装您做 link 反对的其他库提供此符号。
例如,由于您使用 dlopen
,您可以创建一个 dlopen_stub.so
,它同时提供 dlopen
和 get_another_int
(存根中任一函数的实际实现都可以为空),将此存根库的 SONAME
设置为 libdl.so.2
(或任何 SONAME
你真正的 libdl.so
使用) ,和 link 你的二进制文件与那个存根(而不是 linking 与 -ldl
)。
在运行时,假设 LD_BIND_NOW
是 而不是 ,二进制文件将不会尝试解析 get_another_int
,直到您加载 libshar4.so
,届时符号将可用。
我有以下图书馆:
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());
}
我没有 link 库中的二进制文件,并添加了一个 ld
选项来忽略找不到符号的错误:
-Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all
使用这些选项编译二进制文件并link编辑"fine"。
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 [=13=]x0
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 [=13=]x1
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 [=13=]x2
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
的库中制作符号,但在 [=47] 期间不使用 ld
linked =] 时间可用于动态 linker 所以我上面显示的应用程序将 运行 如预期的那样?
Is there a way to workaround this
linker 必须 知道该符号将来自某个共享库,并且需要知道 kind 符号这是为了在主要可执行文件中正确构建该符号的动态符号引用。
由于您不想(或不能)在 link 时提供 libshar4.so
,您的另一个选择是 假装您做 link 反对的其他库提供此符号。
例如,由于您使用 dlopen
,您可以创建一个 dlopen_stub.so
,它同时提供 dlopen
和 get_another_int
(存根中任一函数的实际实现都可以为空),将此存根库的 SONAME
设置为 libdl.so.2
(或任何 SONAME
你真正的 libdl.so
使用) ,和 link 你的二进制文件与那个存根(而不是 linking 与 -ldl
)。
在运行时,假设 LD_BIND_NOW
是 而不是 ,二进制文件将不会尝试解析 get_another_int
,直到您加载 libshar4.so
,届时符号将可用。