__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~!