首页 > 解决方案 > get_pc_thunk 的返回值没有被使用

问题描述

我有这个程序:

static int aux() {
    return 1;
}
int _start(){
    int a = aux();
    return a;
}

当我使用带有标志-nostdlib -m32 -fpie的 GCC 编译它并生成 ELF 二进制文件时,我得到以下汇编代码:

00001000 <aux>:
    1000:   f3 0f 1e fb             endbr32 
    1004:   55                      push   %ebp
    1005:   89 e5                   mov    %esp,%ebp
    1007:   e8 2d 00 00 00          call   1039 <__x86.get_pc_thunk.ax>
    100c:   05 e8 2f 00 00          add    $0x2fe8,%eax
    1011:   b8 01 00 00 00          mov    $0x1,%eax
    1016:   5d                      pop    %ebp
    1017:   c3                      ret    

00001018 <_start>:
    1018:   f3 0f 1e fb             endbr32 
    101c:   55                      push   %ebp
    101d:   89 e5                   mov    %esp,%ebp
    101f:   83 ec 10                sub    $0x10,%esp
    1022:   e8 12 00 00 00          call   1039 <__x86.get_pc_thunk.ax>
    1027:   05 cd 2f 00 00          add    $0x2fcd,%eax
    102c:   e8 cf ff ff ff          call   1000 <aux>
    1031:   89 45 fc                mov    %eax,-0x4(%ebp)
    1034:   8b 45 fc                mov    -0x4(%ebp),%eax
    1037:   c9                      leave  
    1038:   c3                      ret    

00001039 <__x86.get_pc_thunk.ax>:
    1039:   8b 04 24                mov    (%esp),%eax
    103c:   c3                      ret

我知道该get_pc_thunk函数用于在 x86 中实现与位置无关的代码,但在这种情况下,我不明白为什么要使用它。我的问题是:

  1. 该函数返回eax寄存器中下一条指令的地址,并且在这两种用法中,都使用一条add指令来eax指向 GOT。通常,(至少在访问全局变量时),该eax寄存器将立即用于访问表中的全局变量。但是,在这种情况下, 将eax被完全忽略。到底是怎么回事?
  2. 我也不明白为什么get_pc_thunk代码中甚至存在,因为两条call指令都使用相对地址。由于地址是相对的,它们不应该是开箱即用的位置无关的吗?

谢谢!

标签: linuxassemblygccx86loader

解决方案


您尚未启用优化,因此 GCC 会发出函数序言,而不考虑它们是否在相关函数中有用。

要查看get_pc_thunk使用访问全局变量的结果。

删除无用的调用以get_pc_thunk启用优化,例如通过添加-O2到 GCC 命令行。


推荐阅读