gcc - ELF动态符号表

标签 gcc elf

我有一个关于 ELF 动态符号表的问题。对于 FUNC 类型的符号,我注意到某些二进制文件中的值为 0。但在其他二进制文件中,它具有一些非零值。这两个二进制文件都是由 gcc 生成的,我想知道为什么会出现这种差异?是否有任何编译器选项来控制它?

编辑:这是 readelf --dyn-syms prog1 的输出

Symbol table '.dynsym' contains 5 entries:
Num:    Value  Size Type    Bind   Vis      Ndx Name
 0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
 1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
 2: 000082f0     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.4 (2)
 3: 00008314     0 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.4 (2)
 4: 000082fc     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.4 

这里“printf”符号的值为82f0,这恰好是printf的plt表条目的地址。

readelf --dyn-syms prog2 的输出

Symbol table '.dynsym' contains 6 entries:
Num:    Value  Size Type    Bind   Vis      Ndx Name
 0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
 1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
 2: 00000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.4 (2)
 3: 00000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.4 (2)
 4: 00000000     0 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.4 (2)
 5: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.4 

此处所有符号的值均为零。

最佳答案

x86_64 SV ABI要求(强调我的):

To allow comparisons of function addresses to work as expected, if an executable file references a function defined in a shared object, the link editor will place the address of the procedure linkage table entry for that function in its associated symbol table entry. This will result in symbol table entries with section index of SHN_UNDEF but a type of STT_FUNC and a non-zero st_value. A reference to the address of a function from within a shared library will be satisfied by such a definition in the executable.

使用我的 GCC,这个程序:

#include <stdio.h>

int main()
{
  printf("hello %i\n", 42);
  return 0;
}

当直接编译成可执行文件时会生成空值:

 1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)

但是这个程序与printf函数的比较:

#include <stdio.h>

int main()
{
  printf("hello %i\n", 42);
  if (printf == puts)
    return 1;
  return 0;
}

生成一个非空值:

 3: 0000000000400410     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)

在.o文件中,第一个程序生成:

000000000014  000a00000002 R_X86_64_PC32     0000000000000000 printf - 4

第二个:

000000000014  000a00000002 R_X86_64_PC32     0000000000000000 printf - 4
000000000019  000a0000000a R_X86_64_32       0000000000000000 printf + 0

差异是由用于获取函数地址的额外 R_X86_64_32 重定位造成的。

关于gcc - ELF动态符号表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32737355/

相关文章:

linux - 存在于二进制文件的 elf RUNPATH 中的库没有被使用?

c - 全局变量始终初始化为零

c - 存在哪些 C GNU 主义?

linux - vmlinux ELF 查找给定结构成员的偏移量

reverse-engineering - ELF搬迁逆向工程

gdb - leave 和 ret 和有什么不一样

C 中的编译器错误 - ELSE 语句后的 ‘;’ 标记之前应有 ‘{’

c - 安装 r 包时出错 (Linux Mint 17.1) "error: C preprocessor "g++ -E“完整性检查失败”

python - 在 OS X 10.6 上安装 scrapy 的问题

c - 每个进程内存中的共享库是如何寻址的?