【发布时间】:2020-01-15 10:17:50
【问题描述】:
我正在学习 ELF 文件,并以 x86_64 CentOS 7 上的 GCC 构建的 C HelloWorld 程序为例来研究可执行文件。
我可以理解如何为可执行文件中的每个符号找到符号名称,除了动态符号表 (.dynsym) 中的两个符号。
以符号表(.symtab)中的“main”符号为例:
$ readelf -s HelloWorld
...
Symbol table '.symtab' contains 84 entries:
Num: Value Size Type Bind Vis Ndx Name
...
80: 0000000000400586 21 FUNC GLOBAL DEFAULT 13 main
...
它的原值为:
Name of this symbol
^^ ^^ ^^ ^^
00001e20 00 00 00 00 00 00 00 00 fb 03 00 00 12 00 0d 00 |................|
00001e30 86 05 40 00 00 00 00 00 15 00 00 00 00 00 00 00 |..@.............|
值为0x0000 03fb(小edian)。它实际上是 .strtab 节中的一个偏移量,内容如下:
$ readelf -p .strtab HelloWorld
String dump of section '.strtab':
...
[ 3fb] main
...
所以很容易理解,这个符号的名字是“main”。 .symtab 或 .dynsym 中的每个符号都遵循此规则,但 .dynsym 中的两个符号除外。两个例外是:
$ readelf -s HelloWorld
Symbol table '.dynsym' contains 6 entries:
Num: Value Size Type Bind Vis Ndx Name
...
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
...
以符号#2为例,其原始值为:
Name of the symbol
^^ ^^ ^^ ^^
000002e0 00 00 00 00 00 00 00 00 0b 00 00 00 12 00 00 00 |................|
000002f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
符号名称的偏移量 0x0000 000b。通过查看 .dynstr:
$ readelf -p .dynstr HelloWorld
String dump of section '.dynstr':
[ 1] libc.so.6
[ b] puts
[ 10] __libc_start_main
[ 22] GLIBC_2.2.5
[ 2e] _ITM_deregisterTMCloneTable
[ 4a] __gmon_start__
[ 59] _ITM_registerTMCloneTable
我可以看到偏移量 0xb 处的字符串是“puts”。但是为什么readelf会附加一个字符“@”呢?为什么还要附加字符串“GLIBC_2.2.5”(偏移量 0x22)?
【问题讨论】: