balrog~ ELF file analysis tool to be used after firmware extraction |
| git clone https://github.com/djnnvx/balrog.git |
| log | files | refs | archive | README |
mips.rs (2616B)
1 use super::{imm, mem, reg, Kind, Op, HIGH_HALF_SHIFT, IMM16_MASK}; 2 use crate::load::{dyn_val, sym_name}; 3 use capstone::arch::mips::MipsReg; 4 use goblin::elf::Elf; 5 use std::collections::HashMap; 6 7 const DT_PLTGOT: u64 = 3; 8 const DT_MIPS_LOCAL_GOTNO: u64 = 0x7000_000a; 9 const DT_MIPS_SYMTABNO: u64 = 0x7000_0011; 10 const DT_MIPS_GOTSYM: u64 = 0x7000_0013; 11 const GP_BIAS: u64 = 0x7ff0; 12 13 pub const ARG_REGS: [u16; 4] = [ 14 MipsReg::MIPS_REG_A0 as u16, 15 MipsReg::MIPS_REG_A1 as u16, 16 MipsReg::MIPS_REG_A2 as u16, 17 MipsReg::MIPS_REG_A3 as u16, 18 ]; 19 20 pub const SP: u16 = MipsReg::MIPS_REG_SP as u16; 21 pub const GP: u16 = MipsReg::MIPS_REG_GP as u16; 22 23 pub fn decode(mnemonic: &str, o: &[Op; 3]) -> Option<Kind> { 24 match mnemonic { 25 "jal" | "bal" | "jals" => Some(Kind::Call(imm(o, 0)? as u64)), 26 "jalr" => Some(Kind::CallInd { reg: reg(o, 0)? }), 27 "jr" => (reg(o, 0)? == MipsReg::MIPS_REG_RA as u16).then_some(Kind::Ret), 28 "lui" => { 29 let high_half = ((imm(o, 1)? as u64) & IMM16_MASK) << HIGH_HALF_SHIFT; 30 Some(Kind::SetConst { 31 dst: reg(o, 0)?, 32 val: high_half, 33 }) 34 } 35 "lw" => { 36 let (base, disp) = mem(o, 1)?; 37 Some(Kind::Load { 38 dst: reg(o, 0)?, 39 base, 40 disp, 41 }) 42 } 43 "addiu" | "addi" | "ori" => Some(Kind::AddImm { 44 dst: reg(o, 0)?, 45 base: reg(o, 1)?, 46 imm: imm(o, 2)?, 47 }), 48 "move" => Some(Kind::Mov { 49 dst: reg(o, 0)?, 50 src: reg(o, 1)?, 51 }), 52 _ => None, 53 } 54 } 55 56 pub fn resolve_got(elf: &Elf, got2sym: &mut HashMap<u64, String>) -> Option<u64> { 57 let got = dyn_val(elf, DT_PLTGOT)?; 58 let gp = got.wrapping_add(GP_BIAS); 59 60 let (Some(local_gotno), Some(gotsym), Some(symtabno)) = ( 61 dyn_val(elf, DT_MIPS_LOCAL_GOTNO), 62 dyn_val(elf, DT_MIPS_GOTSYM), 63 dyn_val(elf, DT_MIPS_SYMTABNO), 64 ) else { 65 return Some(gp); 66 }; 67 let entry_size = if elf.is_64 { 8 } else { 4 }; 68 let last_dynsym = symtabno.min(elf.dynsyms.len() as u64); 69 for sym_index in gotsym..last_dynsym { 70 let got_entry = local_gotno 71 .wrapping_add(sym_index - gotsym) 72 .wrapping_mul(entry_size); 73 let slot = got.wrapping_add(got_entry); 74 let Some(sym) = elf.dynsyms.get(sym_index as usize) else { 75 continue; 76 }; 77 if let Some(name) = sym_name(&elf.dynstrtab, sym.st_name) { 78 got2sym.entry(slot).or_insert(name); 79 } 80 } 81 Some(gp) 82 }