我正在尝试了解Linux ELF可执行文件。我编写了一个简单的C“Hello World”程序,并使用GCC将其编译为可执行文件。
对于“Section Headers”,我可以理解最后一个“.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"
这些关键和值(value)观从何而来?如何手动找到它?
网络上的文章似乎无济于事:
我搜索了一些文章,也许这是最详细的文章: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
然后,它说:“名称中的第一个namesz字节包含条目所有者或始发者的以空字符结尾的字符表示。”
但是在第一个“4字节字”中,以“0x00”结尾的“0x04”不是可打印字符,而是ASCII控制字符“传输结束”。
因此,基本上的问题是,如何从二进制文件中手动查找ELF解析器显示的那些信息?
最佳答案
从elf(5)注释部分(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
关于c++ - 了解ELF执行程序的SHT_NOTE节 “.note.ABI-tag”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59608986/