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

Download history 252/week @ 2024-06-01 171/week @ 2024-06-08 315/week @ 2024-06-15 17/week @ 2024-06-22 155/week @ 2024-06-29 17/week @ 2024-07-06 62/week @ 2024-07-13 206/week @ 2024-07-20 7/week @ 2024-07-27

296 每月下载量

MIT 许可证

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::BlHOpcode::Bl。对于 BLX,我们称之为 Opcode::BlHOpcode::BlxI。BL 和 BLX 的第一条指令相同。

要判断一条指令是否需要合并,可以使用 Ins::is_half_bl(&self),它简单检查操作码是否为 Opcode::BlH。要将两条指令合并为 BL/BLX,使用 ParsedIns::combine_thumb_bl(&self, second: &Self)

无运行时依赖

功能