为什么在饼图二进制文件上不允许使用“ symbol @ GOT”?

时间:2018-11-20 13:33:51

标签: linux assembly x86 position-independent-code got

这是示例程序集文件test.s

.global main  
main:  
 mov __progname@GOT, %eax         // failed to compile
 mov __progname@GOT(%ebx), %eax   //succeed to compile

我尝试使用-pie标志进行编译,但失败了。

$ gcc -pie -o test test.s
osboxes@osboxes:/mnt/hgfs/VM_Shared/Reassemblabla/src$ gcc -pie -o test test.s
/usr/bin/ld: /tmp/ccPGMLlH.o: direct GOT relocation R_386_GOT32X against `__progname' without base register can not be used when making a shared object
/usr/bin/ld: failed to set dynamic section sizes: File format not recognized
collect2: error: ld returned 1 exit status

错误说,在饼状二进制文件中,只能使用基址寄存器访问GOT条目。

问题。
我不知道为什么编译器会像上面这样抱怨。
更具体地说,为什么对饼图二进制文件不允许__progname@GOT寻址?



我的意见。
加载程序在饼状二进制文件的加载时间中知道__progname@GOT的地址。

因此,加载器可以在加载时简单地将此地址写入__progname@GOT的位置。
那就是装载程序可以做的。

所以我不明白为什么编译器坚持像这样相对寄存器访问
mov __progname@GOT(%ebx), %eax

1 个答案:

答案 0 :(得分:1)

PIE应该使用与pc相关的寻址; ia32很糟糕,因此您需要执行以下操作:

    call thunk
    add  $_GLOBAL_OFFSET_TABLE__, %eax
    mov  __progname@GOT(%eax), %eax
    ret
thunk:
    mov (%esp), %eax
    ret

从该程序地址到_GLOBAL_OFFSET_TABLE__的通知偏移量被计算为参考GOT。因此,可以在任何地址加载(而不是链接或定位),并且可以找到GOT和所有变量,因为相对偏移量相同。 作为参考,上述的amd64版本类似于:

mov    __progname(%rip), %rax
ret

请注意,这两个选项都将文本保持为“纯”。...