diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/msp430/Cargo.lock | 19 | ||||
| -rw-r--r-- | arch/msp430/Cargo.toml | 8 | ||||
| -rw-r--r-- | arch/msp430/build.rs | 15 | ||||
| -rw-r--r-- | arch/msp430/src/architecture.rs | 318 | ||||
| -rw-r--r-- | arch/msp430/src/flag.rs | 26 | ||||
| -rw-r--r-- | arch/msp430/src/lib.rs | 22 | ||||
| -rw-r--r-- | arch/msp430/src/lift.rs | 64 | ||||
| -rw-r--r-- | arch/msp430/src/register.rs | 25 | ||||
| -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 |
13 files changed, 561 insertions, 515 deletions
diff --git a/arch/msp430/Cargo.lock b/arch/msp430/Cargo.lock index 515b6ccf..22f7d7a3 100644 --- a/arch/msp430/Cargo.lock +++ b/arch/msp430/Cargo.lock @@ -25,7 +25,6 @@ name = "binaryninja" version = "0.1.0" dependencies = [ "binaryninjacore-sys", - "lazy_static", "log", ] @@ -111,12 +110,6 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -187,9 +180,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -237,9 +230,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.75" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", @@ -248,9 +241,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 = "windows-targets" diff --git a/arch/msp430/Cargo.toml b/arch/msp430/Cargo.toml index d97b8fc8..ddc442e8 100644 --- a/arch/msp430/Cargo.toml +++ b/arch/msp430/Cargo.toml @@ -5,14 +5,10 @@ authors = ["jrozner"] edition = "2021" [dependencies] -binaryninja = { path = "../../rust" } +binaryninja.workspace = true +binaryninjacore-sys.workspace = true log = "0.4" msp430-asm = "^0.2" [lib] crate-type = ["cdylib"] - -[profile.release] -panic = "abort" -lto = true -debug = 1 diff --git a/arch/msp430/build.rs b/arch/msp430/build.rs new file mode 100644 index 00000000..ed6cec7d --- /dev/null +++ b/arch/msp430/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/msp430/src/architecture.rs b/arch/msp430/src/architecture.rs index c37358ea..938e9ec5 100644 --- a/arch/msp430/src/architecture.rs +++ b/arch/msp430/src/architecture.rs @@ -4,11 +4,10 @@ use crate::register::Register; use binaryninja::{ architecture::{ - Architecture, BranchInfo, CoreArchitecture, CustomArchitectureHandle, FlagCondition, - InstructionInfo, UnusedIntrinsic, UnusedRegisterStack, UnusedRegisterStackInfo, + Architecture, CoreArchitecture, CustomArchitectureHandle, FlagCondition, InstructionInfo, + UnusedIntrinsic, UnusedRegisterStack, UnusedRegisterStackInfo, }, - disassembly::{InstructionTextToken, InstructionTextTokenContents}, - llil::{LiftedExpr, Lifter}, + disassembly::{InstructionTextToken, InstructionTextTokenKind}, Endianness, }; @@ -17,6 +16,11 @@ use msp430_asm::{ single_operand::SingleOperand, two_operand::TwoOperand, }; +use binaryninja::architecture::{ + BranchKind, FlagClassId, FlagGroupId, FlagId, FlagWriteId, RegisterId, +}; +use binaryninja::low_level_il::expression::ValueExpr; +use binaryninja::low_level_il::{MutableLiftedILExpr, MutableLiftedILFunction}; use log::error; const MIN_MNEMONIC: usize = 9; @@ -71,7 +75,7 @@ impl Architecture for Msp430 { 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 } @@ -82,137 +86,81 @@ impl Architecture for Msp430 { match inst { Instruction::Jnz(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jz(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jlo(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jc(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jn(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jge(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jl(inst) => { - info.add_branch( - BranchInfo::True(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); - info.add_branch( - BranchInfo::False(addr + inst.size() as u64), - Some(self.handle), - ); + info.add_branch(BranchKind::True(offset_to_absolute(addr, inst.offset()))); + info.add_branch(BranchKind::False(addr + inst.size() as u64)); } Instruction::Jmp(inst) => { - info.add_branch( - BranchInfo::Unconditional(offset_to_absolute(addr, inst.offset())), - Some(self.handle), - ); + info.add_branch(BranchKind::Unconditional(offset_to_absolute( + addr, + inst.offset(), + ))); } Instruction::Br(inst) => match inst.destination() { - Some(Operand::RegisterDirect(_)) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) - } - Some(Operand::Indexed(_)) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) + Some(Operand::RegisterDirect(_)) => info.add_branch(BranchKind::Indirect), + Some(Operand::Indexed(_)) => info.add_branch(BranchKind::Indirect), + Some(Operand::Absolute(value)) => { + info.add_branch(BranchKind::Unconditional(*value as u64)) } - Some(Operand::Absolute(value)) => info.add_branch( - BranchInfo::Unconditional(*value as u64), - Some(self.handle), - ), Some(Operand::Symbolic(offset)) => info.add_branch( - BranchInfo::Unconditional((addr as i64 + *offset as i64) as u64), - Some(self.handle), + BranchKind::Unconditional((addr as i64 + *offset as i64) as u64), ), - Some(Operand::Immediate(addr)) => info - .add_branch(BranchInfo::Unconditional(*addr as u64), Some(self.handle)), + Some(Operand::Immediate(addr)) => { + info.add_branch(BranchKind::Unconditional(*addr as u64)) + } Some(Operand::Constant(_)) => { - info.add_branch(BranchInfo::Unconditional(addr), Some(self.handle)) + info.add_branch(BranchKind::Unconditional(addr)) } Some(Operand::RegisterIndirect(_)) | Some(Operand::RegisterIndirectAutoIncrement(_)) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) + info.add_branch(BranchKind::Indirect) } None => {} }, Instruction::Call(inst) => match inst.source() { - Operand::RegisterDirect(_) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) - } - Operand::Indexed(_) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) - } + Operand::RegisterDirect(_) => info.add_branch(BranchKind::Indirect), + Operand::Indexed(_) => info.add_branch(BranchKind::Indirect), Operand::Absolute(value) => { - info.add_branch(BranchInfo::Call(*value as u64), Some(self.handle)) - } - Operand::Symbolic(offset) => info.add_branch( - BranchInfo::Call((addr as i64 + *offset as i64) as u64), - Some(self.handle), - ), - Operand::Immediate(addr) => { - info.add_branch(BranchInfo::Call(*addr as u64), Some(self.handle)) + info.add_branch(BranchKind::Call(*value as u64)) } - Operand::Constant(_) => { - info.add_branch(BranchInfo::Call(addr), Some(self.handle)) + Operand::Symbolic(offset) => { + info.add_branch(BranchKind::Call((addr as i64 + *offset as i64) as u64)) } + Operand::Immediate(addr) => info.add_branch(BranchKind::Call(*addr as u64)), + Operand::Constant(_) => info.add_branch(BranchKind::Call(addr)), Operand::RegisterIndirect(_) | Operand::RegisterIndirectAutoIncrement(_) => { - info.add_branch(BranchInfo::Indirect, Some(self.handle)) + info.add_branch(BranchKind::Indirect) } }, Instruction::Reti(_) => { - info.add_branch(BranchInfo::FunctionReturn, Some(self.handle)); + info.add_branch(BranchKind::FunctionReturn); } Instruction::Ret(_) => { - info.add_branch(BranchInfo::FunctionReturn, Some(self.handle)); + info.add_branch(BranchKind::FunctionReturn); } _ => {} } @@ -245,7 +193,7 @@ impl Architecture for Msp430 { &self, data: &[u8], addr: u64, - il: &mut Lifter<Self>, + il: &mut MutableLiftedILFunction<Self>, ) -> Option<(usize, bool)> { match msp430_asm::decode(data) { Ok(inst) => { @@ -277,8 +225,8 @@ impl Architecture for Msp430 { fn flag_group_llil<'a>( &self, _group: Self::FlagGroup, - _il: &'a mut Lifter<Self>, - ) -> Option<LiftedExpr<'a, Self>> { + _il: &'a mut MutableLiftedILFunction<Self>, + ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> { None } @@ -361,14 +309,14 @@ impl Architecture for Msp430 { None } - fn register_from_id(&self, id: u32) -> Option<Self::Register> { + fn register_from_id(&self, id: RegisterId) -> Option<Self::Register> { match id.try_into() { Ok(register) => Some(register), Err(_) => None, } } - fn flag_from_id(&self, id: u32) -> Option<Self::Flag> { + fn flag_from_id(&self, id: FlagId) -> Option<Self::Flag> { match id.try_into() { Ok(flag) => Some(flag), Err(_) => { @@ -378,7 +326,7 @@ impl Architecture for Msp430 { } } - fn flag_write_from_id(&self, id: u32) -> Option<Self::FlagWrite> { + fn flag_write_from_id(&self, id: FlagWriteId) -> Option<Self::FlagWrite> { match id.try_into() { Ok(flag_write) => Some(flag_write), Err(_) => { @@ -388,11 +336,11 @@ impl Architecture for Msp430 { } } - fn flag_class_from_id(&self, _: u32) -> Option<Self::FlagClass> { + fn flag_class_from_id(&self, _: FlagClassId) -> Option<Self::FlagClass> { None } - fn flag_group_from_id(&self, _: u32) -> Option<Self::FlagGroup> { + fn flag_group_from_id(&self, _: FlagGroupId) -> Option<Self::FlagGroup> { None } @@ -417,7 +365,7 @@ fn generate_tokens(inst: &Instruction, addr: u64) -> Vec<InstructionTextToken> { Instruction::Call(inst) => generate_single_operand_tokens(inst, addr, true), Instruction::Reti(_) => vec![InstructionTextToken::new( "reti", - InstructionTextTokenContents::Instruction, + InstructionTextTokenKind::Instruction, )], // Jxx instructions @@ -479,14 +427,14 @@ fn generate_single_operand_tokens( ) -> Vec<InstructionTextToken> { let mut res = vec![InstructionTextToken::new( inst.mnemonic(), - InstructionTextTokenContents::Instruction, + InstructionTextTokenKind::Instruction, )]; if inst.mnemonic().len() < MIN_MNEMONIC { let padding = " ".repeat(MIN_MNEMONIC - inst.mnemonic().len()); res.push(InstructionTextToken::new( - &padding, - InstructionTextTokenContents::Text, + padding, + InstructionTextTokenKind::Text, )) } @@ -500,20 +448,23 @@ fn generate_jxx_tokens(inst: &impl Jxx, addr: u64) -> Vec<InstructionTextToken> let mut res = vec![InstructionTextToken::new( inst.mnemonic(), - InstructionTextTokenContents::Instruction, + InstructionTextTokenKind::Instruction, )]; if inst.mnemonic().len() < MIN_MNEMONIC { let padding = " ".repeat(MIN_MNEMONIC - inst.mnemonic().len()); res.push(InstructionTextToken::new( - &padding, - InstructionTextTokenContents::Text, + padding, + InstructionTextTokenKind::Text, )) } res.push(InstructionTextToken::new( - &format!("0x{fixed_addr:4x}"), - InstructionTextTokenContents::CodeRelativeAddress(fixed_addr), + format!("0x{fixed_addr:4x}"), + InstructionTextTokenKind::CodeRelativeAddress { + value: fixed_addr, + size: None, + }, )); res @@ -522,21 +473,21 @@ fn generate_jxx_tokens(inst: &impl Jxx, addr: u64) -> Vec<InstructionTextToken> fn generate_two_operand_tokens(inst: &impl TwoOperand, addr: u64) -> Vec<InstructionTextToken> { let mut res = vec![InstructionTextToken::new( inst.mnemonic(), - InstructionTextTokenContents::Instruction, + InstructionTextTokenKind::Instruction, )]; if inst.mnemonic().len() < MIN_MNEMONIC { let padding = " ".repeat(MIN_MNEMONIC - inst.mnemonic().len()); res.push(InstructionTextToken::new( - &padding, - InstructionTextTokenContents::Text, + padding, + InstructionTextTokenKind::Text, )) } res.extend_from_slice(&generate_operand_tokens(inst.source(), addr, false)); res.push(InstructionTextToken::new( ", ", - InstructionTextTokenContents::OperandSeparator, + InstructionTextTokenKind::OperandSeparator, )); res.extend_from_slice(&generate_operand_tokens(inst.destination(), addr, false)); @@ -550,14 +501,14 @@ fn generate_emulated_tokens( ) -> Vec<InstructionTextToken> { let mut res = vec![InstructionTextToken::new( inst.mnemonic(), - InstructionTextTokenContents::Instruction, + InstructionTextTokenKind::Instruction, )]; if inst.mnemonic().len() < MIN_MNEMONIC { let padding = " ".repeat(MIN_MNEMONIC - inst.mnemonic().len()); res.push(InstructionTextToken::new( &padding, - InstructionTextTokenContents::Text, + InstructionTextTokenKind::Text, )) } @@ -577,23 +528,23 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr Operand::RegisterDirect(r) => match r { 0 => vec![InstructionTextToken::new( "pc", - InstructionTextTokenContents::Register, + InstructionTextTokenKind::Register, )], 1 => vec![InstructionTextToken::new( "sp", - InstructionTextTokenContents::Register, + InstructionTextTokenKind::Register, )], 2 => vec![InstructionTextToken::new( "sr", - InstructionTextTokenContents::Register, + InstructionTextTokenKind::Register, )], 3 => vec![InstructionTextToken::new( "cg", - InstructionTextTokenContents::Register, + InstructionTextTokenKind::Register, )], _ => vec![InstructionTextToken::new( - &format!("r{r}"), - InstructionTextTokenContents::Register, + format!("r{r}"), + InstructionTextTokenKind::Register, )], }, Operand::Indexed((r, i)) => match r { @@ -606,11 +557,14 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr vec![ InstructionTextToken::new( &num_text, - InstructionTextTokenContents::Integer(*i as u64), + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), - InstructionTextToken::new("(", InstructionTextTokenContents::Text), - InstructionTextToken::new("pc", InstructionTextTokenContents::Register), - InstructionTextToken::new(")", InstructionTextTokenContents::Text), + InstructionTextToken::new("(", InstructionTextTokenKind::Text), + InstructionTextToken::new("pc", InstructionTextTokenKind::Register), + InstructionTextToken::new(")", InstructionTextTokenKind::Text), ] } 1 => { @@ -622,11 +576,14 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr vec![ InstructionTextToken::new( &num_text, - InstructionTextTokenContents::Integer(*i as u64), + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), - InstructionTextToken::new("(", InstructionTextTokenContents::Text), - InstructionTextToken::new("sp", InstructionTextTokenContents::Register), - InstructionTextToken::new(")", InstructionTextTokenContents::Text), + InstructionTextToken::new("(", InstructionTextTokenKind::Text), + InstructionTextToken::new("sp", InstructionTextTokenKind::Register), + InstructionTextToken::new(")", InstructionTextTokenKind::Text), ] } 2 => { @@ -638,11 +595,14 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr vec![ InstructionTextToken::new( &num_text, - InstructionTextTokenContents::Integer(*i as u64), + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), - InstructionTextToken::new("(", InstructionTextTokenContents::Text), - InstructionTextToken::new("sr", InstructionTextTokenContents::Register), - InstructionTextToken::new(")", InstructionTextTokenContents::Text), + InstructionTextToken::new("(", InstructionTextTokenKind::Text), + InstructionTextToken::new("sr", InstructionTextTokenKind::Register), + InstructionTextToken::new(")", InstructionTextTokenKind::Text), ] } 3 => { @@ -654,11 +614,14 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr vec![ InstructionTextToken::new( &num_text, - InstructionTextTokenContents::Integer(*i as u64), + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), - InstructionTextToken::new("(", InstructionTextTokenContents::Text), - InstructionTextToken::new("cg", InstructionTextTokenContents::Register), - InstructionTextToken::new(")", InstructionTextTokenContents::Text), + InstructionTextToken::new("(", InstructionTextTokenKind::Text), + InstructionTextToken::new("cg", InstructionTextTokenKind::Register), + InstructionTextToken::new(")", InstructionTextTokenKind::Text), ] } _ => { @@ -670,14 +633,14 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr vec![ InstructionTextToken::new( &num_text, - InstructionTextTokenContents::Integer(*i as u64), + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), - InstructionTextToken::new("(", InstructionTextTokenContents::Text), - InstructionTextToken::new( - &format!("r{r}"), - InstructionTextTokenContents::Register, - ), - InstructionTextToken::new(")", InstructionTextTokenContents::Text), + InstructionTextToken::new("(", InstructionTextTokenKind::Text), + InstructionTextToken::new(format!("r{r}"), InstructionTextTokenKind::Register), + InstructionTextToken::new(")", InstructionTextTokenKind::Text), ] } }, @@ -689,8 +652,8 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr }; vec![ - InstructionTextToken::new("@", InstructionTextTokenContents::Text), - InstructionTextToken::new(&r_text, InstructionTextTokenContents::Register), + InstructionTextToken::new("@", InstructionTextTokenKind::Text), + InstructionTextToken::new(r_text, InstructionTextTokenKind::Register), ] } Operand::RegisterIndirectAutoIncrement(r) => { @@ -701,41 +664,53 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr }; vec![ - InstructionTextToken::new("@", InstructionTextTokenContents::Text), - InstructionTextToken::new(&r_text, InstructionTextTokenContents::Register), - InstructionTextToken::new("+", InstructionTextTokenContents::Text), + InstructionTextToken::new("@", InstructionTextTokenKind::Text), + InstructionTextToken::new(r_text, InstructionTextTokenKind::Register), + InstructionTextToken::new("+", InstructionTextTokenKind::Text), ] } Operand::Symbolic(i) => { - let val = (addr as i64 + *i as i64) as u64; + let value = (addr as i64 + *i as i64) as u64; vec![InstructionTextToken::new( - &format!("{val:#x}"), - InstructionTextTokenContents::CodeRelativeAddress(val), + format!("{value:#x}"), + InstructionTextTokenKind::CodeRelativeAddress { value, size: None }, )] } Operand::Immediate(i) => { if call { vec![InstructionTextToken::new( - &format!("{i:#x}"), - InstructionTextTokenContents::CodeRelativeAddress(*i as u64), + format!("{i:#x}"), + InstructionTextTokenKind::CodeRelativeAddress { + value: *i as u64, + size: None, + }, )] } else { vec![InstructionTextToken::new( - &format!("{i:#x}"), - InstructionTextTokenContents::PossibleAddress(*i as u64), + format!("{i:#x}"), + InstructionTextTokenKind::PossibleAddress { + value: *i as u64, + size: None, + }, )] } } Operand::Absolute(a) => { if call { vec![InstructionTextToken::new( - &format!("{a:#x}"), - InstructionTextTokenContents::CodeRelativeAddress(*a as u64), + format!("{a:#x}"), + InstructionTextTokenKind::CodeRelativeAddress { + value: *a as u64, + size: None, + }, )] } else { vec![InstructionTextToken::new( - &format!("{a:#x}"), - InstructionTextTokenContents::PossibleAddress(*a as u64), + format!("{a:#x}"), + InstructionTextTokenKind::PossibleAddress { + value: *a as u64, + size: None, + }, )] } } @@ -747,10 +722,13 @@ fn generate_operand_tokens(source: &Operand, addr: u64, call: bool) -> Vec<Instr }; vec![ - InstructionTextToken::new("#", InstructionTextTokenContents::Text), + InstructionTextToken::new("#", InstructionTextTokenKind::Text), InstructionTextToken::new( - &num_text, - InstructionTextTokenContents::Integer(*i as u64), + num_text, + InstructionTextTokenKind::Integer { + value: *i as u64, + size: None, + }, ), ] } diff --git a/arch/msp430/src/flag.rs b/arch/msp430/src/flag.rs index 115fe866..5baca412 100644 --- a/arch/msp430/src/flag.rs +++ b/arch/msp430/src/flag.rs @@ -1,5 +1,5 @@ use binaryninja::architecture; -use binaryninja::architecture::FlagRole; +use binaryninja::architecture::{FlagClassId, FlagGroupId, FlagId, FlagRole, FlagWriteId}; use std::borrow::Cow; use std::collections::HashMap; @@ -25,7 +25,7 @@ impl architecture::Flag for Flag { } } - fn role(&self, _class: Option<Self::FlagClass>) -> architecture::FlagRole { + fn role(&self, _class: Option<Self::FlagClass>) -> FlagRole { match self { Self::C => FlagRole::CarryFlagRole, Self::Z => FlagRole::ZeroFlagRole, @@ -34,20 +34,21 @@ impl architecture::Flag for Flag { } } - fn id(&self) -> u32 { + fn id(&self) -> FlagId { match self { Self::C => 0, Self::Z => 1, Self::N => 2, Self::V => 8, } + .into() } } -impl TryFrom<u32> for Flag { +impl TryFrom<FlagId> for Flag { type Error = (); - fn try_from(flag: u32) -> Result<Self, Self::Error> { - match flag { + fn try_from(flag: FlagId) -> Result<Self, Self::Error> { + match flag.0 { 0 => Ok(Self::C), 1 => Ok(Self::Z), 2 => Ok(Self::N), @@ -65,7 +66,7 @@ impl architecture::FlagClass for FlagClass { unimplemented!() } - fn id(&self) -> u32 { + fn id(&self) -> FlagClassId { unimplemented!() } } @@ -81,7 +82,7 @@ impl architecture::FlagGroup for FlagGroup { unimplemented!() } - fn id(&self) -> u32 { + fn id(&self) -> FlagGroupId { unimplemented!() } @@ -119,13 +120,14 @@ impl architecture::FlagWrite for FlagWrite { None } - fn id(&self) -> u32 { + fn id(&self) -> FlagWriteId { match self { Self::All => 1, Self::Nz => 2, Self::Nvz => 3, Self::Cnz => 4, } + .into() } fn flags_written(&self) -> Vec<Self::FlagType> { @@ -138,11 +140,11 @@ impl architecture::FlagWrite for FlagWrite { } } -impl TryFrom<u32> for FlagWrite { +impl TryFrom<FlagWriteId> for FlagWrite { type Error = (); - fn try_from(value: u32) -> Result<Self, Self::Error> { - match value { + fn try_from(value: FlagWriteId) -> Result<Self, Self::Error> { + match value.0 { 1 => Ok(Self::All), 2 => Ok(Self::Nz), 3 => Ok(Self::Nvz), diff --git a/arch/msp430/src/lib.rs b/arch/msp430/src/lib.rs index 7654b33c..b5465554 100644 --- a/arch/msp430/src/lib.rs +++ b/arch/msp430/src/lib.rs @@ -2,8 +2,14 @@ extern crate binaryninja; extern crate log; extern crate msp430_asm; +use binaryninja::{ + add_optional_plugin_dependency, + architecture::ArchitectureExt, + calling_convention, + custom_binary_view::{BinaryViewType, BinaryViewTypeExt}, + Endianness, +}; use log::LevelFilter; -use binaryninja::{add_optional_plugin_dependency, architecture::ArchitectureExt, callingconvention, custombinaryview::{BinaryViewType, BinaryViewTypeExt}, Endianness}; mod architecture; mod flag; @@ -17,10 +23,10 @@ use binaryninja::logger::Logger; #[allow(non_snake_case)] pub extern "C" fn CorePluginInit() -> bool { Logger::new("MSP430").with_level(LevelFilter::Info).init(); - let arch = binaryninja::architecture::register_architecture( - "msp430", - |custom_handle, handle| Msp430::new(handle, custom_handle), - ); + let arch = + binaryninja::architecture::register_architecture("msp430", |custom_handle, handle| { + Msp430::new(handle, custom_handle) + }); // we may need to introduce additional calling conventions here to // support additional ABIs. MSPGCC's calling convention (what @@ -30,13 +36,13 @@ pub extern "C" fn CorePluginInit() -> bool { // https://www.ti.com/lit/an/slaa664/slaa664.pdf?ts=1613210655081. MSPGCC // appears to be a legacy calling convention while EABI is the newer // standardized one that is compatible with TI's compiler - let default = callingconvention::ConventionBuilder::new(arch) + let default = calling_convention::ConventionBuilder::new(arch) .is_eligible_for_heuristics(true) .int_arg_registers(&["r15", "r14", "r13", "r12"]) .return_int_reg("r15") .return_hi_int_reg("r14") .register("default"); - callingconvention::ConventionBuilder::new(arch) + calling_convention::ConventionBuilder::new(arch) .is_eligible_for_heuristics(true) .return_int_reg("r15") .return_hi_int_reg("r14") @@ -55,4 +61,4 @@ pub extern "C" fn CorePluginInit() -> bool { #[allow(non_snake_case)] pub extern "C" fn CorePluginDependencies() { add_optional_plugin_dependency("view_elf"); -}
\ No newline at end of file +} diff --git a/arch/msp430/src/lift.rs b/arch/msp430/src/lift.rs index feb8ce35..6ad7b67b 100644 --- a/arch/msp430/src/lift.rs +++ b/arch/msp430/src/lift.rs @@ -3,10 +3,7 @@ use crate::flag::{Flag, FlagWrite}; use crate::register::Register; use crate::Msp430; -use binaryninja::{ - architecture::FlagCondition, - llil::{Label, LiftedNonSSA, Lifter, Mutable, NonSSA}, -}; +use binaryninja::{architecture::FlagCondition, low_level_il::lifting::LowLevelILLabel}; use msp430_asm::emulate::Emulated; use msp430_asm::instruction::Instruction; @@ -15,6 +12,8 @@ use msp430_asm::operand::{Operand, OperandWidth}; use msp430_asm::single_operand::SingleOperand; use msp430_asm::two_operand::TwoOperand; +use binaryninja::low_level_il::expression::ValueExpr; +use binaryninja::low_level_il::{MutableLiftedILExpr, MutableLiftedILFunction}; use log::info; macro_rules! auto_increment { @@ -138,31 +137,38 @@ macro_rules! conditional_jump { ($addr:ident, $inst:ident, $cond:ident, $il:ident) => { let true_addr = offset_to_absolute($addr, $inst.offset()); let false_addr = $addr + $inst.size() as u64; - let mut new_true = Label::new(); - let mut new_false = Label::new(); + let mut new_true = true; + let mut new_false = false; - let true_label = $il.label_for_address(true_addr); - let false_label = $il.label_for_address(false_addr); + let mut true_label = $il.label_for_address(true_addr).unwrap_or_else(|| { + new_true = true; + LowLevelILLabel::new() + }); - $il.if_expr( - $cond, - true_label.unwrap_or_else(|| &new_true), - false_label.unwrap_or_else(|| &new_false), - ) - .append(); - - if true_label.is_none() { - $il.mark_label(&mut new_true); + let mut false_label = $il.label_for_address(false_addr).unwrap_or_else(|| { + new_false = true; + LowLevelILLabel::new() + }); + + $il.if_expr($cond, &mut true_label, &mut false_label) + .append(); + + if new_true { + $il.mark_label(&mut true_label); $il.jump($il.const_ptr(true_addr)).append(); } - if false_label.is_none() { - $il.mark_label(&mut new_false); + if new_false { + $il.mark_label(&mut false_label); } }; } -pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &Lifter<Msp430>) { +pub(crate) fn lift_instruction( + inst: &Instruction, + addr: u64, + il: &MutableLiftedILFunction<Msp430>, +) { match inst { Instruction::Rrc(inst) => { let size = match inst.operand_width() { @@ -277,8 +283,8 @@ pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &Lifter<Msp430 let fixed_addr = offset_to_absolute(addr, inst.offset()); let label = il.label_for_address(fixed_addr); match label { - Some(label) => { - il.goto(label).append(); + Some(mut label) => { + il.goto(&mut label).append(); } None => { il.jump(il.const_ptr(fixed_addr)).append(); @@ -411,8 +417,8 @@ pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &Lifter<Msp430 } Instruction::Br(inst) => { let dest = if let Some(Operand::Immediate(dest)) = inst.destination() { - if let Some(label) = il.label_for_address(*dest as u64) { - il.goto(label).append(); + if let Some(mut label) = il.label_for_address(*dest as u64) { + il.goto(&mut label).append(); return; } else { il.const_ptr(*dest as u64) @@ -622,14 +628,8 @@ pub(crate) fn lift_instruction(inst: &Instruction, addr: u64, il: &Lifter<Msp430 fn lift_source_operand<'a>( operand: &Operand, size: usize, - il: &'a Lifter<Msp430>, -) -> binaryninja::llil::Expression< - 'a, - Msp430, - Mutable, - NonSSA<LiftedNonSSA>, - binaryninja::llil::ValueExpr, -> { + il: &'a MutableLiftedILFunction<Msp430>, +) -> MutableLiftedILExpr<'a, Msp430, ValueExpr> { match operand { Operand::RegisterDirect(r) => il.reg(size, Register::try_from(*r as u32).unwrap()), Operand::Indexed((r, offset)) => il diff --git a/arch/msp430/src/register.rs b/arch/msp430/src/register.rs index 20a5dff8..0886e537 100644 --- a/arch/msp430/src/register.rs +++ b/arch/msp430/src/register.rs @@ -1,6 +1,7 @@ use binaryninja::architecture; -use binaryninja::architecture::ImplicitRegisterExtend; +use binaryninja::architecture::{ImplicitRegisterExtend, RegisterId}; +use binaryninja::low_level_il::LowLevelILRegister; use std::borrow::Cow; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -23,15 +24,15 @@ pub enum Register { R15, } -impl TryFrom<u32> for Register { +impl TryFrom<RegisterId> for Register { type Error = (); - fn try_from(id: u32) -> Result<Self, Self::Error> { + fn try_from(id: RegisterId) -> Result<Self, Self::Error> { // TODO: we should return separate errors if the id is between 0x7fff_ffff and 0xffff_ffff // vs outside of that range. Temporary registers have have the high bit set which we // shouldn't get, unless there is a bug in core. An id that isn't within that range but we // don't handle is a bug in the architecture. - match id { + match id.0 { 0 => Ok(Self::Pc), 1 => Ok(Self::Sp), 2 => Ok(Self::Sr), @@ -53,6 +54,15 @@ impl TryFrom<u32> for Register { } } +// TODO: Get rid of this and lift all u32 vals to a proper register id. +impl TryFrom<u32> for Register { + type Error = (); + + fn try_from(id: u32) -> Result<Self, Self::Error> { + Register::try_from(RegisterId(id)) + } +} + impl architecture::Register for Register { type InfoType = Self; @@ -81,7 +91,7 @@ impl architecture::Register for Register { *self } - fn id(&self) -> u32 { + fn id(&self) -> RegisterId { match self { Self::Pc => 0, Self::Sp => 1, @@ -100,6 +110,7 @@ impl architecture::Register for Register { Self::R14 => 14, Self::R15 => 15, } + .into() } } @@ -123,8 +134,8 @@ impl architecture::RegisterInfo for Register { } } -impl From<Register> for binaryninja::llil::Register<Register> { +impl From<Register> for LowLevelILRegister<Register> { fn from(register: Register) -> Self { - binaryninja::llil::Register::ArchReg(register) + LowLevelILRegister::ArchReg(register) } } 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") { |
