c++ - 了解 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
我能理解的是:
- 在位置 (1)(在部分标题“.shstrtab”中)显示 .shstrtab 从 0x22ae 开始
- 在位置 (2) 显示此部分的 sh_name 偏移量为 0x23
- 所以我可以在位置 (3) (0x22ae + 0x23 = 0x22d1) 找到它的 sh_name,它是“.note.ABI-tag”
- 在位置 (4) 显示 sh_offset 为 0x0254 而 sh_size 为 0x20
- 所以我可以找到从 0x0254 到 0x0274 的内容(不包括在内)(0x0254 + 0x20 = 0x0274)
这就是我能找到的所有信息。
但我无法理解的是:
为什么我的 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 解析器显示的那些信息?
解决方案
从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
推荐阅读
- powershell - PowerShell 删除已删除 AD 用户帐户的文件夹权限
- drupal-8 - 使用 ajax 创建在表单提交时提交的数据表,而不将数据保存在数据库中。- Drupal8
- angular - 多层导航未正确跟踪 ActivatedRoute
- css - Min-Height 或 Max-Height 响应速度?
- reactjs - 生产模式下的电子将 URL 调用指向文件 URL 而不是代理 URL
- python - 你如何在 Keras 中继续训练以前的模型?
- jmeter - Jmeter:org.apache.jmeter.report.core.SampleException:找不到输入示例文件
- clojurescript - 为什么 db 在 reframe 中打印 #object[Object [object Object]]?
- c# - C#:不能隐式转换类型'System.Collections.Generic.List
' 到 'System.Collections.Generic.List ' - apache-flink - 如何在 flink 中打印聚合的 DataStream?