AnyPS5动态段重建全解SysVDynamicSectionBuilder如何一步搞定ELF重链接【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5AnyPS5是一款把 PS5 可执行文件自动移植到 Linux 和 Windows 的开源工具无需模拟器或额外运行时。它的核心是relinker负责把 ELF 文件重写为目标系统的原生格式。其中最难、最精妙的部分就是重建动态段Dynamic Section——本文带你读懂负责这块工作的 SysVDynamicSectionBuilder 到底在做什么、为什么这么设计。为什么动态段重建是移植的关键一个 ELF 程序在运行时动态链接器dynamic linker靠PT_DYNAMIC段里的信息知道要加载哪些系统库DT_NEEDED、符号名字在哪动态符号表 字符串表、以及哪些地方需要打补丁重定位表.rela.plt/.rela.dyn。把 PS5 的 ELF 搬到一个全新的宿主系统时原有的动态段无法直接沿用——库名、NID 符号、重定位表都要换成宿主的版本。SysVDynamicSectionBuilder就是从零重新生成这套元数据的组件输出一个SysVDynamicSection结构体定义在 Types.hpp包含动态段数据、动态符号表、字符串表和两份重定位表。它在整个流水线里的位置SysVDynamicSectionBuilder通过接口 ISysVDynamicSectionBuilder 抽象被RelinkerPipeline依赖注入见 RelinkerPipeline.hpp这样可以用测试替身fake来单独验证它的逻辑。整条流水线的执行顺序大致是解析程序头找到PT_DYNAMIC并读出原有动态标签从原有.rela.plt/.rela.dyn中抽取所有 NID 引用可选地做未使用 NID 过滤和 PLT 压缩调用BuildDynamicSection重建新的动态段解析调用点产出最终的RelinkResult。关键调用点在这里RelinkerPipeline先对引用做筛选与压缩再一次性交给构建器见 RelinkerPipeline.cpp。BuildDynamicSection 的四个输入方法签名见 SysVDynamicSectionBuilder.hpp接收四类数据nidReferences每个系统库函数的引用NID 名、所属库、重定位类型、地址、附加值neededLibraries程序声明依赖的系统库列表originalJmprelOffset/originalJmprelCount原.rela.plt表的文件偏移与槽位数量。后两个参数是理解下面槽位校验的钥匙。核心逻辑按槽位严格校验 PLT 重定位构建器把引用分成两类处理R_X86_64_JUMP_SLOTPLT/函数调用和非 PLT 引用如GLOB_DAT、64等数据引用。对前者它做了一个以原表槽位为下标的校验确保重建后的表一一对应、不多不少重定位位置必须落在原.rela.plt表之后否则抛错必须按 24 字节一条Elf64_Rela对齐并换算成槽位索引slotIndex索引不能超过原表大小同一个槽位不允许出现两次防重复。这些校验代码集中在 SysVDynamicSectionBuilder.cpp。为什么这么严格因为 PLT 跳板thunk里硬编码了重定位索引如果槽位缺失或错位运行时的调用会指向错误函数甚至崩溃。构建器要求每个原槽位都必须有一个对应引用宁可报错也不生成残缺的动态段——这正是项目不支持的状态一律抛出std::runtime_error的稳健风格见 README 的说明。逐字节写出四张表校验通过后构建器用一组低层的_append*辅助函数按 ELF64 字节布局精确拼装各张表辅助方法写出的内容_appendU64/_appendI6464 位小端数值_appendDynEntry一条tag val的动态段标签_appendStr往字符串表追加 NUL 结尾字符串并返回偏移_appendElfSym一条 24 字节的Elf64_Sym符号_appendRela一条 24 字节的Elf64_Rela重定位项处理顺序也很讲究见 SysVDynamicSectionBuilder.cpp先放一个空的符号表 0 号项ELF 规范要求按原槽位顺序为每个 PLT 函数建符号、写.rela.plt重定位并推进符号索引symIdx再为所有非 PLT 引用建符号、写.rela.dyn重定位最后把每个依赖库名写成DT_NEEDED标签收尾返回。一个小细节符号名会先做stripHashSuffix处理把 NID 名里#之后的哈希后缀去掉见 源码保证宿主端拿到的是干净的函数名。与 PLT 压缩的协同过滤死代码、重写跳板单独的SysVDynamicSectionBuilder只负责照单写出。真正让它更强大的是与 PltCompactor 的配合当启用严格过滤filter level 2时RelinkerPipeline会先移除从未被调用的 PLT 导入压缩 PLT 表并修补被删除跳板改为陷阱指令然后才把压缩后的引用交给构建器。这样生成的动态段既无冗余符号又保持二进制可执行。这段协作有专门的回归测试覆盖StrictNidFilterTests.cpp 用一段最小 ELF断言压缩后1 个存活 1 个死导入只留下 24 字节.rela.plt和 48 字节符号表且被删跳板被正确置为ud2陷阱——是理解构建器与压缩器边界的最直观示例。如何亲手验证这些行为想在本地跑通可按 BUILD.md 配置构建环境构建约定见 CONVENTIONS.md。相关模块路径一览构建器实现core/relinker/relinker/src/output/SysVDynamicSectionBuilder.cpp接口抽象core/relinker/relinker/include/relinker/domain/ISysVDynamicSectionBuilder.hpp流水线入口core/relinker/relinker/src/pipeline/RelinkerPipeline.cppPLT 压缩器core/relinker/relinker/src/analysis/UnusedNidFilter/PltCompactor.cpp集成测试core/relinker/relinker/tests/StrictNidFilterTests.cpp如需克隆仓库参与研究可使用git clone https://gitcode.com/GitHub_Trending/an/AnyPS5小结为什么这个设计值得学SysVDynamicSectionBuilder看似只是填字节实则把 ELF 动态段最易踩坑的地方都处理干净了以原 PLT 槽位为基准做严格一致性校验、按字节精确拼装四张表、符号/重定位索引自洽递增。它把完整性优先于便利的原则落到了每一处边界检查上这也是 AnyPS5 能在无模拟器的情况下稳定重链接 PS5 二进制的底层原因。读懂它你就掌握了任何 ELF 重链接工具最核心的一环。【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考