Gcc 为什么readelf加上@GLIBC_2.2.5(2)“;FUNC符号后';.dynsym符号表中的名称

Gcc 为什么readelf加上@GLIBC_2.2.5(2)“;FUNC符号后';.dynsym符号表中的名称,gcc,linker,elf,Gcc,Linker,Elf,我正在学习ELF文件,并以GCC在x86_64 CentOS 7上构建的C HelloWorld程序为例来研究可执行文件 我可以理解除了动态符号表(.dynsym)中的两个符号外,如何为可执行文件中的每个符号找到符号名 以符号表(.symtab)中的符号“main”为例: $ readelf -s HelloWorld ... Symbol table '.symtab' contains 84 entries: Num: Value Size Type Bi

我正在学习ELF文件,并以GCC在x86_64 CentOS 7上构建的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  |..@.............|
                                   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 03fb(小edian)。它实际上是具有以下内容的.strtab节中的偏移量:

$ readelf -p .strtab HelloWorld

String dump of section '.strtab':
...
  [   3fb]  main
...
因此,很容易理解这个符号的名称是“main”。除了在.dynsym中有两个符号外,在.symtab或.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 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  |..@.............|
                                   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处)

但为什么readelf会附加字符“@”?为什么还要附加字符串“GLIBC_2.2.5”(偏移量0x22处)

这些是GNU版本的符号
readelf
附加该信息以明确说明,否则您将看到例如以下内容:

  1232: 00000000000792d0   471 FUNC    GLOBAL DEFAULT   13 fmemopen
  1233: 0000000000078ed0   527 FUNC    GLOBAL DEFAULT   13 fmemopen
并且会被两个不同地址的
fmemopen
s所迷惑

电流输出:

  1232: 00000000000792d0   471 FUNC    GLOBAL DEFAULT   13 fmemopen@GLIBC_2.2.5
  1233: 0000000000078ed0   527 FUNC    GLOBAL DEFAULT   13 fmemopen@@GLIBC_2.22
显示这些符号附加了不同的版本信息,并且
GLIBC_2.22
版本是默认版本

您可以阅读有关GNU版本符号的更多信息