Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc i686.get\u pc\u thunk和x86.get\u pc\u thunk之间有什么区别?_Gcc_Assembly_X86_Position Independent Code - Fatal编程技术网

Gcc i686.get\u pc\u thunk和x86.get\u pc\u thunk之间有什么区别?

Gcc i686.get\u pc\u thunk和x86.get\u pc\u thunk之间有什么区别?,gcc,assembly,x86,position-independent-code,Gcc,Assembly,X86,Position Independent Code,GCC和Clang在32位x86位置独立代码中使用这些辅助函数将当前执行地址输入寄存器,例如: call __i686.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx movl $2, 4(%esp) leal .LC0@GOTOFF(%ebx), %eax movl %eax, (%esp) call dlopen@PLT 似乎实现是等效的: __x86.get_pc_thunk.bx: movl

GCC和Clang在32位x86位置独立代码中使用这些辅助函数将当前执行地址输入寄存器,例如:

call    __i686.get_pc_thunk.bx
addl    $_GLOBAL_OFFSET_TABLE_, %ebx
movl    $2, 4(%esp)
leal    .LC0@GOTOFF(%ebx), %eax
movl    %eax, (%esp)
call    dlopen@PLT
似乎实现是等效的:

__x86.get_pc_thunk.bx:
    movl    (%esp), %ebx
    ret

__i686.get_pc_thunk.bx:
    movl (%esp), %ebx
    ret

除了改名似乎i686更老之外,还有什么区别吗?是否有理由使用i686前缀而不是i386

只是一个不同的名字选择,不重要

i686是使用PPro新指令(如CMOV和FCOMI)以及586 CMPGXCHG和CPUID)的32位代码的标准名称。现代GNU/Linux发行版通常将gcc配置为将其用作-m32位代码的默认目标,而不是真正的基线i386。e、 g.gcc-v将显示32位gcc构建的i686linuxgnu

通常,clang使用call next\u insn/pop reg将EIP读入寄存器。有趣的事实:这实际上不会破坏除原始奔腾Pro或通过Nano3000之外的CPU上的返回地址预测:-CPU特殊情况调用rel32=0,因为它不是真正的调用,并且不会将返回地址放入预测堆栈

get_pc_thunk.bx包含要返回的寄存器的名称。32位PIC代码过去只使用EBX作为get指针寄存器,但GCC现在可以选择任何方便的寄存器并为其发出thunk函数,如…get_pc_thunk.ax,因此叶函数不必保存/恢复EBX


PIE确实会使可执行文件的速度变慢,32位代码的速度可能会降低15%,而64位代码的速度可能会降低两个百分点。x86-64具有RIP相对寻址,因此无需使用这些Thunk。在我看来,一个32位的馅饼不值这个价钱,除非你真的需要通过主可执行文件的ASLR来加强对ROP和幽灵攻击的防御。

只是一个不同的名称选择,没有什么意义

i686是使用PPro新指令(如CMOV和FCOMI)以及586 CMPGXCHG和CPUID)的32位代码的标准名称。现代GNU/Linux发行版通常将gcc配置为将其用作-m32位代码的默认目标,而不是真正的基线i386。e、 g.gcc-v将显示32位gcc构建的i686linuxgnu

通常,clang使用call next\u insn/pop reg将EIP读入寄存器。有趣的事实:这实际上不会破坏除原始奔腾Pro或通过Nano3000之外的CPU上的返回地址预测:-CPU特殊情况调用rel32=0,因为它不是真正的调用,并且不会将返回地址放入预测堆栈

get_pc_thunk.bx包含要返回的寄存器的名称。32位PIC代码过去只使用EBX作为get指针寄存器,但GCC现在可以选择任何方便的寄存器并为其发出thunk函数,如…get_pc_thunk.ax,因此叶函数不必保存/恢复EBX


PIE确实会使可执行文件的速度变慢,32位代码的速度可能会降低15%,而64位代码的速度可能会降低两个百分点。x86-64具有RIP相对寻址,因此无需使用这些Thunk。在我看来,一个32位的馅饼不值这个价钱,除非你真的需要通过主可执行文件的ASLR来加强对ROP和幽灵攻击的防御。

所以,在挖掘了提交历史和bug追踪器之后,我想我基本上找到了答案

很久以前,glibc曾经有自己的PIC代码处理方法,这涉及到获取get地址的过程

完成类似任务的get_pc_thunk.*,最初作为内部符号添加到GCC中

不久之后,它也会出现,可能是为了避免在使用GCC编译时代码重复

然而,当为奔腾2或更高版本-march=i686构建时,GCC定义的预处理器宏_i686=1破坏了glibc对存根代码的编译。这个问题很早就解决了,但几年来glibc一直在处理这个问题

2011年GCC 4.7?到uux86。获取pc_thunk.*和glibc以使用匹配的名称。最终,对旧GCC版本的支持与旧名称一起被删除。GCC和glibc现在都只使用_x86.get_pc_thunk.*尽管GCC也可以生成内联调用/弹出版本

因此,总而言之:

两者之间没有实际区别,名称更改只是由于预定义的宏冲突而导致的历史更改

参考资料:


所以,在对提交历史和bug追踪器进行了一些挖掘之后,我想我基本上找到了答案

很久以前,glibc曾经有自己的PIC代码处理方法,这涉及到获取get地址的过程

完成类似任务的get_pc_thunk.*,最初作为内部符号添加到GCC中

不久之后,它也会出现,可能是为了避免在使用GCC编译时代码重复

然而,当为奔腾2或更高版本-march=i686构建时,GCC定义的预处理器宏_i686=1破坏了glibc对存根代码的编译。这个问题很早就解决了,但几年来glibc一直在处理这个问题

2011年GCC 4.7?到uux86。获取pc_thunk.*和glibc以使用匹配的名称。最终,对旧GCC版本的支持与 老名字。GCC和glibc现在都只使用_x86.get_pc_thunk.*尽管GCC也可以生成内联调用/弹出版本

因此,总而言之:

两者之间没有实际区别,名称更改只是由于预定义的宏冲突而导致的历史更改

参考资料: