Crates.io | unarm |
lib.rs | unarm |
version | 1.6.1 |
source | src |
created_at | 2024-06-01 09:42:23.390231 |
updated_at | 2024-10-20 06:17:09.59624 |
description | Disassembles ARM instructions |
homepage | |
repository | https://github.com/AetiasHax/unarm |
max_upload_size | |
id | 1258593 |
size | 6,479,451 |
Disassembler for the ARM instruction set, inspired by ppc750cl. It currently supports the following versions:
The /disasm/
module has disassemblers for ARM and Thumb instructions of the supported versions of ARM.
arm.yaml
files in the /specs/
directory by the /generator/
module.Tested on all 2^32 ARM instructions in each supported version using the /fuzz/
module on a single thread:
Tested on all 2^16 Thumb instructions in each supported version using the /fuzz/
module on a single thread,
averaged after 100,000 iterations:
Below is an example of using unarm
to parse an ARMv5TE instruction.
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]");
Thumb uses 16-bit instructions, trading a subset of ARM instructions for smaller code size. However, this leaves little room for BL/BLX target offsets. This would mean that function calls further than ±1KB away would only be possible using a register as target address, which could take 3 or 4 instructions in total.
To solve this, Thumb includes "32-bit" BL and BLX instructions with a maximum offset of ±4MB. In truth, these are just two
16-bit instructions strung together. For BL, we call them Opcode::BlH
and Opcode::Bl
. For BLX, we call them Opcode::BlH
and Opcode::BlxI
. The first instruction is the same for BL and BLX.
To tell if an instruction needs to be combined, you can use Ins::is_half_bl(&self)
, which simply checks if the opcode is
Opcode::BlH
. To combine two instructions into a BL/BLX, use ParsedIns::combine_thumb_bl(&self, second: &Self)
.