我正在尝试构建共享库,这些共享库在程序集中具有一些调用其他函数的函数。当我使用代码构建 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/