| Crates.io | unarm |
| lib.rs | unarm |
| version | 2.1.0 |
| created_at | 2024-06-01 09:42:23.390231+00 |
| updated_at | 2025-10-25 19:53:24.165173+00 |
| description | Parses ARM instructions |
| homepage | |
| repository | https://github.com/AetiasHax/unarm |
| max_upload_size | |
| id | 1258593 |
| size | 1,350,081 |
Parser for the ARM instruction set, inspired by powerpc-rs. It currently supports the following versions:
It also supports these extensions:
isa.yaml by the /generator/ module.Tested on all 2^32 ARM and Thumb instructions in ARMv6K using the /fuzz/ module on a single thread.
AMD Ryzen 7 7700X:
| Test | Duration | Throughput |
|---|---|---|
| Parse ARM | 27.11s | ~604 MB/s |
| Parse and stringify ARM | 379.15s | ~43 MB/s |
| Parse Thumb | 20.89s | ~392 MB/s |
| Parse and stringify Thumb | 305.58s | ~27 MB/s |
use unarm::*;
let pc = 0;
let options = Options::default();
let ins = parse_arm(0xe5902268, pc, &options);
assert_eq!(
ins,
Ins::Ldr {
cond: Cond::Al,
rd: Reg::R2,
addr: AddrLdrStr::Pre {
rn: Reg::R0,
offset: LdrStrOffset::Imm(0x268),
writeback: false
}
}
);
assert_eq!(ins.display(&options).to_string(), "ldr r2, [r0, #0x268]");
Some instructions in Thumb are 4 bytes long instead of 2. To parse them properly, put the second
half of the instruction in the upper half of the code passed to parse_thumb.
let first = 0xf099;
let second = 0xe866;
let (ins, _size) = parse_thumb(first | (second << 16), 0, &options);
You can do this for 2-byte instructions as well by passing two consecutive instructions in the same way. parse_thumb returns both the parsed instruction and its size, so you can tell if only one or both of the 16-bit words were parsed.
The FormatIns trait is used for formatting an instruction. You can implement this trait yourself to
customize the formatted output. Here is an example:
pub struct MyFormatter {
options: unarm::Options,
}
// Write is a supertrait of FormatIns
impl std::fmt::Write for MyFormatter {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
println!("{s}");
Ok(())
}
}
impl unarm::FormatIns for MyFormatter {
fn options(&self) -> &unarm::Options {
&self.options
}
// Override the default behavior
fn write_reg(&mut self, reg: unarm::Reg) -> core::fmt::Result {
// Add custom behavior here
self.write_str("REG:")?;
reg.write(self)
}
// Override any other trait functions as needed
}
let mut formatter = MyFormatter { options: Default::default() };
let ins = parse_arm(0xe5902268, 0, &formatter.options);
formatter.write_ins(&ins).unwrap();