readelf
来读取ELF文件的信息。我发现节头中的.got
节的地址与从动态节中读取的GOT入口点地址不同。存储在.got
地址和GOT入口点之间的数据是否像垃圾一样?以下是从readelf
获得的信息的一部分。ELF标头-该ELF在ARMv7A上运行。 br />节标题-
.got
部分的地址为0x00008eac
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 38412 (bytes into file)
Flags: 0x5000200, Version5 EABI, soft-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 26
Section header string table index: 25
动态部分的一部分
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .note.gnu.build-i NOTE 00000134 000134 000024 00 A 0 0 4
[ 2] .dynsym DYNSYM 00000158 000158 0006a0 10 A 3 1 4
[ 3] .dynstr STRTAB 000007f8 0007f8 000704 00 A 0 0 1
[ 4] .hash HASH 00000efc 000efc 000334 04 A 2 0 4
[ 5] .gnu.version VERSYM 00001230 001230 0000d4 02 A 2 0 2
[ 6] .gnu.version_d VERDEF 00001304 001304 00001c 00 A 3 1 4
[ 7] .gnu.version_r VERNEED 00001320 001320 000020 00 A 3 1 4
[ 8] .rel.dyn REL 00001340 001340 000178 08 A 2 0 4
[ 9] .rel.plt REL 000014b8 0014b8 000250 08 AI 2 10 4
[10] .plt PROGBITS 00001708 001708 00038c 00 AX 0 0 4
[11] .text PROGBITS 00001a94 001a94 0053d4 00 AX 0 0 4
[12] .ARM.extab PROGBITS 00006e68 006e68 000078 00 A 0 0 4
[13] .ARM.exidx ARM_EXIDX 00006ee0 006ee0 000178 08 AL 11 0 4
[14] .rodata PROGBITS 00007058 007058 000038 00 AM 0 0 4
[15] .fini_array FINI_ARRAY 00008cf8 007cf8 000008 00 WA 0 0 4
[16] .data.rel.ro PROGBITS 00008d00 007d00 00007c 00 WA 0 0 4
[17] .init_array INIT_ARRAY 00008d7c 007d7c 000008 00 WA 0 0 4
[18] .dynamic DYNAMIC 00008d84 007d84 000128 08 WA 3 0 4
[19] .got PROGBITS 00008eac 007eac 000154 00 WA 0 0 4
[20] .data PROGBITS 00009000 008000 001450 00 WA 0 0 4
[21] .bss NOBITS 0000a450 009450 000004 00 WA 0 0 4
[22] .comment PROGBITS 00000000 009450 000065 01 MS 0 0 1
[23] .note.gnu.gold-ve NOTE 00000000 0094b8 00001c 00 0 0 4
[24] .ARM.attributes ARM_ATTRIBUTES 00000000 0094d4 000034 00 0 0 1
[25] .shstrtab STRTAB 00000000 009508 000103 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
.dynamic
的尾巴和.got
的头Dynamic section at offset 0x7d84 contains 32 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0x8ecc
0x00000002 (PLTRELSZ) 592 (bytes)
0x00000017 (JMPREL) 0x14b8
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x1340
0x00000012 (RELSZ) 376 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 41
0x00000006 (SYMTAB) 0x158
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x7f8
0x0000000a (STRSZ) 1796 (bytes)
0x00000004 (HASH) 0xefc
...
提到的Oracle规范:
符号_GLOBAL_OFFSET_TABLE_可用于访问表。该符号可以位于.got节的中间,从而允许将负数和非负数的下标都放入地址数组。 。所有其他数据都指向第一个PLT地址(
0x1708
)。 GOT入口点之前的空间用于存储外部功能的地址是否与其他地址相同,或者有其他使用方式,或者它们只是无用的垃圾? > Update 我发现
0x8eac
到0x8ecb
块中有两个数字,这是GOT入口点之前的块。在0x8ec0
处,0x7058
是.rodata
部分的地址。在0x8ec4
处,0x6ee0
是.ARM.exidx
部分的地址。是在.got
中填充这两个地址,这是ARM链工具和编译器的特定功能吗?#1 楼
没有样本很难说,但是您需要记住,动态加载器并不关心节。它仅使用程序头中的信息,包括PT_DYNAMIC
条目(它可能与.dynamic
部分完全不同,在这种情况下,该部分的内容将被忽略)。在.got
部分中,加载程序并不需要执行其工作。它仅使用动态标签和动态重定位信息(DT_JMPREL
,DT_PLTREL
,DT_REL
,DT_SYMTAB
,DT_STRTAB
和DT_HASH
以及用于符号解析)。实际上,您可以完全删除节表,并且文件仍然可以运行(但是某些工具可能难以解析它)。可能其他一些节与
.got
合并了,尽管我不知道可能是什么。
评论
好吧,实际上,正常的情况是,新鲜的GOT(无地址解析)被填充了链接PLT开头的指针。这是GOT首次初始化所必需的(记住,第一次遇到function @ plt时,您需要执行位于PLT开头的程序)。因此,这说明了为什么将PLT地址重复存储在GOT中(每个库函数在二进制文件中使用一个地址)。我知道为什么PLT地址反复存储在GOT中。每个地址都存储其对应的外部函数或外部变量的地址。我对GOT入口点之前的块用法感到好奇。
好吧,我更好地理解了你的问题。但是,您应该尝试在运行时查看.dynamic节。可能会改变很多事情...顾名思义,它只能在开始时(链接程序执行其工作时)进行初始化。我的猜测是,您将在运行时看到所有列出的变量设置的地址。
“ GOT的进入点”是什么意思? AFAIK没有这样的术语
@IgorSkochinsky对不起,我没有清楚解释。术语“ GOT的入口点”是指地址在.dynamic节中紧随变量PLTGOT之后。在大多数ELF规范中,该地址也与GOT [0]的地址相同。