summaryrefslogtreecommitdiff
path: root/rust/src/mlil/lift.rs
diff options
context:
space:
mode:
authorMichael Krasnitski <michael.krasnitski@gmail.com>2024-02-07 11:44:06 -0500
committerKyle Martin <krm504@nyu.edu>2024-03-18 17:46:37 -0400
commit5fcf6bc59ebc2110d053360d223e6570cdd2272c (patch)
treeed6eafd132cf53fd9e7105f541967324b4165db0 /rust/src/mlil/lift.rs
parentbdd012af7941c7d17b97b3e69628a7bc7cc2411e (diff)
Refactor MLIL instructions
* Turn `MediumLevelILInstruction` into a struct with a `kind` field to indicate the instruction variant, and pull out the `function` and `address` fields from each variant to live in the top-level struct. * Make variant fields public, remove field getter methods and centralize lifting logic to happen all at once. Split tuple fields into individual named fields. * Move the `operands` method to `MediumLevelILLiftedInstruction`, and make it return an owned `Vec` of operands rather than a borrowed iterator.
Diffstat (limited to 'rust/src/mlil/lift.rs')
-rw-r--r--rust/src/mlil/lift.rs250
1 files changed, 244 insertions, 6 deletions
diff --git a/rust/src/mlil/lift.rs b/rust/src/mlil/lift.rs
index bf7f16db..0cf669bf 100644
--- a/rust/src/mlil/lift.rs
+++ b/rust/src/mlil/lift.rs
@@ -1,12 +1,43 @@
+use std::collections::HashMap;
+
+use crate::rc::Ref;
+use crate::types;
+use crate::types::ILIntrinsic;
+use crate::types::{SSAVariable, Variable};
+
use super::operation::*;
+use super::MediumLevelILFunction;
+
+#[derive(Clone)]
+pub enum MediumLevelILLiftedOperand {
+ ConstantData(types::ConstantData),
+ Intrinsic(ILIntrinsic),
+ Expr(MediumLevelILLiftedInstruction),
+ ExprList(Vec<MediumLevelILLiftedInstruction>),
+ Float(f64),
+ Int(u64),
+ IntList(Vec<u64>),
+ TargetMap(HashMap<u64, u64>),
+ Var(Variable),
+ VarList(Vec<Variable>),
+ VarSsa(SSAVariable),
+ VarSsaList(Vec<SSAVariable>),
+}
#[derive(Clone, Debug, PartialEq)]
-pub enum MediumLevelILLiftedInstruction {
- 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),
@@ -133,3 +164,210 @@ pub enum MediumLevelILLiftedInstruction {
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))],
+ }
+ }
+}