从内联汇编调用函数时,对符号重新定位R_X86_64_PC32

时间:2018-01-21 17:38:38

标签: 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选项。我不是集会大师所以我不知道它是否正确 - 我试图建立别人的图书馆。也许我应该使用其他选项?

1 个答案:

答案 0 :(得分:3)

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

call aFunc1@plt

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

您也可以通过GOT调用该函数,类似于PLT存根的作用:

jmp *aFunc1@GOTPCREL(%rip)

或者你可以隐藏这个功能:

.hidden aFunc1
jmp aFunc1

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

.set aFunc1Alias, aFunc1
.hidden aFunc1Alias
jmp aFunc1Alias

使用隐藏功能和隐藏别名,呼叫将始终转到相同的功能,即不再可能为此特定呼叫站点插入符号。