summaryrefslogtreecommitdiff
path: root/arch/riscv/src
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv/src')
-rw-r--r--arch/riscv/src/lib.rs494
1 files changed, 269 insertions, 225 deletions
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(&reg.name(), Register));
+ res.push(InstructionTextToken::new(reg.name(), Register));
}
Operand::F(r) => {
let reg = self::Register::from(r);
- res.push(InstructionTextToken::new(&reg.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(&reg.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") {