This commit is contained in:
Rairosu
2024-04-02 18:52:06 +02:00
parent e7c2b2bd2a
commit 2feb739d75
42 changed files with 4785 additions and 2675 deletions

View File

@@ -21,7 +21,7 @@ impl Iterator for MediumLevelILBlockIter {
.map(|i| unsafe {
BNGetMediumLevelILIndexForInstruction(self.function.handle, i as usize)
})
.map(|i| MediumLevelILInstruction::new(&self.function, i))
.map(|i| MediumLevelILInstruction::new(self.function.to_owned(), i))
}
}
@@ -43,7 +43,7 @@ impl BlockContext for MediumLevelILBlock {
let expr_idx = unsafe {
BNGetMediumLevelILIndexForInstruction(self.function.handle, block.raw_start() as usize)
};
MediumLevelILInstruction::new(&self.function, expr_idx)
MediumLevelILInstruction::new(self.function.to_owned(), expr_idx)
}
fn iter(&self, block: &BasicBlock<Self>) -> MediumLevelILBlockIter {

View File

@@ -14,7 +14,7 @@ use crate::function::Function;
use crate::function::Location;
use crate::rc::{Array, Ref, RefCountable};
use super::{MediumLevelILBlock, MediumLevelILInstruction};
use super::{MediumLevelILBlock, MediumLevelILInstruction, MediumLevelILLiftedInstruction};
pub struct MediumLevelILFunction {
pub(crate) handle: *mut BNMediumLevelILFunction,
@@ -26,21 +26,21 @@ unsafe impl Sync for MediumLevelILFunction {}
impl Eq for MediumLevelILFunction {}
impl PartialEq for MediumLevelILFunction {
fn eq(&self, rhs: &Self) -> bool {
self.handle == rhs.handle
self.get_function().eq(&rhs.get_function())
}
}
impl Hash for MediumLevelILFunction {
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
self.get_function().hash(state)
}
}
impl MediumLevelILFunction {
pub(crate) unsafe fn from_raw(handle: *mut BNMediumLevelILFunction) -> Self {
pub(crate) unsafe fn ref_from_raw(handle: *mut BNMediumLevelILFunction) -> Ref<Self> {
debug_assert!(!handle.is_null());
Self { handle }
Self { handle }.to_owned()
}
pub fn instruction_at<L: Into<Location>>(&self, loc: L) -> Option<MediumLevelILInstruction> {
@@ -53,12 +53,16 @@ impl MediumLevelILFunction {
if expr_idx >= self.instruction_count() {
None
} else {
Some(MediumLevelILInstruction::new(self, expr_idx))
Some(MediumLevelILInstruction::new(self.to_owned(), expr_idx))
}
}
pub fn instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILInstruction {
MediumLevelILInstruction::new(self, expr_idx)
MediumLevelILInstruction::new(self.to_owned(), expr_idx)
}
pub fn lifted_instruction_from_idx(&self, expr_idx: usize) -> MediumLevelILLiftedInstruction {
self.instruction_from_idx(expr_idx).lift()
}
pub fn instruction_count(&self) -> usize {

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,48 @@
use super::operation::*;
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq)]
pub struct MediumLevelILLiftedInstruction {
pub address: u64,
pub operation: MediumLevelILLiftedOperation,
use crate::rc::Ref;
use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable};
use super::operation::*;
use super::MediumLevelILFunction;
#[derive(Clone)]
pub enum MediumLevelILLiftedOperand {
ConstantData(ConstantData),
Intrinsic(ILIntrinsic),
Expr(MediumLevelILLiftedInstruction),
ExprList(Vec<MediumLevelILLiftedInstruction>),
Float(f64),
Int(u64),
IntList(Vec<u64>),
TargetMap(BTreeMap<u64, u64>),
Var(Variable),
VarList(Vec<Variable>),
VarSsa(SSAVariable),
VarSsaList(Vec<SSAVariable>),
}
#[derive(Clone, Debug, PartialEq)]
pub enum MediumLevelILLiftedOperation {
Nop(NoArgs),
Noret(NoArgs),
Bp(NoArgs),
Undef(NoArgs),
Unimpl(NoArgs),
pub struct MediumLevelILLiftedInstruction {
pub function: Ref<MediumLevelILFunction>,
pub address: u64,
pub kind: MediumLevelILLiftedInstructionKind,
}
#[derive(Clone, Debug, PartialEq)]
pub enum MediumLevelILLiftedInstructionKind {
Nop,
Noret,
Bp,
Undef,
Unimpl,
If(LiftedIf),
FloatConst(FloatConst),
Const(Constant),
ConstPtr(Constant),
Import(Constant),
ExternPtr(ExternPtr),
ConstData(ConstantData),
ConstData(LiftedConstData),
Jump(LiftedJump),
RetHint(LiftedJump),
StoreSsa(LiftedStoreSsa),
@@ -93,8 +116,8 @@ pub enum MediumLevelILLiftedOperation {
Rrc(LiftedBinaryOpCarry),
Call(LiftedCall),
Tailcall(LiftedCall),
Intrinsic(LiftedInnerCall),
Syscall(LiftedInnerCall),
Intrinsic(LiftedIntrinsic),
Syscall(LiftedSyscallCall),
IntrinsicSsa(LiftedIntrinsicSsa),
CallSsa(LiftedCallSsa),
TailcallSsa(LiftedCallSsa),
@@ -139,3 +162,210 @@ pub enum MediumLevelILLiftedOperation {
VarAliasedField(VarSsaField),
Trap(Trap),
}
impl MediumLevelILLiftedInstruction {
pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
use MediumLevelILLiftedInstructionKind::*;
use MediumLevelILLiftedOperand as Operand;
match &self.kind {
Nop | Noret | Bp | Undef | Unimpl => vec![],
If(op) => vec![
("condition", Operand::Expr(*op.condition.clone())),
("dest_true", Operand::Int(op.dest_true)),
("dest_false", Operand::Int(op.dest_false)),
],
FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
ExternPtr(op) => vec![
("constant", Operand::Int(op.constant)),
("offset", Operand::Int(op.offset)),
],
ConstData(op) => vec![(
"constant_data",
Operand::ConstantData(op.constant_data.clone()),
)],
Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
StoreSsa(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::Int(op.src_memory)),
("src", Operand::Expr(*op.src.clone())),
],
StoreStructSsa(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("offset", Operand::Int(op.offset)),
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::Int(op.src_memory)),
("src", Operand::Expr(*op.src.clone())),
],
StoreStruct(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("offset", Operand::Int(op.offset)),
("src", Operand::Expr(*op.src.clone())),
],
Store(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("src", Operand::Expr(*op.src.clone())),
],
JumpTo(op) => vec![
("dest", Operand::Expr(*op.dest.clone())),
("targets", Operand::TargetMap(op.targets.clone())),
],
Goto(op) => vec![("dest", Operand::Int(op.dest))],
FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))],
SetVarField(op) => vec![
("dest", Operand::Var(op.dest)),
("offset", Operand::Int(op.offset)),
("src", Operand::Expr(*op.src.clone())),
],
SetVar(op) => vec![
("dest", Operand::Var(op.dest)),
("src", Operand::Expr(*op.src.clone())),
],
FreeVarSlotSsa(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("prev", Operand::VarSsa(op.prev)),
],
SetVarSsaField(op) | SetVarAliasedField(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("prev", Operand::VarSsa(op.prev)),
("offset", Operand::Int(op.offset)),
("src", Operand::Expr(*op.src.clone())),
],
SetVarAliased(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("prev", Operand::VarSsa(op.prev)),
("src", Operand::Expr(*op.src.clone())),
],
SetVarSsa(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("src", Operand::Expr(*op.src.clone())),
],
VarPhi(op) => vec![
("dest", Operand::VarSsa(op.dest)),
("src", Operand::VarSsaList(op.src.clone())),
],
MemPhi(op) => vec![
("dest_memory", Operand::Int(op.dest_memory)),
("src_memory", Operand::IntList(op.src_memory.clone())),
],
VarSplit(op) => vec![
("high", Operand::Var(op.high)),
("low", Operand::Var(op.low)),
],
SetVarSplit(op) => vec![
("high", Operand::Var(op.high)),
("low", Operand::Var(op.low)),
("src", Operand::Expr(*op.src.clone())),
],
VarSplitSsa(op) => vec![
("high", Operand::VarSsa(op.high)),
("low", Operand::VarSsa(op.low)),
],
SetVarSplitSsa(op) => vec![
("high", Operand::VarSsa(op.high)),
("low", Operand::VarSsa(op.low)),
("src", Operand::Expr(*op.src.clone())),
],
Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
| Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
| Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
| CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
| CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | FcmpE(op)
| FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
| FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![
("left", Operand::Expr(*op.left.clone())),
("right", Operand::Expr(*op.right.clone())),
],
Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
("left", Operand::Expr(*op.left.clone())),
("right", Operand::Expr(*op.right.clone())),
("carry", Operand::Expr(*op.carry.clone())),
],
Call(op) | Tailcall(op) => vec![
("output", Operand::VarList(op.output.clone())),
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
],
Syscall(op) => vec![
("output", Operand::VarList(op.output.clone())),
("params", Operand::ExprList(op.params.clone())),
],
Intrinsic(op) => vec![
("output", Operand::VarList(op.output.clone())),
("intrinsic", Operand::Intrinsic(op.intrinsic)),
("params", Operand::ExprList(op.params.clone())),
],
IntrinsicSsa(op) => vec![
("output", Operand::VarSsaList(op.output.clone())),
("intrinsic", Operand::Intrinsic(op.intrinsic)),
("params", Operand::ExprList(op.params.clone())),
],
CallSsa(op) | TailcallSsa(op) => vec![
("output", Operand::VarSsaList(op.output.clone())),
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![
("output", Operand::VarSsaList(op.output.clone())),
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
("stack", Operand::Expr(*op.stack.clone())),
],
SyscallSsa(op) => vec![
("output", Operand::VarSsaList(op.output.clone())),
("params", Operand::ExprList(op.params.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
SyscallUntypedSsa(op) => vec![
("output", Operand::VarSsaList(op.output.clone())),
("params", Operand::ExprList(op.params.clone())),
("stack", Operand::Expr(*op.stack.clone())),
],
CallUntyped(op) | TailcallUntyped(op) => vec![
("output", Operand::VarList(op.output.clone())),
("dest", Operand::Expr(*op.dest.clone())),
("params", Operand::ExprList(op.params.clone())),
("stack", Operand::Expr(*op.stack.clone())),
],
SyscallUntyped(op) => vec![
("output", Operand::VarList(op.output.clone())),
("params", Operand::ExprList(op.params.clone())),
("stack", Operand::Expr(*op.stack.clone())),
],
Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op)
| Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op)
| RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => {
vec![("src", Operand::Expr(*op.src.clone()))]
}
LoadStruct(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("offset", Operand::Int(op.offset)),
],
LoadStructSsa(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("offset", Operand::Int(op.offset)),
("src_memory", Operand::Int(op.src_memory)),
],
LoadSsa(op) => vec![
("src", Operand::Expr(*op.src.clone())),
("src_memory", Operand::Int(op.src_memory)),
],
Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))],
SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))],
Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))],
VarField(op) | AddressOfField(op) => vec![
("src", Operand::Var(op.src)),
("offset", Operand::Int(op.offset)),
],
VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))],
VarSsaField(op) | VarAliasedField(op) => vec![
("src", Operand::VarSsa(op.src)),
("offset", Operand::Int(op.offset)),
],
Trap(op) => vec![("vector", Operand::Int(op.vector))],
}
}
}

File diff suppressed because it is too large Load Diff