我正在尝试构建共享库,这些库在程序集中具有一些调用其他函数的函数。当我使用代码
构建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
选项。我不是集会大师所以我不知道它是否正确 - 我试图建立别人的图书馆。也许我应该使用其他选项?
答案 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
使用隐藏功能和隐藏别名,呼叫将始终转到相同的功能,即不再可能为此特定呼叫站点插入符号。