资讯动态

如何读懂AnyPS5的导出表?APS5_VABI宏与NID命名规范完全指南

发布时间:2026/10/9 7:20:26 来源:尧图企业网站定制
如何读懂AnyPS5的导出表APS5_VABI宏与NID命名规范完全指南【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5AnyPS5 是一款用于将 PS5 可执行文件自动移植到 Linux 和 Windows 的工具核心由 relinker把 ELF 转换成目标系统原生格式和 系统 PRX 库实现 组成无需模拟器或独立运行时。要理解它为什么能在两个平台上都跑起来关键就在于读懂导出表游戏可执行文件里成千上万个对系统库的调用最终都要靠名字对得上才能被链接。本文带你用最短路径掌握APS5_VABI宏与 NIDNode ID命名规范这两大核心机制 为什么导出表是移植的关键PS5 上的程序是 x86-64 ELF它调用libSceRandom、libSceHttp等系统库时走的是动态链接的导出符号表。AnyPS5 的思路很直接用 C 重新实现这些系统库并保证导出符号与原机完全一致。每个系统库对应一个Export.cpp例如随机数库 libSceRandom/Export.cppextern C { int APS5_VABI sceRandomGetRandomNumber(void* buf, size_t size) { // ... } }这里有两个必须理解的细节APS5_VABI宏和sceRandomGetRandomNumber这个名字。前者解决怎么调用后者涉及叫什么名字。APS5_VABI 宏强制使用 SysV 调用约定宏定义在哪里宏只有一处定义VabiMacros.hpp#ifdef _WIN32 #define APS5_VABI __attribute__((sysv_abi)) #else #define APS5_VABI #endif规则一目了然Linux 下宏展开为空什么都不做Windows 下展开为__attribute__((sysv_abi))强制该函数使用 SysV 调用约定而非 Windows x64 ABI为什么 Windows 必须特殊处理这是整个项目里最反直觉的一处设计。同一份 x86-64 代码两个平台的调用约定完全不同对比项LinuxSysV ABIWindowsMS ABI返回值64 位rax高 32 位在edx异常展开C 标准机制SEH / 特殊展开数据整数参数寄存器rdi, rsi, rdx...rcx, rdx, r8...PS5 上的游戏代码按 SysV 约定调用系统库。当这些客端代码在 Windows 上运行时宿主侧实现若按 Windows ABI 编译双方就会在寄存器上鸡同鸭讲。因此所有会被客端代码直接调用的导出函数都加上APS5_VABI在 Windows 上伪装成 Linux 函数从而保证同一份实现跨平台可链接。这也是整个仓库中数百个Export.cpp与内部实现里随处可见该宏的原因libc、libkernel、字体、网络等模块均在 libc/include/general/VabiMacros.hpp 上复用同一约定。NID 命名规范11 个字符的函数指纹什么是 NID在 PS5以及 PS4系统库中很多函数并不以明文名字导出而是导出为一串 11 字符的哈希——即NIDNode ID形如AaBbCcDdEeFG。客端代码引用libSceHttp.prx时导入表里写的就是这串哈希。所以 AnyPS5 不能只导出sceHttpOpen这种可读名字还必须同时提供它对应的 NID。这个名字 → 哈希的转换由 core/libs/nid/ 模块统一完成。NID 是怎么算出来的算法实现在 NidCompute.cpp步骤可以概括为四步拼盐把函数名的 ASCII 字节拼上一个固定的 16 字节盐值kNidSuffix摘要对结果做 SHA-1截取反转取摘要最后 8 个字节并逆序编码用自定义 base64 字母表A–Z a–z 0–9 -编码成 11 个字符也就是说NID 是函数名去除后缀修饰后的确定性哈希——同一个名字在任何机器上算出的 NID 都相同这正是链接能对上的根本原因。批量解析ResolveNids 的判断流程单个库的所有导出符号由 NidResolver.cpp 统一处理对每个导出名按以下优先级判断名字 → 是排除名单 是 → 原样保留 → 以 _nid_no_patch_cut 结尾 是 → 去掉该后缀后保留 → 以 _nid_no_patch 结尾或 SDL_ 开头 是 → 原样保留 → 同库存在名字_nid_postfix版本 是 → 原名保留 → 否则 → ComputeNid(去掉后缀, 库名)这个流程解释了后文所有后缀的用途。读懂 Export.cpp 的 5 种命名后缀写或阅读Export.cpp时真正的规范体现在函数名上。所有标记常量集中定义在 NidPatcherUtils.hpp后缀 / 前缀含义最终导出名sceFoo普通名默认行为会被计算 NIDNID 哈希sceFoo_nid_postfix显式标记这个名字要转成 NID与同名普通函数成对出现时普通名也保留NID 哈希sceFoo_nid_no_patch永不改名按明文导出有些函数在原机上就是明文导出的sceFoosceFoo_nid_no_patch_cut导出时去掉整个后缀sceFoosceFoo_nid_disambigN多个同名导出需要消歧时哈希前缀的 N 会被剥掉再计算按sceFoo的 NIDSDL_xxx前缀宿主侧真实使用的符号不参与 NID 转换原样配套工具 tools/nid_names.py 可以按名字批量算出 NID方便在写导出表时核对。relinker 如何把 NID 写进二进制导出表的落地发生在 relinker 重新链接阶段Linux/ELF 输出ElfNidPatcher.cpp 重写.dynsym/.dynstr重排动态符号表、重建gnu.hash哈希表、修正重定位中的符号索引——改名后这些结构必须同步更新否则动态链接器找不到符号Windows/PE 输出PeNidPatcher.cpp 对 PE 导出表做同样的名字替换统一入口BinaryPatcherFactory 根据文件头自动选择 ELF 还是 PE 打补丁对使用者来说这一步是全自动的把输入 ELF 和sce_module/目录交给relinker用法见 docs/user/USAGE.md即可NID 改名发生在内部。新手学习路线与文件地图按顺序读这四个地方基本就能看懂整个导出体系core/libs/prx/libc/include/general/VabiMacros.hpp ——APS5_VABI的全部秘密不到 10 行core/libs/prx/libSceRandom/Export.cpp —— 最小的完整系统库示例建议对照 guest_random 测试 看效果core/libs/nid/include/nid/NidPatcherUtils.hpp —— 所有命名后缀的字典core/libs/nid/src/NidCompute.cpp —— NID 哈希算法本体更多系统库可以沿着 core/libs/prx/ 目录逐个浏览每个目录就是一个libSce*.prx的完整实现项目整体约定见 docs/dev/CONVENTIONS.md。常见问题速答Q为什么 Linux 上APS5_VABI是空宏因为 Linux 默认就是 SysV ABI不需要任何干预宏只在 Windows 上生效。QNID 和库名有关吗ComputeNid的第二个参数是库名但当前计算只用到了函数名和盐值库名参数保留了解析上下文的完整性。Q我怎么知道一个函数该用明文还是 NID看原机 prx 的实际导出表原机明文导出的函数加_nid_no_patchNID 导出的用默认行为或_nid_postfix标记。Q改了导出名后 Windows 输出会坏吗不会。PE 与 ELF 打补丁器分别负责各自格式BinaryPatcherFactory会自动选择两种输出走同一套名字解析逻辑。掌握了APS5_VABI跨平台调用约定 NID 五后缀导出命名这两套规则你阅读 core/libs/prx/ 下任何一个Export.cpp都不会再迷路 ✅【免费下载链接】AnyPS5Tool for automatic PS5 executables porting to Linux and Windows项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑