You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否不借助共享库强制函数调用通过PLT链接?

如何不使用共享库强制函数调用通过PLT链接?

可以,不需要依赖共享库就能实现强制函数调用走PLT,以下是几种验证有效的方法(基于Linux下GCC/Clang测试):

方法1:使用链接器--plt选项

给链接器传递-Wl,--plt参数,强制链接器为所有非隐藏函数调用生成PLT跳转,即使函数定义在当前可执行内部。修改你的编译命令如下:

$CC main.c fn.c -fpie -fpic -fplt -Wl,--plt -rdynamic -pie -Os && time ./a.out 1

这个选项会让链接器放弃对内部函数的直接绑定优化,统一走PLT路径。你可以通过objdump -d ./a.out查看main中的调用指令,会看到callq *fn@GOTPLT(%rip)这类PLT相关的指令,执行时间也会和动态库版本接近。

方法2:标记函数为弱符号

在函数定义上添加__attribute__((weak))属性,让链接器认为该函数可能被外部动态覆盖,从而自动生成PLT调用。修改fn.c内容:

__attribute__((weak)) void fn(void){}
__typeof(fn) fn_H __attribute((alias("fn"),visibility("hidden")));

然后使用你原来的PIE编译命令即可:

$CC main.c fn.c -fpie -fpic -fplt -rdynamic -pie -Os && time ./a.out 1

弱符号的特性决定了链接器不会进行直接绑定,必须通过PLT来解析,确保运行时可以被外部模块替换。

方法3:使用链接器动态列表显式导出符号

创建一个动态列表文件(比如dyn_list.txt),显式指定需要动态解析的符号:

{
    extern "C" {
        fn;
    };
};

编译时通过-Wl,--dynamic-list=dyn_list.txt告诉链接器将fn当作动态符号处理:

$CC main.c fn.c -fpie -fpic -fplt -Wl,--dynamic-list=dyn_list.txt -pie -Os && time ./a.out 1

这种方式可以精准控制哪些符号走PLT,适合只需要对特定函数生效的场景。

原理说明

在PIE可执行文件中,链接器默认会对内部可见的函数进行直接绑定优化(跳过PLT),因为它认为这些符号不会被外部修改。上述方法本质都是打破这种优化:要么强制链接器生成PLT,要么让链接器认为符号可能被外部动态修改,从而必须通过PLT进行间接调用。

内容的提问来源于stack exchange,提问作者Petr Skocik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:07:42