这里简单介绍一下这是关于什么的。我来自 PSVita homebrew 社区,Andy Nguyen 在那里制作了
so-loader
,基本上是一个库,允许我们通过解析导入并应用一些补丁来执行 Android .so。这是一个成功的实践,使得许多优秀的游戏无需源代码即可移植到该平台,其中一些是 ARMv6,但大多数是 ARMv7(例如《战地:叛逆连队 2》、《华氏度》、《GTA:SA》等)。
这个过程中有趣的一点是,Android 不支持硬浮点 ABI,因此我们有一个完全编译的 SDK 版本,可与 softfp 一起使用,以实现端到端兼容的调用约定。
这一切都非常有效,直到出现了这个特殊的
.so
,它显然是为 ARMv6 制作的。它似乎对调用约定有自己的理解,与我们可以提供的不兼容,但我不明白为什么以及如何修复它。简而言之,有许多与 VFP 相关的指令在我们的 ARMv7-softfp 设备 PSVita 上运行时会导致“未定义指令异常”。此类指令的一些示例取自 Ghidra disasm of this .so:
0026f17c 00 4a 24 7e vmulvc.f32 s8,s8,s0
00264bc0 00 4a 24 ee vmul.f32 s8,s8,s0
00264bc4 4c 8a 38 ee vsub.f32 s16,s24
00264bc8 08 ca 04 ee vmla.f32 s24,s8,s16
0025e330 48 6a b0 ee vmov.f32 s12,s16
对于这个问题,我确信有几件事:
只有这些指令才是问题,因为如果我用 NOP 强制修补它们 (
0xe1a00000
用工作等效物修补这些?
。 so_loader 的工作原理示例可以在创建者的 github 上找到:https://github.com/TheOfficialFloW/gtasa_vita/
编辑:根据评论中的要求,我添加了一些do有效的示例。这些内容取自同一游戏,但版本较新。这个版本根本没有任何未定义的指令崩溃,但不幸的是我们无法使用它,因为在新版本中开发人员取消了物理控件支持:)
003cafac 27 7a 67 ee vmul.f32 s15,s14,s15
001a253c 87 7a 46 ee vmla.f32 s15,s13,s14
001a2540 e8 7a f4 ee vcmpe.f32 s15,s17
001a2528 27 7a 67 ee vmul.f32 s15,s14,s15
000bf9d4 a7 5a 75 ee vadd.f32 s11,s11,s15
000bf9d8 64 7a f0 ee vmov.f32 s15,s9
进一步分析表明,两个版本之间的区别在于,损坏的版本使用了VFP短向量特征。具体来说,您可以在崩溃函数中看到启用了类似这样的短向量模式:
00264a58 10 0a f1 ee vmrs param_1,fpscr
00264a5c 37 08 c0 e3 bic param_1,param_1,#0x370000=>LAB_00360000
00264a60 07 08 80 e3 orr param_1,param_1,#0x70000
00264a64 10 0a e1 ee vmsr fpscr,param_1
PSVita 的 CPU 是 Cortex A9,根据ARM 开发人员文档Cortex-A9 FPU 硬件不支持已弃用的 VFP 短向量功能。当 FPSCR.LEN 字段非零时尝试执行 VFP 数据处理指令会导致 FPSCR.DEX 位被置位并发生同步未定义指令异常。如果需要,您可以使用软件来模拟短矢量特征。
用软件来模拟短向量特征看来,我们需要
。现在的问题是:如何。