fuz*_*fuz 6 c x86 gcc position-independent-code plt
考虑以下功能:
extern void test1(void);
extern void test2(void) {
test1();
}
Run Code Online (Sandbox Code Playgroud)
这是gcc -fpic在amd64 Linux上生成的代码:
test2:
jmp test1
Run Code Online (Sandbox Code Playgroud)
当我编译时-fpic,gcc显式调用PLT来启用符号插入:
test2:
jmp test1@PLT
Run Code Online (Sandbox Code Playgroud)
然而,这对于与位置无关的代码并不是严格需要的,如果我不想支持,可能会被遗漏.如有必要,链接器仍然会将跳转目标重写为PLT符号.
如何在不更改源代码且不使编译代码不适合共享库的情况下,使函数调用直接转到其目标而不是通过PLT显式转换?
如果你声明test1()隐藏(__attribute__((__visibility__("hidden"))),则跳转将是直接的。
Nowtest1()可能不会在其源翻译单元中定义为隐藏,但我相信这种差异不会造成任何损害,除了 C 语言保证&test1 == &test1在运行时被破坏,如果其中一个指针是通过隐藏引用获得的,而另一个指针是通过公共引用(公共引用可能是通过预加载或位于查找范围中当前引用之前的 DSO 插入的,而隐藏引用(导致直接跳转)有效防止任何类型的插入)
处理这个问题的更合适的方法是定义两个名称test1()\xe2\x80\x94a 公共名称和私有/隐藏名称定义两个名称。
在 gcc 和 clang 中,这可以通过一些别名魔法来完成,这只能在定义符号的翻译单元中完成。
\n\n宏可以使它更漂亮:
\n\n#define PRIVATE __attribute__((__visibility__("hidden")))\n#define PUBLIC __attribute__((__visibility__("default")))\n#define PRIVATE_ALIAS(Alias,OfWhat) \\\n extern __typeof(OfWhat) Alias __attribute((__alias__(#OfWhat), \\\n __visibility__("hidden")))\n\n#if HERE\nPUBLIC void test1(void) { }\nPRIVATE_ALIAS(test1__,test1);\n#else\nPUBLIC void test1(void);\nPRIVATE void test1__(void);\n#endif\n\nvoid call_test1(void) { test1(); }\nvoid call_test1__(void) { test1__(); }\n\nvoid call_ext0(void) { void ext0(void); ext0(); }\nvoid call_ext1(void) { PRIVATE void ext1(void); ext1(); }\nRun Code Online (Sandbox Code Playgroud)\n\n上面将 (-O3, x86-64) 编译为:
\n\ncall_test1:\n jmp test1@PLT\ncall_test1__:\n jmp test1__\ncall_ext0:\n jmp ext0@PLT\ncall_ext1:\n jmp ext1\nRun Code Online (Sandbox Code Playgroud)\n\n(定义 HERE=1 还会内联 test1 调用,因为它很小且是本地的,并且 -O3 处于打开状态)。
\n\n现场示例https://godbolt.org/g/eZvmp7。
\n| 归档时间: |
|
| 查看次数: |
789 次 |
| 最近记录: |