summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rust/src/high_level_il/instruction.rs127
-rw-r--r--rust/src/lib.rs1
-rw-r--r--rust/src/medium_level_il/instruction.rs269
-rw-r--r--rust/src/operand_iter.rs237
-rw-r--r--rust/tests/medium_level_il.rs4
5 files changed, 276 insertions, 362 deletions
diff --git a/rust/src/high_level_il/instruction.rs b/rust/src/high_level_il/instruction.rs
index 00900de7..67225eea 100644
--- a/rust/src/high_level_il/instruction.rs
+++ b/rust/src/high_level_il/instruction.rs
@@ -7,7 +7,6 @@ use super::{HighLevelILFunction, HighLevelILLiftedInstruction, HighLevelILLifted
use crate::architecture::{CoreIntrinsic, IntrinsicId};
use crate::confidence::Conf;
use crate::disassembly::DisassemblyTextLine;
-use crate::operand_iter::OperandIter;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
use crate::types::Type;
use crate::variable::{ConstantData, RegisterValue, SSAVariable, Variable};
@@ -552,6 +551,38 @@ impl HighLevelILInstruction {
}
}
+ fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
+ let mut count = 0;
+ let raw_list_ptr = unsafe {
+ BNHighLevelILGetOperandList(
+ self.function.handle,
+ self.expr_index.0,
+ operand_idx,
+ &mut count,
+ )
+ };
+ assert!(!raw_list_ptr.is_null());
+ let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
+ unsafe { BNHighLevelILFreeOperandList(raw_list_ptr) };
+ list
+ }
+
+ fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
+ self.get_operand_list(operand_idx)
+ .chunks(2)
+ .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
+ .map(|(var, version)| SSAVariable::new(var, version))
+ .collect()
+ }
+
+ fn get_expr_list(&self, operand_idx: usize) -> Vec<HighLevelILInstruction> {
+ self.get_operand_list(operand_idx)
+ .into_iter()
+ .map(|val| HighLevelInstructionIndex(val as usize))
+ .filter_map(|idx| self.function.instruction_from_expr_index(idx))
+ .collect()
+ }
+
pub fn lift(&self) -> HighLevelILLiftedInstruction {
use HighLevelILInstructionKind::*;
use HighLevelILLiftedInstructionKind as Lifted;
@@ -630,7 +661,11 @@ impl HighLevelILInstruction {
src: self.lift_operand(op.src),
}),
AssignUnpack(op) => Lifted::AssignUnpack(LiftedAssignUnpack {
- dest: self.lift_instruction_list(op.first_dest, op.num_dests),
+ dest: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
src: self.lift_operand(op.src),
}),
AssignMemSsa(op) => Lifted::AssignMemSsa(LiftedAssignMemSsa {
@@ -640,26 +675,42 @@ impl HighLevelILInstruction {
src_memory: op.src_memory,
}),
AssignUnpackMemSsa(op) => Lifted::AssignUnpackMemSsa(LiftedAssignUnpackMemSsa {
- dest: self.lift_instruction_list(op.first_dest, op.num_dests),
+ dest: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
dest_memory: op.dest_memory,
src: self.lift_operand(op.src),
src_memory: op.src_memory,
}),
- Block(op) => Lifted::Block(LiftedBlock {
- body: self.lift_instruction_list(op.first_param, op.num_params),
+ Block(_op) => Lifted::Block(LiftedBlock {
+ body: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
}),
Call(op) => Lifted::Call(self.lift_call(op)),
Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
CallSsa(op) => Lifted::CallSsa(LiftedCallSsa {
dest: self.lift_operand(op.dest),
- params: self.lift_instruction_list(op.first_param, op.num_params),
+ params: self
+ .get_expr_list(1)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
dest_memory: op.dest_memory,
src_memory: op.src_memory,
}),
Case(op) => Lifted::Case(LiftedCase {
- values: self.lift_instruction_list(op.first_value, op.num_values),
+ values: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
body: self.lift_operand(op.body),
}),
Const(op) => Lifted::Const(op),
@@ -740,7 +791,11 @@ impl HighLevelILInstruction {
IntrinsicId(op.intrinsic),
)
.expect("Invalid intrinsic"),
- params: self.lift_instruction_list(op.first_param, op.num_params),
+ params: self
+ .get_expr_list(1)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
}),
IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
intrinsic: CoreIntrinsic::new(
@@ -748,7 +803,11 @@ impl HighLevelILInstruction {
IntrinsicId(op.intrinsic),
)
.expect("Invalid intrinsic"),
- params: self.lift_instruction_list(op.first_param, op.num_params),
+ params: self
+ .get_expr_list(1)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
dest_memory: op.dest_memory,
src_memory: op.src_memory,
}),
@@ -757,10 +816,14 @@ impl HighLevelILInstruction {
}),
MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
dest: op.dest,
- src: OperandIter::new(&*self.function, op.first_src, op.num_srcs).collect(),
+ src: self.get_operand_list(1),
}),
- Ret(op) => Lifted::Ret(LiftedRet {
- src: self.lift_instruction_list(op.first_src, op.num_srcs),
+ Ret(_op) => Lifted::Ret(LiftedRet {
+ src: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
}),
Split(op) => Lifted::Split(LiftedSplit {
high: self.lift_operand(op.high),
@@ -771,13 +834,25 @@ impl HighLevelILInstruction {
Switch(op) => Lifted::Switch(LiftedSwitch {
condition: self.lift_operand(op.condition),
default: self.lift_operand(op.default),
- cases: self.lift_instruction_list(op.first_case, op.num_cases),
+ cases: self
+ .get_expr_list(2)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
}),
- Syscall(op) => Lifted::Syscall(LiftedSyscall {
- params: self.lift_instruction_list(op.first_param, op.num_params),
+ Syscall(_op) => Lifted::Syscall(LiftedSyscall {
+ params: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
}),
SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
- params: self.lift_instruction_list(op.first_param, op.num_params),
+ params: self
+ .get_expr_list(0)
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
dest_memory: op.dest_memory,
src_memory: op.src_memory,
}),
@@ -794,9 +869,7 @@ impl HighLevelILInstruction {
}),
VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
dest: op.dest,
- src: OperandIter::new(&*self.function, op.first_src, op.num_srcs)
- .ssa_vars()
- .collect(),
+ src: self.get_ssa_var_list(2),
}),
VarSsa(op) => Lifted::VarSsa(op),
@@ -907,8 +980,9 @@ impl HighLevelILInstruction {
fn lift_call(&self, op: Call) -> LiftedCall {
LiftedCall {
dest: self.lift_operand(op.dest),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ params: self
+ .get_expr_list(1)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}
@@ -936,17 +1010,6 @@ impl HighLevelILInstruction {
member_index: op.member_index,
}
}
-
- fn lift_instruction_list(
- &self,
- first_instruction: usize,
- num_instructions: usize,
- ) -> Vec<HighLevelILLiftedInstruction> {
- OperandIter::new(&*self.function, first_instruction, num_instructions)
- .exprs()
- .map(|expr| expr.lift())
- .collect()
- }
}
impl CoreArrayProvider for HighLevelILInstruction {
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 80baae43..05c01077 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -26,7 +26,6 @@
#[macro_use]
mod ffi;
-mod operand_iter;
pub mod architecture;
pub mod background_task;
diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs
index b043788d..065e28f1 100644
--- a/rust/src/medium_level_il/instruction.rs
+++ b/rust/src/medium_level_il/instruction.rs
@@ -621,6 +621,54 @@ impl MediumLevelILInstruction {
}
}
+ fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
+ let mut count = 0;
+ let raw_list_ptr = unsafe {
+ BNMediumLevelILGetOperandList(
+ self.function.handle,
+ self.expr_index.0,
+ operand_idx,
+ &mut count,
+ )
+ };
+ assert!(!raw_list_ptr.is_null());
+ let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
+ unsafe { BNMediumLevelILFreeOperandList(raw_list_ptr) };
+ list
+ }
+
+ fn get_var_list(&self, operand_idx: usize) -> Vec<Variable> {
+ self.get_operand_list(operand_idx)
+ .into_iter()
+ .map(Variable::from_identifier)
+ .collect()
+ }
+
+ fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
+ self.get_operand_list(operand_idx)
+ .chunks(2)
+ .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
+ .map(|(var, version)| SSAVariable::new(var, version))
+ .collect()
+ }
+
+ fn get_expr_list(&self, operand_idx: usize) -> Vec<MediumLevelILInstruction> {
+ self.get_operand_list(operand_idx)
+ .into_iter()
+ .map(|val| MediumLevelInstructionIndex(val as usize))
+ .filter_map(|idx| self.function.instruction_from_expr_index(idx))
+ .collect()
+ }
+
+ fn get_target_map(&self, operand_idx: usize) -> BTreeMap<u64, MediumLevelInstructionIndex> {
+ self.get_operand_list(operand_idx)
+ .chunks(2)
+ // TODO: This filter is kinda redundant.
+ .filter_map(|chunk| chunk.get(0..2))
+ .map(|chunk| (chunk[0], MediumLevelInstructionIndex(chunk[1] as usize)))
+ .collect()
+ }
+
pub fn lift(&self) -> MediumLevelILLiftedInstruction {
use MediumLevelILInstructionKind::*;
use MediumLevelILLiftedInstructionKind as Lifted;
@@ -690,12 +738,7 @@ impl MediumLevelILInstruction {
}),
JumpTo(op) => Lifted::JumpTo(LiftedJumpTo {
dest: self.lift_operand(op.dest),
- targets: OperandIter::new(&*self.function, op.first_operand, op.num_operands)
- .pairs()
- .map(|(addr, instr_idx)| {
- (addr, MediumLevelInstructionIndex(instr_idx as usize))
- })
- .collect(),
+ targets: self.get_target_map(1),
}),
Goto(op) => Lifted::Goto(op),
FreeVarSlot(op) => Lifted::FreeVarSlot(op),
@@ -732,14 +775,12 @@ impl MediumLevelILInstruction {
}),
VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
dest: op.dest,
- src: OperandIter::new(&*self.function, op.first_operand, op.num_operands)
- .ssa_vars()
- .collect(),
+ src: self.get_ssa_var_list(2),
}),
MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
dest_memory: op.dest_memory,
- src_memory: OperandIter::new(&*self.function, op.first_operand, op.num_operands)
- .collect(),
+ // TODO: Make a stronger type for this.
+ src_memory: self.get_operand_list(0),
}),
VarSplit(op) => Lifted::VarSplit(op),
SetVarSplit(op) => Lifted::SetVarSplit(LiftedSetVarSplit {
@@ -809,42 +850,59 @@ impl MediumLevelILInstruction {
Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
- output: OperandIter::new(&*self.function, op.first_output, op.num_outputs)
- .vars()
- .collect(),
+ output: self.get_var_list(0),
intrinsic: CoreIntrinsic::new(
self.function.function().arch(),
IntrinsicId(op.intrinsic),
)
.expect("Valid intrinsic"),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ params: self
+ .get_expr_list(3)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}),
- Syscall(op) => Lifted::Syscall(LiftedSyscallCall {
- output: OperandIter::new(&*self.function, op.first_output, op.num_outputs)
- .vars()
- .collect(),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ Syscall(_op) => Lifted::Syscall(LiftedSyscallCall {
+ output: self.get_var_list(0),
+ params: self
+ .get_expr_list(2)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}),
IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
- output: OperandIter::new(&*self.function, op.first_output, op.num_outputs)
- .ssa_vars()
+ output: self.get_ssa_var_list(0),
+ intrinsic: CoreIntrinsic::new(
+ self.function.function().arch(),
+ IntrinsicId(op.intrinsic),
+ )
+ .expect("Valid intrinsic"),
+ params: self
+ .get_expr_list(3)
+ .iter()
+ .map(|expr| expr.lift())
.collect(),
+ }),
+ MemoryIntrinsicSsa(op) => Lifted::MemoryIntrinsicSsa(LiftedMemoryIntrinsicSsa {
+ output: self.lift_operand(op.output),
intrinsic: CoreIntrinsic::new(
self.function.function().arch(),
IntrinsicId(op.intrinsic),
)
.expect("Valid intrinsic"),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ params: self
+ .get_expr_list(3)
+ .iter()
.map(|expr| expr.lift())
.collect(),
+ src_memory: op.src_memory,
}),
+ MemoryIntrinsicOutputSsa(op) => {
+ Lifted::MemoryIntrinsicOutputSsa(LiftedMemoryIntrinsicOutputSsa {
+ dest_memory: op.dest_memory,
+ output: self.get_ssa_var_list(1),
+ })
+ }
CallSsa(op) => Lifted::CallSsa(self.lift_call_ssa(op)),
TailcallSsa(op) => Lifted::TailcallSsa(self.lift_call_ssa(op)),
@@ -853,28 +911,46 @@ impl MediumLevelILInstruction {
TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(self.lift_call_untyped_ssa(op)),
SyscallSsa(op) => Lifted::SyscallSsa(LiftedSyscallSsa {
- output: get_call_output_ssa(&self.function, op.output).collect(),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ output: get_call_output_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
+ params: self
+ .get_expr_list(1)
+ .iter()
.map(|expr| expr.lift())
.collect(),
src_memory: op.src_memory,
}),
SyscallUntypedSsa(op) => Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa {
- output: get_call_output_ssa(&self.function, op.output).collect(),
- params: get_call_params_ssa(&self.function, op.params)
- .map(|param| param.lift())
- .collect(),
+ output: get_call_output_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
+ params: get_call_params_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.params),
+ ))
+ .iter()
+ .map(|param| param.lift())
+ .collect(),
stack: self.lift_operand(op.stack),
}),
CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)),
TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)),
SyscallUntyped(op) => Lifted::SyscallUntyped(LiftedSyscallUntyped {
- output: get_call_output(&self.function, op.output).collect(),
- params: get_call_params(&self.function, op.params)
- .map(|param| param.lift())
- .collect(),
+ output: get_call_output(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
+ params: get_call_params(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.params),
+ ))
+ .iter()
+ .map(|param| param.lift())
+ .collect(),
stack: self.lift_operand(op.stack),
}),
@@ -910,21 +986,24 @@ impl MediumLevelILInstruction {
src: self.lift_operand(op.src),
src_memory: op.src_memory,
}),
- Ret(op) => Lifted::Ret(LiftedRet {
- src: OperandIter::new(&*self.function, op.first_operand, op.num_operands)
- .exprs()
+ Ret(_op) => Lifted::Ret(LiftedRet {
+ src: self
+ .get_expr_list(0)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}),
- SeparateParamList(op) => Lifted::SeparateParamList(LiftedSeparateParamList {
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ SeparateParamList(_op) => Lifted::SeparateParamList(LiftedSeparateParamList {
+ params: self
+ .get_expr_list(0)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}),
- SharedParamSlot(op) => Lifted::SharedParamSlot(LiftedSharedParamSlot {
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ SharedParamSlot(_op) => Lifted::SharedParamSlot(LiftedSharedParamSlot {
+ params: self
+ .get_expr_list(0)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}),
@@ -1413,12 +1492,11 @@ impl MediumLevelILInstruction {
fn lift_call(&self, op: Call) -> LiftedCall {
LiftedCall {
- output: OperandIter::new(&*self.function, op.first_output, op.num_outputs)
- .vars()
- .collect(),
+ output: self.get_var_list(0),
dest: self.lift_operand(op.dest),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ params: self
+ .get_expr_list(3)
+ .iter()
.map(|expr| expr.lift())
.collect(),
}
@@ -1426,21 +1504,32 @@ impl MediumLevelILInstruction {
fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped {
LiftedCallUntyped {
- output: get_call_output(&self.function, op.output).collect(),
+ output: get_call_output(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
dest: self.lift_operand(op.dest),
- params: get_call_params(&self.function, op.params)
- .map(|expr| expr.lift())
- .collect(),
+ params: get_call_params(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.params),
+ ))
+ .iter()
+ .map(|expr| expr.lift())
+ .collect(),
stack: self.lift_operand(op.stack),
}
}
fn lift_call_ssa(&self, op: CallSsa) -> LiftedCallSsa {
LiftedCallSsa {
- output: get_call_output_ssa(&self.function, op.output).collect(),
+ output: get_call_output_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
dest: self.lift_operand(op.dest),
- params: OperandIter::new(&*self.function, op.first_param, op.num_params)
- .exprs()
+ params: self
+ .get_expr_list(2)
+ .iter()
.map(|expr| expr.lift())
.collect(),
src_memory: op.src_memory,
@@ -1449,11 +1538,18 @@ impl MediumLevelILInstruction {
fn lift_call_untyped_ssa(&self, op: CallUntypedSsa) -> LiftedCallUntypedSsa {
LiftedCallUntypedSsa {
- output: get_call_output_ssa(&self.function, op.output).collect(),
+ output: get_call_output_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.output),
+ )),
dest: self.lift_operand(op.dest),
- params: get_call_params_ssa(&self.function, op.params)
- .map(|param| param.lift())
- .collect(),
+ params: get_call_params_ssa(&MediumLevelILInstruction::new(
+ self.function.clone(),
+ MediumLevelInstructionIndex(op.params),
+ ))
+ .iter()
+ .map(|param| param.lift())
+ .collect(),
stack: self.lift_operand(op.stack),
}
}
@@ -1636,10 +1732,6 @@ fn get_float(value: u64, size: usize) -> f64 {
}
}
-fn get_raw_operation(function: &MediumLevelILFunction, idx: usize) -> BNMediumLevelILInstruction {
- unsafe { BNGetMediumLevelILByIndex(function.handle, idx) }
-}
-
fn get_var(id: u64) -> Variable {
Variable::from_identifier(id)
}
@@ -1648,37 +1740,32 @@ fn get_var_ssa(id: u64, version: usize) -> SSAVariable {
SSAVariable::new(get_var(id), version)
}
-fn get_call_output(function: &MediumLevelILFunction, idx: usize) -> impl Iterator<Item = Variable> {
- let op = get_raw_operation(function, idx);
- assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT);
- OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).vars()
+fn get_call_output(instr: &MediumLevelILInstruction) -> Vec<Variable> {
+ match instr.kind {
+ MediumLevelILInstructionKind::CallOutput(_op) => instr.get_var_list(0),
+ _ => vec![],
+ }
}
-fn get_call_params(
- function: &MediumLevelILFunction,
- idx: usize,
-) -> impl Iterator<Item = MediumLevelILInstruction> {
- let op = get_raw_operation(function, idx);
- assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM);
- OperandIter::new(function, op.operands[1] as usize, op.operands[0] as usize).exprs()
+fn get_call_params(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> {
+ match instr.kind {
+ MediumLevelILInstructionKind::CallParam(_op) => instr.get_expr_list(0),
+ _ => vec![],
+ }
}
-fn get_call_output_ssa(
- function: &MediumLevelILFunction,
- idx: usize,
-) -> impl Iterator<Item = SSAVariable> {
- let op = get_raw_operation(function, idx);
- assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_OUTPUT_SSA);
- OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).ssa_vars()
+fn get_call_output_ssa(instr: &MediumLevelILInstruction) -> Vec<SSAVariable> {
+ match instr.kind {
+ MediumLevelILInstructionKind::CallOutputSsa(_op) => instr.get_ssa_var_list(1),
+ _ => vec![],
+ }
}
-fn get_call_params_ssa(
- function: &MediumLevelILFunction,
- idx: usize,
-) -> impl Iterator<Item = MediumLevelILInstruction> {
- let op = get_raw_operation(function, idx);
- assert_eq!(op.operation, BNMediumLevelILOperation::MLIL_CALL_PARAM_SSA);
- OperandIter::new(function, op.operands[2] as usize, op.operands[1] as usize).exprs()
+fn get_call_params_ssa(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> {
+ match instr.kind {
+ MediumLevelILInstructionKind::CallParamSsa(_op) => instr.get_expr_list(1),
+ _ => vec![],
+ }
}
/// Conditional branching instruction and an expected conditional result
diff --git a/rust/src/operand_iter.rs b/rust/src/operand_iter.rs
deleted file mode 100644
index fcbf5fad..00000000
--- a/rust/src/operand_iter.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-use binaryninjacore_sys::BNGetHighLevelILByIndex;
-use binaryninjacore_sys::BNGetMediumLevelILByIndex;
-use binaryninjacore_sys::BNHighLevelILOperation;
-use binaryninjacore_sys::BNMediumLevelILOperation;
-
-use crate::high_level_il::{
- HighLevelILFunction, HighLevelILInstruction, HighLevelInstructionIndex,
-};
-use crate::medium_level_il::{
- MediumLevelILFunction, MediumLevelILInstruction, MediumLevelInstructionIndex,
-};
-use crate::rc::{Ref, RefCountable};
-use crate::variable::{SSAVariable, Variable};
-
-// TODO: This code needs to go away IMO, we have the facilities to do this for each IL already!
-
-pub trait ILFunction {
- type Instruction;
- type InstructionIndex: From<u64>;
-
- // TODO Actually this is il expression from index!
- fn il_instruction_from_index(&self, instr_index: Self::InstructionIndex) -> Self::Instruction;
- fn operands_from_index(&self, instr_index: Self::InstructionIndex) -> [u64; 5];
-}
-
-impl ILFunction for MediumLevelILFunction {
- type Instruction = MediumLevelILInstruction;
- type InstructionIndex = MediumLevelInstructionIndex;
-
- fn il_instruction_from_index(&self, instr_index: Self::InstructionIndex) -> Self::Instruction {
- self.instruction_from_expr_index(instr_index).unwrap()
- }
-
- fn operands_from_index(&self, instr_index: Self::InstructionIndex) -> [u64; 5] {
- // TODO: WTF?!?!?!
- let node = unsafe { BNGetMediumLevelILByIndex(self.handle, instr_index.0) };
- assert_eq!(node.operation, BNMediumLevelILOperation::MLIL_UNDEF);
- node.operands
- }
-}
-
-impl ILFunction for HighLevelILFunction {
- type Instruction = HighLevelILInstruction;
- type InstructionIndex = HighLevelInstructionIndex;
-
- fn il_instruction_from_index(&self, instr_index: Self::InstructionIndex) -> Self::Instruction {
- self.instruction_from_expr_index(instr_index).unwrap()
- }
-
- fn operands_from_index(&self, instr_index: Self::InstructionIndex) -> [u64; 5] {
- let node = unsafe { BNGetHighLevelILByIndex(self.handle, instr_index.0, self.full_ast) };
- assert_eq!(node.operation, BNHighLevelILOperation::HLIL_UNDEF);
- node.operands
- }
-}
-
-pub struct OperandIter<F: ILFunction + RefCountable> {
- function: Ref<F>,
- remaining: usize,
- next_iter_idx: Option<usize>,
- current_iter: OperandIterInner,
-}
-
-impl<F: ILFunction + RefCountable> OperandIter<F> {
- pub(crate) fn new(function: &F, idx: usize, number: usize) -> Self {
- // Zero-length lists immediately finish iteration
- let next_iter_idx = if number > 0 { Some(idx) } else { None };
- Self {
- function: function.to_owned(),
- remaining: number,
- next_iter_idx,
- current_iter: OperandIterInner::empty(),
- }
- }
-
- pub fn pairs(self) -> OperandPairIter<F> {
- assert_eq!(self.len() % 2, 0);
- OperandPairIter(self)
- }
-
- pub fn exprs(self) -> OperandExprIter<F> {
- OperandExprIter(self)
- }
-
- pub fn vars(self) -> OperandVarIter<F> {
- OperandVarIter(self)
- }
-
- pub fn ssa_vars(self) -> OperandSSAVarIter<F> {
- OperandSSAVarIter(self.pairs())
- }
-}
-
-impl<F: ILFunction + RefCountable> Iterator for OperandIter<F> {
- type Item = u64;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(item) = self.current_iter.next() {
- self.remaining -= 1;
- Some(item)
- } else {
- // Will short-circuit and return `None` once iter is exhausted
- let iter_idx = self.next_iter_idx?;
- let iter_idx = F::InstructionIndex::from(iter_idx as u64);
- let operands = self.function.operands_from_index(iter_idx);
-
- let next = if self.remaining > 4 {
- self.next_iter_idx = Some(operands[4] as usize);
- &operands[..4]
- } else {
- self.next_iter_idx = None;
- &operands[..self.remaining]
- };
-
- self.current_iter = OperandIterInner::from_slice(next);
- self.next()
- }
- }
-}
-
-impl<F: ILFunction + RefCountable> ExactSizeIterator for OperandIter<F> {
- fn len(&self) -> usize {
- self.remaining + self.current_iter.len()
- }
-}
-
-struct OperandIterInner {
- arr: [u64; 4],
- idx: usize,
-}
-
-impl OperandIterInner {
- fn from_slice(slice: &[u64]) -> Self {
- assert!(slice.len() <= 4);
- let idx = 4 - slice.len();
- let mut arr = [0; 4];
- arr[idx..].copy_from_slice(slice);
- Self { arr, idx }
- }
-
- fn empty() -> Self {
- Self {
- arr: [0; 4],
- idx: 4,
- }
- }
-}
-
-impl Iterator for OperandIterInner {
- type Item = u64;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.idx < 4 {
- let val = self.arr[self.idx];
- self.idx += 1;
- Some(val)
- } else {
- None
- }
- }
-}
-
-impl ExactSizeIterator for OperandIterInner {
- fn len(&self) -> usize {
- 4 - self.idx
- }
-}
-
-pub struct OperandPairIter<F: ILFunction + RefCountable>(OperandIter<F>);
-
-impl<F: ILFunction + RefCountable> Iterator for OperandPairIter<F> {
- type Item = (u64, u64);
-
- fn next(&mut self) -> Option<Self::Item> {
- let first = self.0.next()?;
- let second = self.0.next()?;
- Some((first, second))
- }
-}
-impl<F: ILFunction + RefCountable> ExactSizeIterator for OperandPairIter<F> {
- fn len(&self) -> usize {
- self.0.len() / 2
- }
-}
-
-pub struct OperandExprIter<F: ILFunction + RefCountable>(OperandIter<F>);
-
-impl<F: ILFunction + RefCountable> Iterator for OperandExprIter<F> {
- type Item = F::Instruction;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0
- .next()
- .map(F::InstructionIndex::from)
- .map(|idx| self.0.function.il_instruction_from_index(idx))
- }
-}
-
-impl<F: ILFunction + RefCountable> ExactSizeIterator for OperandExprIter<F> {
- fn len(&self) -> usize {
- self.0.len()
- }
-}
-
-pub struct OperandVarIter<F: ILFunction + RefCountable>(OperandIter<F>);
-
-impl<F: ILFunction + RefCountable> Iterator for OperandVarIter<F> {
- type Item = Variable;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next().map(Variable::from_identifier)
- }
-}
-impl<F: ILFunction + RefCountable> ExactSizeIterator for OperandVarIter<F> {
- fn len(&self) -> usize {
- self.0.len()
- }
-}
-
-pub struct OperandSSAVarIter<F: ILFunction + RefCountable>(OperandPairIter<F>);
-
-impl<F: ILFunction + RefCountable> Iterator for OperandSSAVarIter<F> {
- type Item = SSAVariable;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next().map(|(id, version)| {
- let var = Variable::from_identifier(id);
- SSAVariable::new(var, version as _)
- })
- }
-}
-
-impl<F: ILFunction + RefCountable> ExactSizeIterator for OperandSSAVarIter<F> {
- fn len(&self) -> usize {
- self.0.len()
- }
-}
diff --git a/rust/tests/medium_level_il.rs b/rust/tests/medium_level_il.rs
index 7f73cde3..b8c1c108 100644
--- a/rust/tests/medium_level_il.rs
+++ b/rust/tests/medium_level_il.rs
@@ -1,6 +1,8 @@
use binaryninja::binary_view::BinaryViewExt;
use binaryninja::headless::Session;
-use binaryninja::medium_level_il::{MediumLevelILInstructionKind, MediumLevelILLiftedInstructionKind, MediumLevelInstructionIndex};
+use binaryninja::medium_level_il::{
+ MediumLevelILInstructionKind, MediumLevelILLiftedInstructionKind, MediumLevelInstructionIndex,
+};
use std::path::PathBuf;
#[test]