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

手动构建x64 ELF文件加载时ld-linux-x86-64.so段错误求助

手动构建x64 ELF文件在新发行版加载崩溃的修复方案

问题背景

  • 手动构建的x64 ELF文件p64在Ubuntu 20.04.x稳定运行10年,近3个月在Ubuntu 22.04、Mint 19.3、Fedora 36、MX Linux MX21上加载崩溃
  • dmesg显示崩溃发生在ld-linux-x86-64.so.2中,触发地址0的段错误
  • 二进制包含10种老旧/罕见重定位格式,未使用GOT/PLT结构
  • 测试现象:
    • 直接运行./p64崩溃
    • 通过/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2直接启动可正常运行
    • 带参数-c -test启动时仍崩溃

核心原因分析

新发行版的ld-linux动态链接器对老旧重定位格式的兼容性逻辑发生了变化,尤其是处理无GOT/PLT结构的二进制时,在命令行参数加载流程中未正确处理罕见重定位,导致空指针引用(地址0的段错误)。

修复方案:添加伪GOT/PLT结构

步骤1:准备工具

使用objcopy、readelf、objdump等ELF分析工具,配合二进制编辑工具(如hexedit或自定义Python脚本)。

步骤2:调整段表,预留GOT/PLT空间

  1. 执行readelf -l p64查看现有段表,找到空闲虚拟地址区域,或扩展现有可执行/可读写段的大小,预留出至少64字节的空间(足够基础GOT/PLT结构使用)
  2. 添加两个新段:
    • .got段:设置权限为可读写(SHF_WRITE | SHF_ALLOC),虚拟地址对齐到8字节
    • .plt段:设置权限为可执行(SHF_EXECINSTR | SHF_ALLOC),虚拟地址对齐到16字节

步骤3:添加GOT/PLT重定位项

  1. 执行readelf -r p64列出所有现有重定位条目
  2. 为每个需要动态解析的符号,添加R_X86_64_GLOB_DAT(用于数据引用)或R_X86_64_JUMP_SLOT(用于函数调用)类型的重定位,指向新创建的GOT表项

步骤4:写入PLT存根代码

在.plt段写入标准x86_64 PLT存根模板:

.plt:
  jmp QWORD PTR [rip+0x0]        ; 跳转到GOT中存储的函数地址
  push 0x0                      ; 对应符号的重定位索引
  jmp .plt+0x10                 ; 跳转到动态链接器的PLT解析入口

同时将GOT表的第一个条目设置为动态链接器的PLT解析器地址(可从正常ELF文件的readelf -d输出中获取)。

步骤5:更新动态段信息

修改.dynamic段,添加DT_PLTGOT条目,指向新创建的GOT段起始地址,确保动态链接器能识别GOT/PLT结构。

步骤6:验证修复

  1. 执行readelf -l -r -d p64确认GOT/PLT段、重定位项和动态段条目已正确配置
  2. 直接运行./p64和./p64 -c -test验证是否崩溃
  3. 查看dmesg确认无地址0的段错误输出

临时替代方案

如果暂时无法修改二进制,可使用Ubuntu 20.04的旧版动态链接器启动:

/path/to/ubuntu20.04/ld-linux-x86-64.so.2 ./p64 -c -test

此方案仅为临时 workaround,长期仍需修改二进制适配新链接器。

内容的提问来源于stack exchange,提问作者Pete Lomax

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:15:39