5 个稳定版本
1.4.0 | 2024年6月29日 |
---|---|
1.3.0 | 2024年6月15日 |
1.2.0 | 2024年6月15日 |
1.1.0 | 2024年6月10日 |
1.0.0 | 2024年6月1日 |
#7 in #opcode
296 每月下载量
15MB
402K SLoC
unarm
ARM指令集的反汇编器,受 ppc750cl 启发。它目前支持以下版本
- ARMv4T
- ARMv5TE
- ARMv6K
内容
反汇编器
/disasm/
模块为支持的 ARM 版本的 ARM 和 Thumb 指令提供了反汇编器。
- 它们由
/generator/
模块从/specs/
目录中的arm.yaml
文件生成。 - 它们接受所有 2^32 个可能的 ARM 指令和 2^16 个可能的 Thumb 指令而不会出错。
- 不保证输出是 100% 正确的。
- 一些非法指令可能不会被解析为非法。
- 一些指令可能无法正确字符串化。
- (更多,可能是)
性能(ARM)
使用 /fuzz/
模块在一个线程上测试了每个支持版本的 2^32 个 ARM 指令
- Intel Core i7-8700: 1.4亿指令/秒 (~534 MB/s)
性能(Thumb)
使用 /fuzz/
模块在一个线程上测试了每个支持版本的 2^16 个 Thumb 指令,平均 100,000 次迭代后
- Intel Core i7-8700: 2.56亿指令/秒 (~488 MB/s)
用法
以下是一个使用 unarm
解析 ARMv5TE 指令的示例。
use unarm::{args::*, v5te::arm::{Ins, Opcode}};
let ins = Ins::new(0xe5902268, &Default::default());
assert_eq!(ins.op, Opcode::Ldr);
let parsed = ins.parse(&Default::default());
assert_eq!(
parsed.args[0],
Argument::Reg(Reg { reg: Register::R2, deref: false, writeback: false })
);
assert_eq!(
parsed.args[1],
Argument::Reg(Reg { reg: Register::R0, deref: true, writeback: false })
);
assert!(matches!(
parsed.args[2],
Argument::OffsetImm(OffsetImm { value: 0x268, post_indexed: false })
));
assert_eq!(parsed.display(Default::default()).to_string(), "ldr r2, [r0, #0x268]");
32位 Thumb 指令
Thumb 使用 16 位指令,以较小的代码大小为代价,牺牲了 ARM 指令的子集。然而,这为 BL/BLX 目标偏移量留下了很少的空间。这意味着超出 ±1KB 的函数调用只能使用寄存器作为目标地址,这总共可能需要 3 或 4 条指令。
为了解决这个问题,Thumb 包含了具有最大 ±4MB 偏移量的 "32 位" BL 和 BLX 指令。实际上,这些只是两个连在一起的 16 位指令。对于 BL,我们称之为 Opcode::BlH
和 Opcode::Bl
。对于 BLX,我们称之为 Opcode::BlH
和 Opcode::BlxI
。BL 和 BLX 的第一条指令相同。
要判断一条指令是否需要合并,可以使用 Ins::is_half_bl(&self)
,它简单检查操作码是否为 Opcode::BlH
。要将两条指令合并为 BL/BLX,使用 ParsedIns::combine_thumb_bl(&self, second: &Self)
。