c - 从内联汇编调用函数时针对符号重定位 R_X86_64_PC32

标签 c gcc assembly

我正在尝试构建共享库,这些共享库在程序集中具有一些调用其他函数的函数。当我使用代码构建 liba.so

void aFunc1()
{
}

asm(
    ".globl aFunc2\n\t"
    ".type aFunc2, @function\n\t"
    "aFunc2:\n\t"
    ".cfi_startproc\n\t"
    "call aFunc1\n\t" /* note here*/
    "ret\n\t"
    ".cfi_endproc\n\t"
);

和命令

gcc -o liba.so a.c -shared -fPIC

我遇到了错误

/usr/bin/ld: /tmp/ccdGBiQv.o: relocation R_X86_64_PC32 against symbol `aFunc1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

它告诉我使用选项 -fPIC 但我已经使用了该选项!但是我发现使用选项 -Wl,-Bsymbolic 可以正常编译。

gcc -o liba.so a.c -shared -fPIC -Wl,-Bsymbolic

不幸的是,当我尝试构建第二个库 libb.so 时,问题又回来了,它还使用尝试从第一个库调用函数的汇编函数。编译代码

#include <a.h>

asm(
    ".globl bFunc2\n\t"
    ".type bFunc2, @function\n\t"
    "bFunc2:\n\t"
    ".cfi_startproc\n\t"
    "call aFunc1\n\t" /* note here*/
    "ret\n\t"
    ".cfi_endproc\n\t"
);

用命令

gcc -o libb.so b.c liba.so -shared -fPIC -Wl,-Bsymbolic

给出错误

/usr/bin/ld: /tmp/ccaGvn5d.o: relocation R_X86_64_PC32 against symbol `aFunc1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

如您所见,选项 -Wl,Bsymbolic 没有帮助。

我想知道如何构建第二个库以及为什么第一个库需要 -Wl,Bsymbolic 选项。我不是汇编大师,所以我不知道它是否正确 — 我正在尝试构建其他库。也许我应该使用其他选项?

最佳答案

您需要调用 PLT stub ,因为函数可能已被插入(使调用不再直接,具有固定的偏移量):

call aFunc1@plt

使用 -Bsymbolic,链接器会将其转换为对 aFunc1 的调用(没有双重间接寻址)。

您也可以通过 GOT 调用函数,类似于 PLT stub 所做的:

jmp *aFunc1@GOTPCREL(%rip)

或者你可以隐藏这个函数:

.hidden aFunc1
jmp aFunc1

请注意,他也会隐藏定义,因此不再导出该函数。要为单个符号模拟 -Bsymbolic 的行为,您可以使用隐藏别名:

.set aFunc1Alias, aFunc1
.hidden aFunc1Alias
jmp aFunc1Alias

使用隐藏函数和隐藏别名,调用将始终转到相同的函数,即不再可能为这个特定调用站点插入符号。

关于c - 从内联汇编调用函数时针对符号重定位 R_X86_64_PC32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48369771/

相关文章:

c - 了解如何将参数传递给 Assembly 中的函数

c - 内存地址计算在 "Smashing The Stack For Fun And Profit"

c - C 中 *ptr += 1 和 *ptr++ 的区别

c++ - 内联值的优化

c - 删除重复值并在其位置添加 0

c - 在 GCC 中拦截函数调用的链接器错误

c - GCC 和乘法指令

assembly - MOV 到宏参数指定的寄存器中

c - 使用超声波传感器时距离等于什么公制单位?

C编程: EXC_BAD_ACCESS