GCC 5.3增加了一个新选项: -fno-semantic-interposition
新的-fno-semantic-interposition选项可用于提高共享库的代码质量,其中不允许插入导出的符号.
这听起来像是对C++项目有用的东西,其中插入不能用于任何原因,但延迟是一个问题.
但是,描述相当模糊.有人能够澄清这个选项是如何工作的吗?
我不确定这个问题的主题是什么,但是我们走了......
为了强制代码的关键部分的代码局部性/紧凑性,我正在寻找一种方法在调用时R_X86_64_JUMP_SLOT直接通过"跳槽"(ELF 重定位)在外部(动态加载)库中调用函数site - 链接器通常放入PLT/GOT的内容,但是在调用站点上有这些内联.
如果我模仿这样的调用:
#include <stdio.h>
int main(int argc, char **argv)
{
asm ("push $1f\n\t"
"jmp *0f\n\t"
"0: .quad %P0\n"
"1:\n\t"
: : "i"(printf), "D"("Hello, World!\n"));
return 0;
}Run Code Online (Sandbox Code Playgroud)
为了得到一个64位字的空间,电话本身是有效的(拜托,没有评论这是幸运的巧合,因为这打破了某些ABI规则 - 所有这些都不是这个问题的主题......并且,对于我的情况,可以工作围绕/以其他方式解决,我试图保持这个例子简短).
它创建以下程序集:
0000000000000000 <main>:
0: bf 00 00 00 00 mov $0x0,%edi
1: R_X86_64_32 .rodata.str1.1
5: 68 00 00 00 00 pushq $0x0
6: R_X86_64_32 .text+0x19
a: ff 24 25 00 00 00 00 jmpq *0x0
d: R_X86_64_32S .text+0x11
...
11: R_X86_64_64 printf
19: 31 … 类Unix系统中的共享对象(*.so)由于符号插入而效率低下:.so内部对全局变量的每次访问都需要GOT查找,而.so内部从一个函数到另一个函数的每次调用都需要一个PLT抬头.因此,我很高兴看到gcc版本5.1添加了选项-fno-semantic-interposition.但是,当我尝试在没有使用PLT的情况下创建一个函数调用另一个函数的.so时,我收到错误消息:
在创建共享对象时,不能使用符号`functionname'重定位R_X86_64_PC32; 用-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内的交叉引用?