动态链接库
相关的段
啊对,我之前的解释有误,让我重新详细解释一下 .plt、.got.plt 和 .rela.plt 的关系:
.plt(Procedure Linkage Table):
- 是一个代码段,包含了跳转指令
- 每个动态链接的函数在
.plt中都有一个对应的条目 - 第一次调用时,会跳转到动态链接器进行符号解析
- 解析完成后,会跳转到
.got.plt中存储的地址
.got.plt(Global Offset Table for PLT):
- 是一个数据段,存储了函数地址
- 初始时存储的是
.plt中解析函数的代码地址 - 动态链接器解析完符号后,会将实际函数地址写入这里
- 后续调用时,
.plt会直接跳转到.got.plt中存储的地址
.rela.plt(Relocation Table for PLT):
- 是一个重定位表,包含了重定位信息
- 存储了
.got.plt中需要重定位的条目的信息 - 动态链接器使用这些信息来解析符号地址
工作流程:
第一次调用动态链接函数时:
.plt跳转到动态链接器- 动态链接器使用
.rela.plt中的信息解析符号地址 - 将解析后的地址写入
.got.plt中 - 跳转到实际函数地址
后续调用时:
.plt直接跳转到.got.plt中存储的地址- 不需要再次进行符号解析
你可以使用以下命令查看这些段的内容:
readelf -S your_program # 查看段信息
objdump -d -j .plt your_program # 查看 .plt 段内容
objdump -s -j .got.plt your_program # 查看 .got.plt 段内容
readelf -r your_program # 查看重定位表内容
这种设计的主要优点是:
- 实现了延迟绑定,提高了程序启动速度
- 只有实际使用的函数才会被解析
- 减少了内存占用和启动时间
- 支持动态加载和卸载共享库
- .rela.dyn 和 .rela.plt 是重定位信息表
typedef struct {
Elf64_Addr r_offset; // 需要重定位的位置(相对于段基址的偏移)
Elf64_Xword r_info; // 重定位类型和符号表索引
Elf64_Sxword r_addend; // 重定位的加数
} Elf64_Rela;
- 查看重定位表
readelf -r -C HelloWorld
Relocation section '.rela.dyn' at offset 0x7e0 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003d98 000000000008 R_X86_64_RELATIVE 1160
000000003da0 000000000008 R_X86_64_RELATIVE 1120
000000004008 000000000008 R_X86_64_RELATIVE 4008
000000003fd0 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0
000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 std::basic_ostrea[...]@GLIBCXX_3.4 + 0
000000003fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000003fe8 000600000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0
000000003ff0 000700000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff8 000800000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0
000000004040 001200000005 R_X86_64_COPY 0000000000004040 std::cout@GLIBCXX_3.4 + 0
Relocation section '.rela.plt' at offset 0x8d0 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000003fc0 000300000007 R_X86_64_JUMP_SLO 0000000000000000 std::basic_ostrea[...]@GLIBCXX_3.4 + 0
000000003fc8 000400000007 R_X86_64_JUMP_SLO 0000000000000000 std::ostream::operator@GLIBCXX_3.4 + 0
- 查看动态重定位表
objdump -R HelloWorld
HelloWorld: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0000000000003d98 R_X86_64_RELATIVE *ABS*+0x0000000000001160
0000000000003da0 R_X86_64_RELATIVE *ABS*+0x0000000000001120
0000000000004008 R_X86_64_RELATIVE *ABS*+0x0000000000004008
0000000000003fd0 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5
0000000000003fd8 R_X86_64_GLOB_DAT _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GLIBCXX_3.4
0000000000003fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.34
0000000000003fe8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable@Base
0000000000003ff0 R_X86_64_GLOB_DAT __gmon_start__@Base
0000000000003ff8 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable@Base
0000000000004040 R_X86_64_COPY _ZSt4cout@GLIBCXX_3.4
0000000000003fc0 R_X86_64_JUMP_SLOT _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@GLIBCXX_3.4
0000000000003fc8 R_X86_64_JUMP_SLOT _ZNSolsEPFRSoS_E@GLIBCXX_3.4
查看 plt 与 got 相关的信息
objdump -d -j .plt.got HelloWorld
HelloWorld: file format elf64-x86-64
Disassembly of section .plt.got:
0000000000001050 <__cxa_finalize@plt>:
1050: f3 0f 1e fa endbr64
1054: ff 25 76 2f 00 00 jmp *0x2f76(%rip) # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
105a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
objdump -d -j .plt HelloWorld
HelloWorld: file format elf64-x86-64
Disassembly of section .plt:
0000000000001020 <.plt>:
1020: ff 35 8a 2f 00 00 push 0x2f8a(%rip) # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x8>
1026: ff 25 8c 2f 00 00 jmp *0x2f8c(%rip) # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x10>
102c: 0f 1f 40 00 nopl 0x0(%rax)
1030: f3 0f 1e fa endbr64
1034: 68 00 00 00 00 push $0x0
1039: e9 e2 ff ff ff jmp 1020 <_init+0x20>
103e: 66 90 xchg %ax,%ax
1040: f3 0f 1e fa endbr64
1044: 68 01 00 00 00 push $0x1
1049: e9 d2 ff ff ff jmp 1020 <_init+0x20>
104e: 66 90 xchg %ax,%ax
查看动态符号
objdump -R -C HelloWorld
HelloWorld: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0000000000003d98 R_X86_64_RELATIVE *ABS*+0x0000000000001160
0000000000003da0 R_X86_64_RELATIVE *ABS*+0x0000000000001120
0000000000004008 R_X86_64_RELATIVE *ABS*+0x0000000000004008
0000000000003fd0 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5
0000000000003fd8 R_X86_64_GLOB_DAT std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)@GLIBCXX_3.4
0000000000003fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.34
0000000000003fe8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable@Base
0000000000003ff0 R_X86_64_GLOB_DAT __gmon_start__@Base
0000000000003ff8 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable@Base
0000000000004040 R_X86_64_COPY std::cout@GLIBCXX_3.4
0000000000003fc0 R_X86_64_JUMP_SLOT std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@GLIBCXX_3.4
0000000000003fc8 R_X86_64_JUMP_SLOT std::ostream::operator<<(std::ostream& (*)(std::ostream&))@GLIBCXX_3.4