c - 什么 C 源代码将编译为针对 GOT 中另一个指针的调用 *get_func@GOTPCREL(%rip) 和 cmp?

标签 c assembly x86-64 dynamic-linking

我想生成以下指令。什么 C 源代码将编译成这个 asm?

call    *get_func@GOTPCREL(%rip)
cmpq    func@GOTPCREL(%rip), %rax

最佳答案

看起来像是对使用 -fno-plt 编译的 get_func() 的调用,然后将返回值与另一个函数的地址进行比较。

我使用了 void* 而不是声明一个返回函数指针的函数,因为这样更容易。这是问题,以便所有内容都可以从 void* 转换为/而无需强制转换。

void func();
void *get_func(void);  // returns a function pointer
int foo(void) {
  return func == get_func();
}

source + asm on Godbolt

    # gcc7.2 -O3 -fno-plt
    subq    $8, %rsp
    # your lines verbatim in the compiler output
    call    *get_func@GOTPCREL(%rip)
    cmpq    func@GOTPCREL(%rip), %rax

    sete    %al
    addq    $8, %rsp
    movzbl  %al, %eax
    ret

无论有没有 PLT,函数地址都将来自 GOT,但使用传统的 -fplt(这仍然是默认值),call 指令将来自 GOT。是对此可执行文件或共享对象中的 PLT 的 rel32 调用。

例如仅使用 -fPIC:

    call    get_func@PLT
    cmpq    func@GOTPCREL(%rip), %rax

或没有其中之一(仅对于位置相关的可执行文件,因此 func 的地址是链接时间常量):

    call    get_func        # converted at link-time to a PLT call if it's in a shared lib
    cmpq    $func, %rax

相关:32-bit absolute addresses no longer allowed in x86-64 Linux?许多发行版让 gcc 默认启用 -pie/-fPIE

<小时/>

clang 更聪明,并且在 cmp 之前将 eax 进行异或清零,因此关键路径上没有 movzbl 。但call/cmp基本是一样的。

clang 没有 no-PLT 选项。

关于c - 什么 C 源代码将编译为针对 GOT 中另一个指针的调用 *get_func@GOTPCREL(%rip) 和 cmp?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47524637/

相关文章:

编译 sendmmsg 得到对 `sendmmsg' 的 undefined reference ?

assembly - 关于进位标志的 ARM 文档的困惑

x86 - 分页和 PIC 可执行文件

assembly - 查看寄存器以外的堆栈内容

linux - 助记符中的无效字符(0xe2)

performance - 现代 x86-64 cpu 仍然受益于内存数据对齐吗?

linux - 为什么我在 `ret' 时会出现段错误? (FASM)

c - C 语言中可以并行执行输入/输出操作吗?

c - 编写一个函数接收两个参数并返回差值

c - 变量设置不正确