首页 > 解决方案 > 了解 ELF 可执行文件的 SHT_NOTE 部分“.note.ABI-tag”

问题描述

我正在尝试了解 Linux ELF 可执行文件。我编写了一个简单的 C“Hello World”程序,并使用 GCC 将其编译为可执行文件。

对于“节标题”,我可以理解最后一个“.shstrtab”和第二个“.interp”,因为只有一些偏移量可以让我找出它所指的内容。

但是对于部分标题“.note.ABI-tag”,我只是感到困惑。

下面列出的内容来自我的 HelloWorld 可执行文件:

...
00000230  01 00 00 00 00 00 00 00  2f 6c 69 62 36 34 2f 6c  |......../lib64/l|
00000240  64 2d 6c 69 6e 75 78 2d  78 38 36 2d 36 34 2e 73  |d-linux-x86-64.s|
00000250  6f 2e 32 00 04 00 00 00  10 00 00 00 01 00 00 00  |o.2.............| <-- (5) start at 0x0254 (value: "0x04")
00000260  47 4e 55 00 00 00 00 00  03 00 00 00 02 00 00 00  |GNU.............|
00000270  00 00 00 00 04 00 00 00  14 00 00 00 03 00 00 00  |................| <-- (6) end at 0x0274 (note included)
00000280  47 4e 55 00 42 5c e5 58  cc 7b 78 91 e0 e1 b0 9a  |GNU.B\.X.{x.....|
00000290  3d 09 5b 6a 03 c1 7c bb  01 00 00 00 01 00 00 00  |=.[j..|.........|
000002a0  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
...
000022a0  72 54 4d 43 6c 6f 6e 65  54 61 62 6c 65 00 00 2e  |rTMCloneTable...|
000022b0  73 79 6d 74 61 62 00 2e  73 74 72 74 61 62 00 2e  |symtab..strtab..|
000022c0  73 68 73 74 72 74 61 62  00 2e 69 6e 74 65 72 70  |shstrtab..interp|
000022d0  00 2e 6e 6f 74 65 2e 41  42 49 2d 74 61 67 00 2e  |..note.ABI-tag..| <-- (3) name starts at 0x22d1
000022e0  6e 6f 74 65 2e 67 6e 75  2e 62 75 69 6c 64 2d 69  |note.gnu.build-i|
000022f0  64 00 2e 67 6e 75 2e 68  61 73 68 00 2e 64 79 6e  |d..gnu.hash..dyn|
...
00002440  00 00 00 00 00 00 00 00  23 00 00 00 07 00 00 00  |........#.......| <-- (2) sh_name offset is 0x23
00002450  02 00 00 00 00 00 00 00  54 02 40 00 00 00 00 00  |........T.@.....|
00002460  54 02 00 00 00 00 00 00  20 00 00 00 00 00 00 00  |T....... .......| <-- (4) sh_offset = 0x0254, sh_size = 0x20
00002470  00 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00  |................|
00002480  00 00 00 00 00 00 00 00  31 00 00 00 07 00 00 00  |........1.......|

...
00002b00  00 00 00 00 00 00 00 00  11 00 00 00 03 00 00 00  |................|
00002b10  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00002b20  ae 22 00 00 00 00 00 00  19 01 00 00 00 00 00 00  |."..............| <-- (1).shstrtab starts at 0x22ae
00002b30  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|
00002b40  00 00 00 00 00 00 00 00  (end of the file)        |........|
00002b48

我能理解的是:

这就是我能找到的所有信息。

但我无法理解的是:

为什么我的 ELF 解析器告诉我它可以找到更多信息:

Note Segment (offset=0x254, size=32)
    Name="GNU"
    Type=1
    Type String="NT_GNU_ABI_TAG"
    Description="OS Linux 3.2.0"

这些关键和价值从何而来?我怎样才能手动找到它?

网上的文章似乎没有帮助:

我搜索了一些文章,也许这是最详细的一篇:https ://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html

但我仍然无法理解这一点。

例如它说“每个条目是目标处理器格式的4字节字数组”,所以似乎我应该将0x0254(包括)和0x0274(不包括)之间的字节分成8“4字节字",应该是:

1st word: 04 00 00 00
2nd word: 10 00 00 00
3rd word: 01 00 00 00
4th word: 47 4e 55 00
5th word: 00 00 00 00
6th word: 03 00 00 00
7th word: 02 00 00 00
8th word: 00 00 00 00

然后它说“name 中的第一个 namesz 字节包含条目所有者或发起者的空终止字符表示。”

但在第一个“4字节字”中,以“0x00”结尾的“0x04”不是可打印字符,而是ASCII控制字符“传输结束”。

所以基本上问题是,如何从二进制文件中手动查找 ELF 解析器显示的那些信息?

标签: c++cexecutableelf

解决方案


elf(5)部分Notes(Nhdr)中抓取它我能够确定:

1st word: 04 00 00 00 - n_namesz - the name of the name field in bytes. It is 4 - "GNU"
2nd word: 10 00 00 00 - n_descsz - The length of the descriptor field in bytes.
3rd word: 01 00 00 00 - n_type - The NT_GNU_ABI_TAG label (or ELF_NOTE_ABI or similar)
4th word: 47 4e 55 00 - "GNU" with zero terminator
5th word: 00 00 00 00 - OS descriptor - ELF_NOTE_OS_LINUX,
6th word: 03 00 00 00 - major version of the ABI
7th word: 02 00 00 00 - minor version of the ABI
8th word: 00 00 00 00 - subminor version of the ABI

推荐阅读