如何创建部分符号即时解析、部分延迟解析的ELF可执行文件?
单符号级ELF绑定控制方案
能否通过链接器参数直接实现?
GNU链接器(ld)没有原生的单符号级绑定控制选项,但可以通过代码配合链接器选项或自定义链接器脚本实现需求,无需补丁二进制文件。如果严格要求纯链接器参数(无代码/脚本修改),则需要补丁ELF文件。
无需补丁的实现方法
方法1:地址引用触发立即解析
默认情况下,链接器对函数调用采用延迟绑定(PLT机制),对符号地址的直接引用采用启动时立即解析(直接填充GOT)。只需在代码中对需要立即解析的符号添加地址引用(无需调用函数):
// 需要立即解析的符号 extern void foo(void); // 仅声明地址引用,不会执行函数逻辑 static void (*__unused_foo_ptr)(void) = foo; // 保持延迟绑定的符号 extern void bar(void); void call_bar() { // 通过函数调用触发PLT延迟绑定 bar(); }
编译后,foo会在启动时被立即解析,bar则在首次调用时延迟解析。
方法2:链接器脚本重定向重定位段
编写自定义链接器脚本,将指定符号的重定位从PLT延迟段(.rel.plt/.rela.plt)移到立即解析段(.rel.dyn/.rela.dyn):
// 继承系统默认链接器脚本(以x86_64为例) INCLUDE /usr/lib/ldscripts/elf_x86_64.x // 定义需要立即解析的符号匹配规则 IMMEDIATE_SYMBOLS { *foo*; // 匹配所有含foo的符号 } // 重定位段调整 SECTIONS { .rel.dyn : { *(.rel.dyn) // 将目标符号的PLT重定位移到立即解析段 *(IMMEDIATE_SYMBOLS.rel.plt) } .rel.plt : { // 排除已移走的符号,保留其他符号的延迟绑定 *(!IMMEDIATE_SYMBOLS.rel.plt) } }
编译时指定脚本:
gcc -o myprog myprog.c -Wl,-T,my_script.ld
需要补丁二进制的场景(纯链接器参数无法实现时)
如果必须不修改代码/脚本,仅通过补丁二进制实现,步骤如下:
- 查看重定位表:用
readelf -r myprog找到目标符号的R_X86_64_JUMP_SLOT(PLT延迟)条目。 - 修改重定位类型:将该条目的类型从
R_X86_64_JUMP_SLOT改为R_X86_64_GLOB_DAT(立即解析)。 - 移动重定位条目:将该条目从
.rel.plt/.rela.plt段移到.rel.dyn/.rela.dyn段。 - 更新段表与动态节:调整
DT_REL/DT_RELENT(或DT_RELA/DT_RELAENT)的计数,确保动态链接器能正确识别。
可以用objcopy或pyelftools等工具完成这些修改。
内容的提问来源于stack exchange,提问作者Fee
相关产品推荐
相关产品推荐

