我使用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

我发现0x8eac0x8ecb块中有两个数字,这是GOT入口点之前的块。在0x8ec0处,0x7058.rodata部分的地址。在0x8ec4处,0x6ee0.ARM.exidx部分的地址。是在.got中填充这两个地址,这是ARM链工具和编译器的特定功能吗?

评论

好吧,实际上,正常的情况是,新鲜的GOT(无地址解析)被填充了链接PLT开头的指针。这是GOT首次初始化所必需的(记住,第一次遇到function @ plt时,您需要执行位于PLT开头的程序)。因此,这说明了为什么将PLT地址重复存储在GOT中(每个库函数在二进制文件中使用一个地址)。

我知道为什么PLT地址反复存储在GOT中。每个地址都存储其对应的外部函数或外部变量的地址。我对GOT入口点之前的块用法感到好奇。

好吧,我更好地理解了你的问题。但是,您应该尝试在运行时查看.dynamic节。可能会改变很多事情...顾名思义,它只能在开始时(链接程序执行其工作时)进行初始化。我的猜测是,您将在运行时看到所有列出的变量设置的地址。

“ GOT的进入点”是什么意思? AFAIK没有这样的术语

@IgorSkochinsky对不起,我没有清楚解释。术语“ GOT的入口点”是指地址在.dynamic节中紧随变量PLTGOT之后。在大多数ELF规范中,该地址也与GOT [0]的地址相同。

#1 楼

没有样本很难说,但是您需要记住,动态加载器并不关心节。它仅使用程序头中的信息,包括PT_DYNAMIC条目(它可能与.dynamic部分完全不同,在这种情况下,该部分的内容将被忽略)。在.got部分中,加载程序并不需要执行其工作。它仅使用动态标签和动态重定位信息(DT_JMPRELDT_PLTRELDT_RELDT_SYMTABDT_STRTABDT_HASH以及用于符号解析)。实际上,您可以完全删除节表,并且文件仍然可以运行(但是某些工具可能难以解析它)。

可能其他一些节与.got合并了,尽管我不知道可能是什么。