balrog.git


balrog

~ ELF file analysis tool to be used after firmware extraction
git clone https://github.com/djnnvx/balrog.git
log | files | refs | archive | README

arm.rs (2681B)

      1 use super::{imm, mem, reg, Kind, Op, HIGH_HALF_SHIFT, IMM16_MASK};
      2 use crate::load::Binary;
      3 use capstone::arch::arm::ArmReg;
      4 
      5 const PC_BIAS: u64 = 8;
      6 const WORD: usize = 4;
      7 
      8 pub const ARG_REGS: [u16; 4] = [
      9     ArmReg::ARM_REG_R0 as u16,
     10     ArmReg::ARM_REG_R1 as u16,
     11     ArmReg::ARM_REG_R2 as u16,
     12     ArmReg::ARM_REG_R3 as u16,
     13 ];
     14 
     15 pub const SP: u16 = ArmReg::ARM_REG_SP as u16;
     16 
     17 fn pc_relative(addr: u64, disp: i64) -> u64 {
     18     addr.wrapping_add(PC_BIAS).wrapping_add(disp as u64)
     19 }
     20 
     21 fn literal(addr: u64, disp: i64, bin: &Binary) -> Option<u64> {
     22     let pool = pc_relative(addr, disp);
     23     let word: [u8; WORD] = bin.read_vaddr(pool, WORD)?.try_into().ok()?;
     24     Some(if bin.little {
     25         u32::from_le_bytes(word) as u64
     26     } else {
     27         u32::from_be_bytes(word) as u64
     28     })
     29 }
     30 
     31 pub fn decode(mnemonic: &str, o: &[Op; 3], addr: u64, bin: &Binary) -> Option<Kind> {
     32     match mnemonic {
     33         "bl" | "blx" => match o[0] {
     34             Op::Imm(target) => Some(Kind::Call(target as u64)),
     35             Op::Reg(r) => Some(Kind::CallInd { reg: r }),
     36             _ => None,
     37         },
     38         "bx" => Some(Kind::Ret),
     39         "movw" => {
     40             let low_half = (imm(o, 1)? as u64) & IMM16_MASK;
     41             Some(Kind::SetConst {
     42                 dst: reg(o, 0)?,
     43                 val: low_half,
     44             })
     45         }
     46         "movt" => {
     47             let high_half = ((imm(o, 1)? as u64) << HIGH_HALF_SHIFT) as i64;
     48             Some(Kind::AddImm {
     49                 dst: reg(o, 0)?,
     50                 base: reg(o, 0)?,
     51                 imm: high_half,
     52             })
     53         }
     54         "ldr" => {
     55             let (base, disp) = mem(o, 1)?;
     56             let dst = reg(o, 0)?;
     57             if base == ArmReg::ARM_REG_PC as u16 {
     58                 Some(Kind::PcVal {
     59                     dst,
     60                     val: literal(addr, disp, bin)?,
     61                 })
     62             } else {
     63                 Some(Kind::Load { dst, base, disp })
     64             }
     65         }
     66         "add" => {
     67             let (dst, base) = (reg(o, 0)?, reg(o, 1)?);
     68             if base == ArmReg::ARM_REG_PC as u16 {
     69                 Some(Kind::SetConst {
     70                     dst,
     71                     val: pc_relative(addr, imm(o, 2)?),
     72                 })
     73             } else {
     74                 Some(Kind::AddImm {
     75                     dst,
     76                     base,
     77                     imm: imm(o, 2)?,
     78                 })
     79             }
     80         }
     81         "sub" => Some(Kind::AddImm {
     82             dst: reg(o, 0)?,
     83             base: reg(o, 1)?,
     84             imm: -imm(o, 2)?,
     85         }),
     86         "mov" => Some(Kind::Mov {
     87             dst: reg(o, 0)?,
     88             src: reg(o, 1)?,
     89         }),
     90         _ => None,
     91     }
     92 }