__x86.get_pc_thunk.ax函数

__x86.get_pc_thunk

c语言到汇编指令这篇博文中,我一开始通过gcc编译源文件,没有关闭地址随机化这个选项,在编译出的程序的反汇编中,发现了很奇怪的call指令
源程序

long x = 1;
char c = 'a';

int main()
{
int a = 23;
char b = 'b';
short c = 12;
}

反汇编

0x11ad <main>                           endbr32                                                                                    
0x11b1 <main+4> push ebp
0x11b2 <main+5> mov ebp,esp
0x11b4 <main+7> sub esp,0x10
0x11b7 <main+10> call 0x11d9 <__x86.get_pc_thunk.ax>
0x11bc <main+15> add eax,0x2e20
0x11c1 <main+20> mov DWORD PTR [ebp-0x4],0x17
0x11c8 <main+27> mov BYTE PTR [ebp-0x7],0x62
0x11cc <main+31> mov WORD PTR [ebp-0x6],0xc
0x11d2 <main+37> mov eax,0x0
0x11d7 <main+42> leave
0x11d8 <main+43> ret

在main+10的位置处调用了一个__x86.get_pc_thunk.ax,很好奇这个是什么东西,gdb动态调试跟进去看看

发现了只有两条汇编指令

mov eax,[esp]
ret

esp存的就是main函数的地址(因为在main函数中call了当前这个函数)

简单说这个指令就相当于mov eax,eip

这个函数的作用就是get到main函数的地址

很好奇,为什么要获得main函数的地址呢?

我们继续往下走

发现eax这里通过add一个数字后变成了GOT表的地址,这样就不难理解了(关于什么是GOT表和PLT表,我会后面再展开文章进行学习记录),这个函数在x86上的PIC(position independent code)中使用,用来实现对模块的内部数据进行访问,比如全局变量。我们在main函数中访问一下全局变量x,用gdb查看汇编代码,果然可以看到程序访问x是通过GOT进行的。

事实上类似的函数还有:__x86.get_pc_thunk.bx__x86.get_pc_thunk.cx__x86.get_pc_thunk.dx。功能是类似的,只不过传入的寄存器分别为%ebx%ecx%edx。早期版本的编译器中,这个函数叫__i686.get_pc_thunk.ax

关闭pie

使用gcc编译命令

gcc -fno-pie

关闭pie,调试程序发现已经不需要再通过该函数进行寻址了

Reference

c - How do i get rid of call __x86.get_pc_thunk.ax - Stack Overflow

__x86.get_pc_thunk.ax函数

文章作者: Alex
文章链接: http://example.com/2021/04/06/ax/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alex's blog~