Linux中没有符号插入的共享对象,-fno-semantic-interposition错误 [英] Shared object in Linux without symbol interposition, -fno-semantic-interposition error

查看:44
本文介绍了Linux中没有符号插入的共享对象,-fno-semantic-interposition错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类 Unix 系统中的共享对象 (*.so) 由于符号插入而效率低下:每次访问 .so 中的全局变量都需要 GOT 查找,并且每次从一个函数调用 .so 中的另一个函数需要 PLT 查找.因此,我很高兴看到 gcc 5.1 版添加了选项 -fno-semantic-interposition.但是,当我尝试在一个函数调用另一个函数而不使用 PLT 的情况下创建 .so 时,我收到错误消息:

<块引用>

重定位R_X86_64_PC32针对符号`functionname'在制作共享对象时不能使用;用 -fPIC 重新编译

我希望选项 -fno-semantic-interposition 可以消除此错误消息,但事实并非如此.-mcmodel=large 也无济于事.对函数的引用确实与位置无关,错误消息实际上证实了这一点(R_X86_64_PC32 表示 64 位模式下的 PC 相对 32 位重定位).-fPIC 并不是真的意味着位置无关,顾名思义,它实际上意味着使用 GOT 和 PLT.

我不能使用 __attribute__((visibility ("hidden"))) 因为被调用的函数和调用者是在单独的文件中编译的(调用者在 C++ 中,被调用的函数在汇编中).

我尝试制作一个程序集列表以查看选项 -fno-semantic-interposition 的作用.我发现当一个函数调用同一个文件中的另一个函数时,它会引用本地别名,但在调用另一个文件中的函数时它仍然使用 PLT.

(g++ 版本为 5.2.1 Ubuntu,64 位模式).

有没有办法让链接器在没有 GOT/PLT 查找的情况下接受 .so 中的交叉引用?

解决方案

有没有办法让链接器在没有 GOT/PLT 查找的情况下接受 .so 中的交叉引用?

是的:attribute((visibility("hidden"))) 正是这样做的方法.

<块引用>

我不能使用 attribute((visibility ("hidden"))) 因为被调用的函数和调用者是在单独的文件中编译的

您感到困惑:visibility("hidden") 表示该符号在最终链接时不会从共享库中导出.但该符号是全局并且在最终链接之前在多个翻译单元中可见.

证明:

$ cat t1.cextern int foo() __attribute__((visibility("hidden")));int main() { 返回 foo();}$猫t2.cint foo() __attribute__((visibility("hidden")));int foo() { 返回 42;}$ gcc -c -fPIC t1.c t2.c$ gcc -shared t1.o t2.o -o t.so$ nm -D t.so |grep foo$

<块引用>

我尝试制作一个程序集列表以查看选项 -fno-semantic-interposition 的作用.我发现当一个函数调用同一个文件中的另一个函数时,它会引用本地别名,但在调用另一个文件中的函数时它仍然使用 PLT.

如果您阅读了 gcc-patches 中的讨论,您会看到 讨论code>-fno-semantic-interposition 是关于允许内联可能插入的函数,而不是关于它们在未内联时实际调用的方式.

Shared objects (*.so) in Unix-like systems are inefficient because of the symbol interposition: Every access to a global variable inside the .so needs a GOT lookup, and every call from one function to another inside the .so needs a PLT lookup. I was therefore happy to see that gcc version 5.1 has added the option -fno-semantic-interposition. However, when I try to make a .so where one function calls another without using a PLT, I get the error message:

relocation R_X86_64_PC32 against symbol `functionname' can not be used when making a shared object; recompile with -fPIC

I expected the option -fno-semantic-interposition to eliminate this error message, but it doesn't. -mcmodel=large doesn't help either. The reference to the function is indeed position-independent, which the error message actually confirms (R_X86_64_PC32 means PC-relative 32-bit relocation in 64-bit mode). -fPIC does not really mean position-independent, as the name would imply, it actually means use GOT and PLT.

I cannot use __attribute__((visibility ("hidden"))) because the called function and the caller are compiled in seperate files (caller is in C++, called function is in assembly).

I tried to make an assembly listing to see what the option -fno-semantic-interposition does. I found out that it makes a reference to a local alias when one function calls another in the same file, but it still uses a PLT when calling a function in another file.

(g++ version is 5.2.1 Ubuntu, 64-bit mode).

Is there a way to make the linker accept a cross-reference inside a .so without the GOT/PLT lookup?

解决方案

Is there a way to make the linker accept a cross-reference inside a .so without the GOT/PLT lookup?

Yes: attribute((visibility("hidden"))) is exactly the way to do it.

I cannot use attribute((visibility ("hidden"))) because the called function and the caller are compiled in seperate files

You are confused: visibility("hidden") means that the symbol will not be exported from the shared library, when it is finally linked. But the symbol is global and visible across multiple translation units before that final link.

Proof:

$ cat t1.c
extern int foo() __attribute__((visibility("hidden")));

int main() { return foo(); }
$ cat t2.c
int foo() __attribute__((visibility("hidden")));
int foo() { return 42; }
$ gcc -c -fPIC t1.c t2.c
$ gcc -shared t1.o t2.o -o t.so
$ nm -D t.so | grep foo
$

I tried to make an assembly listing to see what the option -fno-semantic-interposition does. I found out that it makes a reference to a local alias when one function calls another in the same file, but it still uses a PLT when calling a function in another file.

If you read the discussion in gcc-patches, you'll see that the -fno-semantic-interposition is about allowing inlining of possibly interposable functions, not about the way they are actually called when not inlined.

这篇关于Linux中没有符号插入的共享对象,-fno-semantic-interposition错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆