diff options
Diffstat (limited to 'arch/riscv')
| -rw-r--r-- | arch/riscv/Cargo.lock | 31 | ||||
| -rw-r--r-- | arch/riscv/Cargo.toml | 10 | ||||
| -rw-r--r-- | arch/riscv/build.rs | 15 | ||||
| -rw-r--r-- | arch/riscv/disasm/src/lib.rs | 29 | ||||
| -rw-r--r-- | arch/riscv/src/lib.rs | 494 |
5 files changed, 312 insertions, 267 deletions
diff --git a/arch/riscv/Cargo.lock b/arch/riscv/Cargo.lock index de9ca95e..e7c74d5d 100644 --- a/arch/riscv/Cargo.lock +++ b/arch/riscv/Cargo.lock @@ -32,7 +32,6 @@ name = "binaryninja" version = "0.1.0" dependencies = [ "binaryninjacore-sys", - "lazy_static", "log", "rayon", ] @@ -157,12 +156,6 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] name = "libc" version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -236,9 +229,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -265,9 +258,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -277,9 +270,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -288,9 +281,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "riscv-dis" @@ -313,9 +306,9 @@ checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "syn" -version = "2.0.41" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", @@ -324,9 +317,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "winapi" diff --git a/arch/riscv/Cargo.toml b/arch/riscv/Cargo.toml index 974535b7..1c0979e9 100644 --- a/arch/riscv/Cargo.toml +++ b/arch/riscv/Cargo.toml @@ -5,7 +5,8 @@ authors = ["Ryan Snyder <ryan.snyder.or@gmail.com>"] edition = "2021" [dependencies] -binaryninja = { path = "../../rust" } +binaryninja.workspace = true +binaryninjacore-sys.workspace = true riscv-dis = { path = "disasm" } log = "0.4" rayon = { version = "1.0", optional = true } @@ -15,9 +16,4 @@ default = [] liftcheck = ["rayon", "binaryninja/rayon"] [lib] -crate-type = ["cdylib"] - -[profile.release] -panic = "abort" -lto = true -debug = 1 +crate-type = ["cdylib"]
\ No newline at end of file diff --git a/arch/riscv/build.rs b/arch/riscv/build.rs new file mode 100644 index 00000000..ed6cec7d --- /dev/null +++ b/arch/riscv/build.rs @@ -0,0 +1,15 @@ +fn main() { + let link_path = std::env::var_os("DEP_BINARYNINJACORE_PATH") + .expect("DEP_BINARYNINJACORE_PATH not specified"); + + println!("cargo::rustc-link-lib=dylib=binaryninjacore"); + println!("cargo::rustc-link-search={}", link_path.to_str().unwrap()); + + #[cfg(not(target_os = "windows"))] + { + println!( + "cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}", + link_path.to_string_lossy() + ); + } +} diff --git a/arch/riscv/disasm/src/lib.rs b/arch/riscv/disasm/src/lib.rs index ad612e7a..a25516a6 100644 --- a/arch/riscv/disasm/src/lib.rs +++ b/arch/riscv/disasm/src/lib.rs @@ -4,10 +4,9 @@ // finish transition to from_instr32 from 'new' // make the various component structs smaller (8 bit IntReg/FloatReg etc.) -extern crate byteorder; - use std::borrow::Cow; use std::fmt; +use std::fmt::Debug; use std::marker::PhantomData; use std::mem; @@ -292,7 +291,7 @@ impl FloatRegType for () {} impl FloatRegType for f32 {} impl FloatRegType for f64 {} -pub trait RegFile: Sized + Copy + Clone { +pub trait RegFile: Debug + Sized + Copy + Clone { type Int: IntRegType; type Float: FloatRegType; @@ -345,21 +344,21 @@ pub enum Operand<D: RiscVDisassembler> { impl<D: RiscVDisassembler> fmt::Display for Operand<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Operand::R(ref r) => write!(f, "x{}", r.id()), - &Operand::F(ref r) => write!(f, "f{}", r.id()), - &Operand::I(i) => match i { + match *self { + Operand::R(r) => write!(f, "x{}", r.id()), + Operand::F(r) => write!(f, "f{}", r.id()), + Operand::I(i) => match i { -0x80000..=-1 => write!(f, "-{:x}", -i), _ => write!(f, "{:x}", i), }, - &Operand::M(i, ref r) => { + Operand::M(i, r) => { if i < 0 { write!(f, "-{:x}(x{})", -i, r.id()) } else { write!(f, "{:x}(x{})", i, r.id()) } } - &Operand::RM(ref r) => write!(f, "{}", r.name()), + Operand::RM(r) => write!(f, "{}", r.name()), } } } @@ -1777,7 +1776,7 @@ pub enum Instr<D: RiscVDisassembler> { impl<D: RiscVDisassembler> Instr<D> { pub fn mnem(&self) -> Mnem<D> { - Mnem(&self) + Mnem(self) } pub fn operands(&self) -> Vec<Operand<D>> { @@ -2300,7 +2299,7 @@ impl<'a, D: RiscVDisassembler + 'a> Mnem<'a, D> { } } -impl<'a, D: RiscVDisassembler> fmt::Display for Mnem<'a, D> { +impl<D: RiscVDisassembler> fmt::Display for Mnem<'_, D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match (self.mnem(), self.suffix()) { (m, None) => f.pad(m), @@ -2332,7 +2331,7 @@ impl StandardExtension for ExtensionSupported { } } -pub trait RiscVDisassembler: Sized + Copy + Clone { +pub trait RiscVDisassembler: Debug + Sized + Copy + Clone { type RegFile: RegFile; type MulDivExtension: StandardExtension; type AtomicExtension: StandardExtension; @@ -3141,9 +3140,7 @@ pub trait RiscVDisassembler: Sized + Copy + Clone { f if (f & 0xfe0) == 0x120 => { Op::SfenceVma(RTypeIntInst::new(inst)?) } - 0x104 => { - Op::SfenceVm(RTypeIntInst::new(inst)?) - } + 0x104 => Op::SfenceVm(RTypeIntInst::new(inst)?), 0x000 => Op::Ecall, 0x001 => Op::Ebreak, @@ -3171,7 +3168,7 @@ pub trait RiscVDisassembler: Sized + Copy + Clone { Ok(Instr::Rv32(decoded)) } - _ => return Err(TooShort), + _ => Err(TooShort), } } } diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index ca2774ca..1abce973 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::unusual_byte_groupings)] // Option -> Result // rework operands/instruction text // helper func for reading/writing to registers @@ -13,24 +14,19 @@ use binaryninja::{ LlvmServicesRelocMode, Register as Reg, RegisterInfo, UnusedFlag, UnusedRegisterStack, UnusedRegisterStackInfo, }, - binaryview::{BinaryView, BinaryViewExt}, - callingconvention::{register_calling_convention, CallingConventionBase, ConventionBuilder}, - custombinaryview::{BinaryViewType, BinaryViewTypeExt}, - disassembly::{InstructionTextToken, InstructionTextTokenContents}, + binary_view::{BinaryView, BinaryViewExt}, + calling_convention::{register_calling_convention, CallingConvention, ConventionBuilder}, + custom_binary_view::{BinaryViewType, BinaryViewTypeExt}, + disassembly::{InstructionTextToken, InstructionTextTokenKind}, function::Function, - functionrecognizer::FunctionRecognizer, - llil, - llil::{ - ExprInfo, InstrInfo, Label, Liftable, LiftableWithSize, LiftedNonSSA, Lifter, Mutable, - NonSSA, - }, + function_recognizer::FunctionRecognizer, rc::Ref, relocation::{ CoreRelocationHandler, CustomRelocationHandlerHandle, RelocationHandler, RelocationInfo, RelocationType, }, symbol::{Symbol, SymbolType}, - types::{max_confidence, min_confidence, Conf, NameAndType, Type}, + types::{NameAndType, Type}, }; use log::LevelFilter; use std::borrow::Cow; @@ -38,7 +34,18 @@ use std::fmt; use std::hash::Hash; use std::marker::PhantomData; +use binaryninja::architecture::{BranchKind, IntrinsicId, RegisterId}; +use binaryninja::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE}; use binaryninja::logger::Logger; +use binaryninja::low_level_il::expression::{LowLevelILExpressionKind, ValueExpr}; +use binaryninja::low_level_il::instruction::LowLevelILInstructionKind; +use binaryninja::low_level_il::lifting::{ + LiftableLowLevelIL, LiftableLowLevelILWithSize, LowLevelILLabel, +}; +use binaryninja::low_level_il::{ + expression::ExpressionHandler, instruction::InstructionHandler, LowLevelILRegister, + MutableLiftedILExpr, MutableLiftedILFunction, RegularLowLevelILFunction, +}; use riscv_dis::{ FloatReg, FloatRegType, Instr, IntRegType, Op, RegFile, Register as RiscVRegister, RiscVDisassembler, RoundMode, @@ -82,18 +89,18 @@ enum Intrinsic { #[derive(Copy, Clone)] struct Register<D: 'static + RiscVDisassembler> { - id: u32, + id: RegisterId, _dis: PhantomData<D>, } -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] struct RiscVIntrinsic<D: 'static + RiscVDisassembler> { id: Intrinsic, _dis: PhantomData<D>, } impl<D: 'static + RiscVDisassembler> Register<D> { - fn new(id: u32) -> Self { + fn new(id: RegisterId) -> Self { Self { id, _dis: PhantomData, @@ -103,10 +110,10 @@ impl<D: 'static + RiscVDisassembler> Register<D> { fn reg_type(&self) -> RegType { let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); - if self.id < int_reg_count { - RegType::Integer(self.id) + if self.id.0 < int_reg_count { + RegType::Integer(self.id.0) } else { - RegType::Float(self.id - int_reg_count) + RegType::Float(self.id.0 - int_reg_count) } } } @@ -114,7 +121,7 @@ impl<D: 'static + RiscVDisassembler> Register<D> { impl<D: 'static + RiscVDisassembler> From<riscv_dis::IntReg<D>> for Register<D> { fn from(reg: riscv_dis::IntReg<D>) -> Self { Self { - id: reg.id(), + id: RegisterId(reg.id()), _dis: PhantomData, } } @@ -125,15 +132,15 @@ impl<D: 'static + RiscVDisassembler> From<FloatReg<D>> for Register<D> { let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); Self { - id: reg.id() + int_reg_count, + id: RegisterId(reg.id() + int_reg_count), _dis: PhantomData, } } } -impl<D: 'static + RiscVDisassembler> Into<llil::Register<Register<D>>> for Register<D> { - fn into(self) -> llil::Register<Register<D>> { - llil::Register::ArchReg(self) +impl<D: 'static + RiscVDisassembler> From<Register<D>> for LowLevelILRegister<Register<D>> { + fn from(reg: Register<D>) -> Self { + LowLevelILRegister::ArchReg(reg) } } @@ -192,18 +199,20 @@ impl<D: 'static + RiscVDisassembler> architecture::Register for Register<D> { *self } - fn id(&self) -> u32 { + fn id(&self) -> RegisterId { self.id } } -impl<'a, D: 'static + RiscVDisassembler + Send + Sync> Liftable<'a, RiscVArch<D>> for Register<D> { - type Result = llil::ValueExpr; +impl<'a, D: 'static + RiscVDisassembler + Send + Sync> LiftableLowLevelIL<'a, RiscVArch<D>> + for Register<D> +{ + type Result = ValueExpr; fn lift( - il: &'a llil::Lifter<RiscVArch<D>>, + il: &'a MutableLiftedILFunction<RiscVArch<D>>, reg: Self, - ) -> llil::Expression<'a, RiscVArch<D>, Mutable, NonSSA<LiftedNonSSA>, Self::Result> { + ) -> MutableLiftedILExpr<'a, RiscVArch<D>, Self::Result> { match reg.reg_type() { RegType::Integer(0) => il.const_int(reg.size(), 0), RegType::Integer(_) => il.reg(reg.size(), reg), @@ -212,14 +221,14 @@ impl<'a, D: 'static + RiscVDisassembler + Send + Sync> Liftable<'a, RiscVArch<D> } } -impl<'a, D: 'static + RiscVDisassembler + Send + Sync> LiftableWithSize<'a, RiscVArch<D>> +impl<'a, D: 'static + RiscVDisassembler + Send + Sync> LiftableLowLevelILWithSize<'a, RiscVArch<D>> for Register<D> { fn lift_with_size( - il: &'a llil::Lifter<RiscVArch<D>>, + il: &'a MutableLiftedILFunction<RiscVArch<D>>, reg: Self, size: usize, - ) -> llil::Expression<'a, RiscVArch<D>, Mutable, NonSSA<LiftedNonSSA>, llil::ValueExpr> { + ) -> MutableLiftedILExpr<'a, RiscVArch<D>, ValueExpr> { #[cfg(debug_assertions)] { if reg.size() < size { @@ -262,14 +271,19 @@ impl<D: 'static + RiscVDisassembler> PartialEq for Register<D> { impl<D: 'static + RiscVDisassembler> Eq for Register<D> {} -impl<D: 'static + RiscVDisassembler + Send + Sync> fmt::Debug for Register<D> { +impl<D: 'static + RiscVDisassembler> fmt::Debug for Register<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.name().as_ref()) } } impl<D: RiscVDisassembler> RiscVIntrinsic<D> { - fn id_from_parts(id: u32, sz1: Option<u8>, sz2: Option<u8>, rm: Option<RoundMode>) -> u32 { + fn id_from_parts( + id: u32, + sz1: Option<u8>, + sz2: Option<u8>, + rm: Option<RoundMode>, + ) -> IntrinsicId { let sz1 = sz1.unwrap_or(0); let sz2 = sz2.unwrap_or(0); let rm = match rm { @@ -285,10 +299,11 @@ impl<D: RiscVDisassembler> RiscVIntrinsic<D> { id |= sz1 as u32; id |= (sz2 as u32) << 8; id |= (rm as u32) << 16; - id + IntrinsicId(id) } - fn parts_from_id(id: u32) -> Option<(u32, u8, u8, RoundMode)> { + fn parts_from_id(id: IntrinsicId) -> Option<(u32, u8, u8, RoundMode)> { + let id = id.0; let sz1 = (id & 0xff) as u8; let sz2 = ((id >> 8) & 0xff) as u8; let rm = match (id >> 16) & 0xf { @@ -303,7 +318,7 @@ impl<D: RiscVDisassembler> RiscVIntrinsic<D> { Some(((id >> 20) & 0xfff, sz1, sz2, rm)) } - fn from_id(id: u32) -> Option<RiscVIntrinsic<D>> { + fn from_id(id: IntrinsicId) -> Option<RiscVIntrinsic<D>> { match Self::parts_from_id(id) { Some((0, _, _, _)) => Some(Intrinsic::Uret.into()), Some((1, _, _, _)) => Some(Intrinsic::Sret.into()), @@ -468,7 +483,7 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { } } - fn id(&self) -> u32 { + fn id(&self) -> IntrinsicId { match self.id { Intrinsic::Uret => Self::id_from_parts(0, None, None, None), Intrinsic::Sret => Self::id_from_parts(1, None, None, None), @@ -509,7 +524,7 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { } } - fn inputs(&self) -> Vec<Ref<NameAndType>> { + fn inputs(&self) -> Vec<NameAndType> { match self.id { Intrinsic::Uret | Intrinsic::Sret | Intrinsic::Mret | Intrinsic::Wfi => { vec![] @@ -517,17 +532,18 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { Intrinsic::Csrrd => { vec![NameAndType::new( "csr", - &Type::int(4, false), - max_confidence(), + Conf::new(Type::int(4, false), MAX_CONFIDENCE), )] } Intrinsic::Csrrw | Intrinsic::Csrwr | Intrinsic::Csrrs | Intrinsic::Csrrc => { vec![ - NameAndType::new("csr", &Type::int(4, false), max_confidence()), + NameAndType::new("csr", Conf::new(Type::int(4, false), MAX_CONFIDENCE)), NameAndType::new( "value", - &Type::int(<D::RegFile as RegFile>::Int::width(), false), - min_confidence(), + Conf::new( + Type::int(<D::RegFile as RegFile>::Int::width(), false), + MIN_CONFIDENCE, + ), ), ] } @@ -541,8 +557,8 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { | Intrinsic::Fmin(size) | Intrinsic::Fmax(size) => { vec![ - NameAndType::new("", &Type::float(size as usize), max_confidence()), - NameAndType::new("", &Type::float(size as usize), max_confidence()), + NameAndType::new("", Conf::new(Type::float(size as usize), MAX_CONFIDENCE)), + NameAndType::new("", Conf::new(Type::float(size as usize), MAX_CONFIDENCE)), ] } Intrinsic::Fsqrt(size, _) @@ -552,26 +568,26 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { | Intrinsic::FcvtFToU(size, _, _) => { vec![NameAndType::new( "", - &Type::float(size as usize), - max_confidence(), + Conf::new(Type::float(size as usize), MAX_CONFIDENCE), )] } Intrinsic::FcvtIToF(size, _, _) => { vec![NameAndType::new( "", - &Type::int(size as usize, true), - max_confidence(), + Conf::new(Type::int(size as usize, true), MAX_CONFIDENCE), )] } Intrinsic::FcvtUToF(size, _, _) => { vec![NameAndType::new( "", - &Type::int(size as usize, false), - max_confidence(), + Conf::new(Type::int(size as usize, false), MAX_CONFIDENCE), )] } Intrinsic::Fence => { - vec![NameAndType::new("", &Type::int(4, false), min_confidence())] + vec![NameAndType::new( + "", + Conf::new(Type::int(4, false), MIN_CONFIDENCE), + )] } } } @@ -589,7 +605,7 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { Intrinsic::Csrrw | Intrinsic::Csrrd | Intrinsic::Csrrs | Intrinsic::Csrrc => { vec![Conf::new( Type::int(<D::RegFile as RegFile>::Int::width(), false), - min_confidence(), + MIN_CONFIDENCE, )] } Intrinsic::Fadd(size, _) @@ -605,16 +621,16 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> { | Intrinsic::FcvtFToF(_, size, _) | Intrinsic::FcvtIToF(_, size, _) | Intrinsic::FcvtUToF(_, size, _) => { - vec![Conf::new(Type::float(size as usize), max_confidence())] + vec![Conf::new(Type::float(size as usize), MAX_CONFIDENCE)] } Intrinsic::Fclass(_) => { - vec![Conf::new(Type::int(4, false), min_confidence())] + vec![Conf::new(Type::int(4, false), MIN_CONFIDENCE)] } Intrinsic::FcvtFToI(_, size, _) => { - vec![Conf::new(Type::int(size as usize, true), max_confidence())] + vec![Conf::new(Type::int(size as usize, true), MAX_CONFIDENCE)] } Intrinsic::FcvtFToU(_, size, _) => { - vec![Conf::new(Type::int(size as usize, false), max_confidence())] + vec![Conf::new(Type::int(size as usize, false), MAX_CONFIDENCE)] } } } @@ -671,13 +687,11 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo self.max_instr_len() } - fn associated_arch_by_addr(&self, _addr: &mut u64) -> CoreArchitecture { + fn associated_arch_by_addr(&self, _addr: u64) -> CoreArchitecture { self.handle } fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo> { - use architecture::BranchInfo; - let (inst_len, op) = match D::decode(addr, data) { Ok(Instr::Rv16(op)) => (2, op), Ok(Instr::Rv32(op)) => (4, op), @@ -691,23 +705,23 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let target = addr.wrapping_add(j.imm() as i64 as u64); let branch = if j.rd().id() == 0 { - BranchInfo::Unconditional(target) + BranchKind::Unconditional(target) } else { - BranchInfo::Call(target) + BranchKind::Call(target) }; - res.add_branch(branch, None); + res.add_branch(branch); } Op::Jalr(ref i) => { // TODO handle the calls with rs1 == 0? if i.rd().id() == 0 { let branch_type = if i.rs1().id() == 1 { - BranchInfo::FunctionReturn + BranchKind::FunctionReturn } else { - BranchInfo::Unresolved + BranchKind::Unresolved }; - res.add_branch(branch_type, None); + res.add_branch(branch_type); } } Op::Beq(ref b) @@ -716,21 +730,18 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo | Op::Bge(ref b) | Op::BltU(ref b) | Op::BgeU(ref b) => { - res.add_branch(BranchInfo::False(addr.wrapping_add(inst_len as u64)), None); - res.add_branch( - BranchInfo::True(addr.wrapping_add(b.imm() as i64 as u64)), - None, - ); + res.add_branch(BranchKind::False(addr.wrapping_add(inst_len as u64))); + res.add_branch(BranchKind::True(addr.wrapping_add(b.imm() as i64 as u64))); } Op::Ecall => { - res.add_branch(BranchInfo::SystemCall, None); + res.add_branch(BranchKind::SystemCall); } Op::Ebreak => { // TODO is this valid, or should lifting handle this? - res.add_branch(BranchInfo::Unresolved, None); + res.add_branch(BranchKind::Unresolved); } Op::Uret | Op::Sret | Op::Mret => { - res.add_branch(BranchInfo::FunctionReturn, None); + res.add_branch(BranchKind::FunctionReturn); } _ => {} } @@ -744,7 +755,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo addr: u64, ) -> Option<(usize, Vec<InstructionTextToken>)> { use riscv_dis::Operand; - use InstructionTextTokenContents::*; + use InstructionTextTokenKind::*; let inst = match D::decode(addr, data) { Ok(i) => i, @@ -982,12 +993,12 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo Operand::R(r) => { let reg = self::Register::from(r); - res.push(InstructionTextToken::new(®.name(), Register)); + res.push(InstructionTextToken::new(reg.name(), Register)); } Operand::F(r) => { let reg = self::Register::from(r); - res.push(InstructionTextToken::new(®.name(), Register)); + res.push(InstructionTextToken::new(reg.name(), Register)); } Operand::I(i) => { match op { @@ -1002,8 +1013,11 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let target = addr.wrapping_add(i as i64 as u64); res.push(InstructionTextToken::new( - &format!("0x{:x}", target), - CodeRelativeAddress(target), + format!("0x{:x}", target), + CodeRelativeAddress { + value: target, + size: Some(self.address_size()), + }, )); } _ => { @@ -1012,7 +1026,10 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo -0x8_0000..=-1 => format!("-0x{:x}", -i), _ => format!("0x{:x}", i), }, - Integer(i as u64), + Integer { + value: i as u64, + size: None, + }, )); } } @@ -1027,12 +1044,15 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo } else { format!("0x{:x}", i) }, - Integer(i as u64), + Integer { + value: i as u64, + size: None, + }, )); - res.push(InstructionTextToken::new("(", Brace)); - res.push(InstructionTextToken::new(®.name(), Register)); - res.push(InstructionTextToken::new(")", Brace)); + res.push(InstructionTextToken::new("(", Brace { hash: None })); + res.push(InstructionTextToken::new(reg.name(), Register)); + res.push(InstructionTextToken::new(")", Brace { hash: None })); res.push(InstructionTextToken::new("", EndMemoryOperand)); } Operand::RM(r) => { @@ -1048,7 +1068,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo &self, data: &[u8], addr: u64, - il: &mut llil::Lifter<Self>, + il: &mut MutableLiftedILFunction<Self>, ) -> Option<(usize, bool)> { let max_width = self.default_integer_size(); @@ -1061,7 +1081,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo macro_rules! set_reg_or_append_fallback { ($op:ident, $t:expr, $f:expr) => {{ let rd = Register::from($op.rd()); - match rd.id { + match rd.id.0 { 0 => $f.append(), _ => il.set_reg(rd.size(), rd, $t).append(), } @@ -1202,7 +1222,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let target = addr.wrapping_add(j.imm() as i64 as u64); match (j.rd().id(), il.label_for_address(target)) { - (0, Some(l)) => il.goto(l), + (0, Some(mut l)) => il.goto(&mut l), (0, None) => il.jump(il.const_ptr(target)), (_, _) => il.call(il.const_ptr(target)), } @@ -1221,7 +1241,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo (0, _, _) => il.jump(target).append(), // indirect jump (rd_id, rs1_id, _) if rd_id == rs1_id => { // store the target in a temporary register so we don't clobber it when rd == rs1 - let tmp_reg: llil::Register<Register<D>> = llil::Register::Temp(0); + let tmp_reg: LowLevelILRegister<Register<D>> = LowLevelILRegister::Temp(0); il.set_reg(max_width, tmp_reg, target).append(); // indirect jump with storage of next address to non-`ra` register il.set_reg( @@ -1259,34 +1279,31 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo _ => unreachable!(), }; - let mut new_false: Option<Label> = None; - let mut new_true: Option<Label> = None; + let mut new_false = false; + let mut new_true = false; let ft = addr.wrapping_add(inst_len); let tt = addr.wrapping_add(b.imm() as i64 as u64); - { - let f = il.label_for_address(ft).unwrap_or_else(|| { - new_false = Some(Label::new()); - new_false.as_ref().unwrap() - }); - - let t = il.label_for_address(tt).unwrap_or_else(|| { - new_true = Some(Label::new()); - new_true.as_ref().unwrap() - }); + let mut f = il.label_for_address(ft).unwrap_or_else(|| { + new_false = true; + LowLevelILLabel::new() + }); - il.if_expr(cond_expr, t, f).append(); - } + let mut t = il.label_for_address(tt).unwrap_or_else(|| { + new_true = true; + LowLevelILLabel::new() + }); - if let Some(t) = new_true.as_mut() { - il.mark_label(t); + il.if_expr(cond_expr, &mut t, &mut f).append(); + if new_true { + il.mark_label(&mut t); il.jump(il.const_ptr(tt)).append(); } - if let Some(f) = new_false.as_mut() { - il.mark_label(f); + if new_false { + il.mark_label(&mut f); } } @@ -1294,41 +1311,41 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo Op::Ebreak => il.bp().append(), Op::Uret => { il.intrinsic( - Lifter::<Self>::NO_OUTPUTS, + MutableLiftedILFunction::<Self>::NO_OUTPUTS, Intrinsic::Uret, - Lifter::<Self>::NO_INPUTS, + MutableLiftedILFunction::<Self>::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Sret => { il.intrinsic( - Lifter::<Self>::NO_OUTPUTS, + MutableLiftedILFunction::<Self>::NO_OUTPUTS, Intrinsic::Sret, - Lifter::<Self>::NO_INPUTS, + MutableLiftedILFunction::<Self>::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Mret => { il.intrinsic( - Lifter::<Self>::NO_OUTPUTS, + MutableLiftedILFunction::<Self>::NO_OUTPUTS, Intrinsic::Mret, - Lifter::<Self>::NO_INPUTS, + MutableLiftedILFunction::<Self>::NO_INPUTS, ) .append(); il.no_ret().append(); } Op::Wfi => il .intrinsic( - Lifter::<Self>::NO_OUTPUTS, + MutableLiftedILFunction::<Self>::NO_OUTPUTS, Intrinsic::Wfi, - Lifter::<Self>::NO_INPUTS, + MutableLiftedILFunction::<Self>::NO_INPUTS, ) .append(), Op::Fence(i) => il .intrinsic( - Lifter::<Self>::NO_OUTPUTS, + MutableLiftedILFunction::<Self>::NO_OUTPUTS, Intrinsic::Fence, [il.const_int(4, i.imm() as u32 as u64)], ) @@ -1336,19 +1353,23 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo Op::Csrrw(i) => { let rd = Register::from(i.rd()); - let rs1 = Liftable::lift(il, Register::from(i.rs1())); + let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1())); let csr = il.const_int(4, i.csr() as u64); if i.rd().id() == 0 { - il.intrinsic(Lifter::<Self>::NO_OUTPUTS, Intrinsic::Csrwr, [csr, rs1]) - .append(); + il.intrinsic( + MutableLiftedILFunction::<Self>::NO_OUTPUTS, + Intrinsic::Csrwr, + [csr, rs1], + ) + .append(); } else { il.intrinsic([rd], Intrinsic::Csrrw, [rs1]).append(); } } Op::Csrrs(i) => { let rd = Register::from(i.rd()); - let rs1 = Liftable::lift(il, Register::from(i.rs1())); + let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1())); let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { @@ -1359,7 +1380,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo } Op::Csrrc(i) => { let rd = Register::from(i.rd()); - let rs1 = Liftable::lift(il, Register::from(i.rs1())); + let rs1 = LiftableLowLevelIL::lift(il, Register::from(i.rs1())); let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { @@ -1374,8 +1395,12 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let imm = il.const_int(max_width, i.imm() as u64); if i.rd().id() == 0 { - il.intrinsic(Lifter::<Self>::NO_OUTPUTS, Intrinsic::Csrwr, [csr, imm]) - .append(); + il.intrinsic( + MutableLiftedILFunction::<Self>::NO_OUTPUTS, + Intrinsic::Csrwr, + [csr, imm], + ) + .append(); } else { il.intrinsic([rd], Intrinsic::Csrrw, [csr, imm]).append(); } @@ -1418,7 +1443,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let rd = a.rd(); let dest_reg = match rd.id() { - 0 => llil::Register::Temp(0), + 0 => LowLevelILRegister::Temp(0), _ => Register::from(rd).into(), }; @@ -1429,29 +1454,26 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo // nature of the store -- dataflow will give up il.set_reg(max_width, dest_reg, il.unimplemented()).append(); - let mut new_false: Option<Label> = None; - let mut t = Label::new(); + let mut new_false = false; + let mut t = LowLevelILLabel::new(); - { - let cond_expr = il.cmp_e(max_width, dest_reg, 0u64); + let cond_expr = il.cmp_e(max_width, dest_reg, 0u64); - let ft = addr.wrapping_add(inst_len); - let f = il.label_for_address(ft).unwrap_or_else(|| { - new_false = Some(Label::new()); - new_false.as_ref().unwrap() - }); + let ft = addr.wrapping_add(inst_len); + let mut f = il.label_for_address(ft).unwrap_or_else(|| { + new_false = true; + LowLevelILLabel::new() + }); - il.if_expr(cond_expr, &t, f).append(); - } + il.if_expr(cond_expr, &mut t, &mut f).append(); il.mark_label(&mut t); - il.store(size, Register::from(a.rs1()), Register::from(a.rs2())) .with_source_operand(2) .append(); - if let Some(f) = new_false.as_mut() { - il.mark_label(f); + if new_false { + il.mark_label(&mut f); } } Op::AmoSwap(a) @@ -1469,14 +1491,14 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let rs2 = a.rs2(); let dest_reg = match rd.id() { - 0 => llil::Register::Temp(0), + 0 => LowLevelILRegister::Temp(0), _ => Register::from(rd).into(), }; let mut next_temp_reg = 1; let mut alloc_reg = |rs: riscv_dis::IntReg<D>| match (rs.id(), rd.id()) { (id, r) if id != 0 && id == r => { - let reg = llil::Register::Temp(next_temp_reg); + let reg = LowLevelILRegister::Temp(next_temp_reg); next_temp_reg += 1; il.set_reg(max_width, reg, Register::from(rs)).append(); @@ -1497,8 +1519,8 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo il.set_reg(max_width, dest_reg, load_expr).append(); - let val_expr = LiftableWithSize::lift_with_size(il, reg_with_val, size); - let dest_reg_val = LiftableWithSize::lift_with_size(il, dest_reg, size); + let val_expr = LiftableLowLevelILWithSize::lift_with_size(il, reg_with_val, size); + let dest_reg_val = LiftableLowLevelILWithSize::lift_with_size(il, dest_reg, size); let val_to_store = match op { Op::AmoSwap(..) => val_expr, @@ -1556,7 +1578,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo }; il.set_reg(width, rd, result).append(); } else { - let product = llil::Register::Temp(0); + let product = LowLevelILRegister::Temp(0); il.intrinsic( [product], Intrinsic::Fmul(f.width(), f.rm()), @@ -1711,7 +1733,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo } Op::Fle(f) | Op::Flt(f) | Op::Feq(f) => { let rd = match f.rd().id() { - 0 => llil::Register::Temp(0), + 0 => LowLevelILRegister::Temp(0), _ => Register::from(f.rd()).into(), }; let left = Register::from(f.rs1()); @@ -1745,7 +1767,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo } Op::FcvtToInt(f) => { let rd = match f.rd().id() { - 0 => llil::Register::Temp(0), + 0 => LowLevelILRegister::Temp(0), _ => Register::from(f.rd()).into(), }; let rs1 = Register::from(f.rs1()); @@ -1780,7 +1802,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let rs1 = Register::from(f.rs1()); let rd_width = f.rd_width() as usize; let rs1_width = f.rs1_width() as usize; - let rs1 = LiftableWithSize::lift_with_size(il, rs1, rs1_width); + let rs1 = LiftableLowLevelILWithSize::lift_with_size(il, rs1, rs1_width); if f.zx() { il.intrinsic( [rd], @@ -1802,7 +1824,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo } Op::FmvToInt(f) => { let rd = match f.rd().id() { - 0 => llil::Register::Temp(0), + 0 => LowLevelILRegister::Temp(0), _ => Register::from(f.rd()).into(), }; let rs1 = Register::from(f.rs1()); @@ -1818,7 +1840,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let rd = Register::from(f.rd()); let rs1 = Register::from(f.rs1()); let width = f.width() as usize; - let rs1 = LiftableWithSize::lift_with_size(il, rs1, width); + let rs1 = LiftableLowLevelILWithSize::lift_with_size(il, rs1, width); il.set_reg(width, rd, rs1).append(); } Op::Fclass(f) => { @@ -1845,7 +1867,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let mut res = Vec::with_capacity(reg_count as usize); for i in 0..reg_count { - res.push(Register::new(i)); + res.push(Register::new(RegisterId(i))); } res @@ -1859,28 +1881,28 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo let mut regs = Vec::with_capacity(2); for i in &[3, 4] { - regs.push(Register::new(*i)); + regs.push(Register::new(RegisterId(*i))); } regs } fn stack_pointer_reg(&self) -> Option<Self::Register> { - Some(Register::new(2)) + Some(Register::new(RegisterId(2))) } fn link_reg(&self) -> Option<Self::Register> { - Some(Register::new(1)) + Some(Register::new(RegisterId(1))) } - fn register_from_id(&self, id: u32) -> Option<Self::Register> { + fn register_from_id(&self, id: RegisterId) -> Option<Self::Register> { let mut reg_count = <D::RegFile as RegFile>::int_reg_count(); if <D::RegFile as RegFile>::Float::present() { reg_count += 32; } - if id > reg_count { + if id.0 > reg_count { None } else { Some(Register::new(id)) @@ -1960,7 +1982,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo res.iter().map(|i| (*i).into()).collect() } - fn intrinsic_from_id(&self, id: u32) -> Option<Self::Intrinsic> { + fn intrinsic_from_id(&self, id: IntrinsicId) -> Option<Self::Intrinsic> { RiscVIntrinsic::from_id(id) } @@ -2454,7 +2476,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> RelocationHandler // Actual target symbol is on the associated R_RISCV_PCREL_HI20 relocation, which // is pointed to by `reloc.target()`. let target = match bv - .get_relocations_at(reloc.target()) + .relocations_at(reloc.target()) .iter() .find(|r| r.info().native_type == Self::R_RISCV_PCREL_HI20) { @@ -2648,10 +2670,8 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> RiscVCC<D> { } } -impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConventionBase for RiscVCC<D> { - type Arch = RiscVArch<D>; - - fn caller_saved_registers(&self) -> Vec<Register<D>> { +impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConvention for RiscVCC<D> { + fn caller_saved_registers(&self) -> Vec<RegisterId> { let mut regs = Vec::with_capacity(36); let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); @@ -2659,7 +2679,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConventionBase for Ris 1u32, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 28, 29, 30, 31, ] { if i < &int_reg_count { - regs.push(Register::new(*i)); + regs.push(RegisterId(*i)); } } @@ -2667,52 +2687,52 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConventionBase for Ris for i in &[ 0u32, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 28, 29, 30, 31, ] { - regs.push(Register::new(*i + int_reg_count)); + regs.push(RegisterId(*i + int_reg_count)); } } regs } - fn callee_saved_registers(&self) -> Vec<Register<D>> { + fn callee_saved_registers(&self) -> Vec<RegisterId> { let mut regs = Vec::with_capacity(24); let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); for i in &[8u32, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27] { if i < &int_reg_count { - regs.push(Register::new(*i)); + regs.push(RegisterId(*i)); } } if <D::RegFile as RegFile>::Float::present() { for i in &[8u32, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27] { - regs.push(Register::new(*i + int_reg_count)); + regs.push(RegisterId(*i + int_reg_count)); } } regs } - fn int_arg_registers(&self) -> Vec<Register<D>> { + fn int_arg_registers(&self) -> Vec<RegisterId> { let mut regs = Vec::with_capacity(8); let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); for i in &[10, 11, 12, 13, 14, 15, 16, 17] { if i < &int_reg_count { - regs.push(Register::new(*i)); + regs.push(RegisterId(*i)); } } regs } - fn float_arg_registers(&self) -> Vec<Register<D>> { + fn float_arg_registers(&self) -> Vec<RegisterId> { let mut regs = Vec::with_capacity(8); if <D::RegFile as RegFile>::Float::present() { let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); for i in &[10, 11, 12, 13, 14, 15, 16, 17] { - regs.push(Register::new(*i + int_reg_count)); + regs.push(RegisterId(*i + int_reg_count)); } } @@ -2735,29 +2755,29 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConventionBase for Ris } // a0 == x10 - fn return_int_reg(&self) -> Option<Register<D>> { - Some(Register::new(10)) + fn return_int_reg(&self) -> Option<RegisterId> { + Some(RegisterId(10)) } // a1 == x11 - fn return_hi_int_reg(&self) -> Option<Register<D>> { - Some(Register::new(11)) + fn return_hi_int_reg(&self) -> Option<RegisterId> { + Some(RegisterId(11)) } - fn return_float_reg(&self) -> Option<Register<D>> { + fn return_float_reg(&self) -> Option<RegisterId> { if <D::RegFile as RegFile>::Float::present() { let int_reg_count = <D::RegFile as RegFile>::int_reg_count(); - Some(Register::new(10 + int_reg_count)) + Some(RegisterId(10 + int_reg_count)) } else { None } } // gp == x3 - fn global_pointer_reg(&self) -> Option<Register<D>> { - Some(Register::new(3)) + fn global_pointer_reg(&self) -> Option<RegisterId> { + Some(RegisterId(3)) } - fn implicitly_defined_registers(&self) -> Vec<Register<D>> { + fn implicitly_defined_registers(&self) -> Vec<RegisterId> { Vec::new() } fn are_argument_registers_used_for_var_args(&self) -> bool { @@ -2772,7 +2792,7 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { &self, bv: &BinaryView, func: &Function, - llil: &llil::RegularFunction<CoreArchitecture>, + llil: &RegularLowLevelILFunction<CoreArchitecture>, ) -> bool { // Look for the following code pattern: // t3 = plt @@ -2788,11 +2808,13 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { let mut next_llil_instr = llil.basic_blocks().iter().next().unwrap().iter(); // Match instruction that fetches PC-relative PLT address range - let auipc = next_llil_instr.next().unwrap().info(); + let auipc = next_llil_instr.next().unwrap().kind(); let (auipc_dest, plt_base) = match auipc { - InstrInfo::SetReg(r) => { - let value = match r.source_expr().info() { - ExprInfo::Const(v) | ExprInfo::ConstPtr(v) => v.value(), + LowLevelILInstructionKind::SetReg(r) => { + let value = match r.source_expr().kind() { + LowLevelILExpressionKind::Const(v) | LowLevelILExpressionKind::ConstPtr(v) => { + v.value() + } _ => return false, }; (r.dest_reg(), value) @@ -2801,34 +2823,46 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { }; // Match load instruction that loads the imported address - let load = next_llil_instr.next().unwrap().info(); + let load = next_llil_instr.next().unwrap().kind(); let (mut entry, mut target_reg) = match load { - InstrInfo::SetReg(r) => match r.source_expr().info() { - ExprInfo::Load(l) => { + LowLevelILInstructionKind::SetReg(r) => match r.source_expr().kind() { + LowLevelILExpressionKind::Load(l) => { let target_reg = r.dest_reg(); - let entry = match l.source_mem_expr().info() { - ExprInfo::Reg(lr) if lr.source_reg() == auipc_dest => plt_base, - ExprInfo::Add(a) => match (a.left().info(), a.right().info()) { - (ExprInfo::Reg(a), ExprInfo::Const(b) | ExprInfo::ConstPtr(b)) - if a.source_reg() == auipc_dest => - { - plt_base.wrapping_add(b.value()) - } - (ExprInfo::Const(b) | ExprInfo::ConstPtr(b), ExprInfo::Reg(a)) - if a.source_reg() == auipc_dest => - { - plt_base.wrapping_add(b.value()) + let entry = match l.source_mem_expr().kind() { + LowLevelILExpressionKind::Reg(lr) if lr.source_reg() == auipc_dest => { + plt_base + } + LowLevelILExpressionKind::Add(a) => { + match (a.left().kind(), a.right().kind()) { + ( + LowLevelILExpressionKind::Reg(a), + LowLevelILExpressionKind::Const(b) + | LowLevelILExpressionKind::ConstPtr(b), + ) if a.source_reg() == auipc_dest => { + plt_base.wrapping_add(b.value()) + } + ( + LowLevelILExpressionKind::Const(b) + | LowLevelILExpressionKind::ConstPtr(b), + LowLevelILExpressionKind::Reg(a), + ) if a.source_reg() == auipc_dest => { + plt_base.wrapping_add(b.value()) + } + _ => return false, } - _ => return false, - }, - ExprInfo::Sub(a) => match (a.left().info(), a.right().info()) { - (ExprInfo::Reg(a), ExprInfo::Const(b) | ExprInfo::ConstPtr(b)) - if a.source_reg() == auipc_dest => - { - plt_base.wrapping_sub(b.value()) + } + LowLevelILExpressionKind::Sub(a) => { + match (a.left().kind(), a.right().kind()) { + ( + LowLevelILExpressionKind::Reg(a), + LowLevelILExpressionKind::Const(b) + | LowLevelILExpressionKind::ConstPtr(b), + ) if a.source_reg() == auipc_dest => { + plt_base.wrapping_sub(b.value()) + } + _ => return false, } - _ => return false, - }, + } _ => return false, }; (entry, target_reg) @@ -2843,22 +2877,22 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { // Ensure that load is pointing at an import address let sym = match bv.symbol_by_address(entry) { - Ok(sym) => sym, - Err(_) => return false, + Some(sym) => sym, + None => return false, }; if sym.sym_type() != SymbolType::ImportAddress { return false; } // (OPTIONAL) Check if we are storing in temp0, adjust target reg if so - let mut temp_reg_inst = next_llil_instr.next().unwrap().info(); + let mut temp_reg_inst = next_llil_instr.next().unwrap().kind(); match &temp_reg_inst { - InstrInfo::SetReg(r) if llil.instruction_count() >= 5 => { - match r.source_expr().info() { - ExprInfo::Reg(op) if target_reg == op.source_reg() => { + LowLevelILInstructionKind::SetReg(r) if llil.instruction_count() >= 5 => { + match r.source_expr().kind() { + LowLevelILExpressionKind::Reg(op) if target_reg == op.source_reg() => { // Update the target_reg to the temp reg. target_reg = r.dest_reg(); - temp_reg_inst = next_llil_instr.next().unwrap().info() + temp_reg_inst = next_llil_instr.next().unwrap().kind() } _ => {} } @@ -2869,9 +2903,11 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { // Match instruction that stores the next instruction address into a register let next_pc_inst = temp_reg_inst; let (next_pc_dest, next_pc, cur_pc) = match next_pc_inst { - InstrInfo::SetReg(r) => { - let value = match r.source_expr().info() { - ExprInfo::Const(v) | ExprInfo::ConstPtr(v) => v.value(), + LowLevelILInstructionKind::SetReg(r) => { + let value = match r.source_expr().kind() { + LowLevelILExpressionKind::Const(v) | LowLevelILExpressionKind::ConstPtr(v) => { + v.value() + } _ => return false, }; (r.dest_reg(), value, r.address()) @@ -2883,17 +2919,17 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { } // Match tail call at the end and make sure it is going to the import - let jump = next_llil_instr.next().unwrap().info(); + let jump = next_llil_instr.next().unwrap().kind(); match jump { - InstrInfo::TailCall(j) => { - match j.target().info() { - ExprInfo::Reg(r) if r.source_reg() == target_reg => (), + LowLevelILInstructionKind::TailCall(j) => { + match j.target().kind() { + LowLevelILExpressionKind::Reg(r) if r.source_reg() == target_reg => (), _ => return false, }; } - InstrInfo::Jump(j) => { - match j.target().info() { - ExprInfo::Reg(r) if r.source_reg() == target_reg => (), + LowLevelILInstructionKind::Jump(j) => { + match j.target().kind() { + LowLevelILExpressionKind::Reg(r) if r.source_reg() == target_reg => (), _ => return false, }; } @@ -2907,7 +2943,7 @@ impl FunctionRecognizer for RiscVELFPLTRecognizer { for ext_sym in &bv.symbols_by_name(func_sym.raw_name()) { if ext_sym.sym_type() == SymbolType::External { if let Some(var) = bv.data_variable_at_address(ext_sym.address()) { - func.apply_imported_types(func_sym.as_ref(), Some(var.t())); + func.apply_imported_types(func_sym.as_ref(), Some(&var.ty.contents)); return true; } } @@ -2957,9 +2993,17 @@ pub extern "C" fn CorePluginInit() -> bool { arch32.register_function_recognizer(RiscVELFPLTRecognizer); arch64.register_function_recognizer(RiscVELFPLTRecognizer); - let cc32 = register_calling_convention(arch32, "default", RiscVCC::new()); + let cc32 = register_calling_convention( + arch32, + "default", + RiscVCC::<RiscVIMACDisassembler<Rv32GRegs>>::new(), + ); arch32.set_default_calling_convention(&cc32); - let cc64 = register_calling_convention(arch64, "default", RiscVCC::new()); + let cc64 = register_calling_convention( + arch64, + "default", + RiscVCC::<RiscVIMACDisassembler<Rv64GRegs>>::new(), + ); arch64.set_default_calling_convention(&cc64); if let Ok(bvt) = BinaryViewType::by_name("ELF") { |
