use std::str::FromStr;
use super::{GenericState, GenericStep, State, Step};
use bitflags::bitflags;
#[derive(Clone, Debug)]
pub struct Aarch64Step {
state: Aarch64State,
code: [u8; 4],
address: u64,
strace: Option<String>,
memory_ops: Vec<super::MemoryOp>,
}
impl Step<32> for Aarch64Step {
type STATE = Aarch64State;
fn code(&self) -> &[u8] {
&self.code[..]
}
fn state(&self) -> &Aarch64State {
&self.state
}
fn address(&self) -> u64 {
self.address
}
fn strace(&self) -> Option<&String> {
self.strace.as_ref()
}
fn memory_ops(&self) -> &[super::MemoryOp] {
&self.memory_ops[..]
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Aarch64Flags: u32 {
const NEGATIVE = 1 << 31;
const ZERO = 1 << 30;
const CARRY = 1 << 29;
const OVERFLOW = 1 << 28;
const CUMULATIVE_SATURATION = 1 << 27;
const SSBS = 1 << 23;
const PAN = 1 << 22;
const DIT = 1 << 21;
const GE_0 = 1 << 19;
const GE_1 = 1 << 18;
const GE_2 = 1 << 17;
const GE_3 = 1 << 16;
const ENDIANNESS = 1 << 9; const A = 1 << 8; const IRQ = 1 << 7; const FIQ = 1 << 6; const PE_0 = 1 << 3; const PE_1 = 1 << 2;
const PE_2 = 1 << 1;
const PE_3 = 1 << 0;
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Aarch64State {
regs: [u64; 32],
pc: u64,
flags: Aarch64Flags,
}
impl State<32> for Aarch64State {
type FLAGS = Aarch64Flags;
fn pc(&self) -> u64 {
self.pc
}
fn regs(&self) -> &[u64; 32] {
&self.regs
}
fn flags(&self) -> &Aarch64Flags {
&self.flags
}
fn reg_name(i: usize) -> &'static str {
[
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13",
"x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25",
"x26", "x27", "x28", "x29", "x30", "sp", "xzr",
][i]
}
}
impl FromStr for Aarch64State {
type Err = anyhow::Error;
fn from_str(input: &str) -> anyhow::Result<Self> {
let generic: GenericState<u64, 32> = GenericState::from_str(input)?;
Ok(Self {
regs: generic.regs,
pc: generic.pc,
flags: Aarch64Flags::from_bits_retain(generic.flags as u32),
})
}
}
impl TryFrom<&[String]> for Aarch64Step {
type Error = anyhow::Error;
fn try_from(input: &[String]) -> anyhow::Result<Self> {
let generic: GenericStep<Aarch64State> = GenericStep::try_from(input)?;
Ok(Self {
state: generic.state,
code: generic.code.try_into().unwrap(),
address: generic.address,
strace: generic.strace,
memory_ops: generic.memory_ops,
})
}
}
#[cfg(test)]
mod tests {
use super::Aarch64State;
use crate::state::Aarch64Flags;
use std::str::FromStr;
#[test]
fn aarch64_state_from_string() {
let input = "r0=0|r1=0|r2=0|r3=0|r4=0|r5=0|r6=0|r7=0|r8=0|r9=0|r10=0|r11=0|r12=0|r13=0|r14=0|r15=0|r16=0|r17=0|r18=0|r19=0|r20=0|r21=0|r22=0|r23=0|r24=0|r25=0|r26=0|r27=0|r28=0|r29=0|r30=0|r31=0|pc=0|flags=0";
let result = Aarch64State::from_str(input);
assert!(result.is_ok());
assert_eq!(
result.unwrap(),
Aarch64State {
regs: [0; 32],
pc: 0,
flags: Aarch64Flags::empty(),
}
);
}
}