1use super::lift::*;
2use super::operation::*;
3use super::{MediumLevelILBlock, MediumLevelILFunction};
4use crate::architecture::{CoreIntrinsic, FlagId, IntrinsicId, RegisterId};
5use crate::basic_block::BasicBlock;
6use crate::confidence::Conf;
7use crate::disassembly::InstructionTextToken;
8use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
9use crate::types::Type;
10use crate::variable::{ConstantData, PossibleValueSet, RegisterValue, SSAVariable, Variable};
11use crate::{DataFlowQueryOption, ILBranchDependence};
12use binaryninjacore_sys::*;
13use std::collections::BTreeMap;
14use std::fmt;
15use std::fmt::{Debug, Display, Formatter};
16
17#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct MediumLevelInstructionIndex(pub usize);
19
20impl MediumLevelInstructionIndex {
21 pub fn next(&self) -> Self {
22 Self(self.0 + 1)
23 }
24}
25
26impl From<usize> for MediumLevelInstructionIndex {
27 fn from(index: usize) -> Self {
28 Self(index)
29 }
30}
31
32impl From<u64> for MediumLevelInstructionIndex {
33 fn from(index: u64) -> Self {
34 Self(index as usize)
35 }
36}
37
38impl Display for MediumLevelInstructionIndex {
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 f.write_fmt(format_args!("{}", self.0))
41 }
42}
43
44#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
45pub struct MediumLevelExpressionIndex(pub usize);
46
47impl MediumLevelExpressionIndex {
48 pub fn next(&self) -> Self {
49 Self(self.0 + 1)
50 }
51}
52
53impl From<usize> for MediumLevelExpressionIndex {
54 fn from(index: usize) -> Self {
55 Self(index)
56 }
57}
58
59impl From<u64> for MediumLevelExpressionIndex {
60 fn from(index: u64) -> Self {
61 Self(index as usize)
62 }
63}
64
65impl Display for MediumLevelExpressionIndex {
66 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
67 f.write_fmt(format_args!("{}", self.0))
68 }
69}
70
71#[derive(Clone)]
72pub struct MediumLevelILInstruction {
73 pub function: Ref<MediumLevelILFunction>,
74 pub address: u64,
75 pub instr_index: MediumLevelInstructionIndex,
76 pub expr_index: MediumLevelExpressionIndex,
77 pub size: usize,
78 pub kind: MediumLevelILInstructionKind,
79}
80
81impl MediumLevelILInstruction {
82 pub(crate) fn from_instr_index(
83 function: Ref<MediumLevelILFunction>,
84 instr_index: MediumLevelInstructionIndex,
85 ) -> Self {
86 let expr_index_raw =
88 unsafe { BNGetMediumLevelILIndexForInstruction(function.handle, instr_index.0) };
89 Self::new(
90 function,
91 instr_index,
92 MediumLevelExpressionIndex(expr_index_raw),
93 )
94 }
95
96 pub(crate) fn from_expr_index(
97 function: Ref<MediumLevelILFunction>,
98 expr_index: MediumLevelExpressionIndex,
99 ) -> Self {
100 let instr_index_raw =
102 unsafe { BNGetMediumLevelILInstructionForExpr(function.handle, expr_index.0) };
103 Self::new(
104 function,
105 MediumLevelInstructionIndex(instr_index_raw),
106 expr_index,
107 )
108 }
109
110 pub(crate) fn new(
111 function: Ref<MediumLevelILFunction>,
112 instr_index: MediumLevelInstructionIndex,
113 expr_index: MediumLevelExpressionIndex,
114 ) -> Self {
115 let op = unsafe { BNGetMediumLevelILByIndex(function.handle, expr_index.0) };
117 use BNMediumLevelILOperation::*;
118 use MediumLevelILInstructionKind as Op;
119 let kind = match op.operation {
120 MLIL_NOP => Op::Nop,
121 MLIL_NORET => Op::Noret,
122 MLIL_BP => Op::Bp,
123 MLIL_UNDEF => Op::Undef,
124 MLIL_ASSERT => Op::Assert(Assert {
125 src: get_var(op.operands[0]),
126 constraint_index: op.operands[1] as usize,
127 }),
128 MLIL_ASSERT_SSA => Op::AssertSsa(AssertSsa {
129 src: get_var_ssa(op.operands[0], op.operands[1] as usize),
130 constraint_index: op.operands[2] as usize,
131 }),
132 MLIL_FORCE_VER => Op::ForceVer(ForceVer {
133 dest: get_var(op.operands[0]),
134 src: get_var(op.operands[1]),
135 reason: unsafe {
136 std::mem::transmute::<u8, ForceVersionReason>(op.operands[2] as u8)
137 },
138 }),
139 MLIL_FORCE_VER_SSA => Op::ForceVerSsa(ForceVerSsa {
140 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
141 src: get_var_ssa(op.operands[2], op.operands[3] as usize),
142 reason: unsafe {
143 std::mem::transmute::<u8, ForceVersionReason>(op.operands[4] as u8)
144 },
145 }),
146 MLIL_UNIMPL => Op::Unimpl,
147 MLIL_IF => Op::If(MediumLevelILOperationIf {
148 condition: MediumLevelExpressionIndex::from(op.operands[0]),
149 dest_true: MediumLevelInstructionIndex(op.operands[1] as usize),
150 dest_false: MediumLevelInstructionIndex(op.operands[2] as usize),
151 }),
152 MLIL_FLOAT_CONST => Op::FloatConst(FloatConst {
153 constant: get_float(op.operands[0], op.size),
154 }),
155 MLIL_CONST => Op::Const(Constant {
156 constant: op.operands[0],
157 }),
158 MLIL_CONST_PTR => Op::ConstPtr(Constant {
159 constant: op.operands[0],
160 }),
161 MLIL_IMPORT => Op::Import(Constant {
162 constant: op.operands[0],
163 }),
164 MLIL_EXTERN_PTR => Op::ExternPtr(ExternPtr {
165 constant: op.operands[0],
166 offset: op.operands[1],
167 }),
168 MLIL_CONST_DATA => Op::ConstData(ConstData {
169 constant_data_kind: op.operands[0] as u32,
170 constant_data_value: op.operands[1] as i64,
171 size: op.size,
172 }),
173 MLIL_JUMP => Op::Jump(Jump {
174 dest: MediumLevelExpressionIndex::from(op.operands[0]),
175 }),
176 MLIL_RET_HINT => Op::RetHint(Jump {
177 dest: MediumLevelExpressionIndex::from(op.operands[0]),
178 }),
179 MLIL_STORE_SSA => Op::StoreSsa(StoreSsa {
180 dest: MediumLevelExpressionIndex::from(op.operands[0]),
181 dest_memory: op.operands[1],
182 src_memory: op.operands[2],
183 src: MediumLevelExpressionIndex::from(op.operands[3]),
184 }),
185 MLIL_STORE_STRUCT_SSA => Op::StoreStructSsa(StoreStructSsa {
186 dest: MediumLevelExpressionIndex::from(op.operands[0]),
187 offset: op.operands[1],
188 dest_memory: op.operands[2],
189 src_memory: op.operands[3],
190 src: MediumLevelExpressionIndex::from(op.operands[4]),
191 }),
192 MLIL_STORE_STRUCT => Op::StoreStruct(StoreStruct {
193 dest: MediumLevelExpressionIndex::from(op.operands[0]),
194 offset: op.operands[1],
195 src: MediumLevelExpressionIndex::from(op.operands[2]),
196 }),
197 MLIL_STORE => Op::Store(Store {
198 dest: MediumLevelExpressionIndex::from(op.operands[0]),
199 src: MediumLevelExpressionIndex::from(op.operands[1]),
200 }),
201 MLIL_JUMP_TO => Op::JumpTo(JumpTo {
202 dest: MediumLevelExpressionIndex::from(op.operands[0]),
203 num_operands: op.operands[1] as usize,
204 first_operand: op.operands[2] as usize,
205 }),
206 MLIL_GOTO => Op::Goto(Goto {
207 dest: MediumLevelInstructionIndex(op.operands[0] as usize),
208 }),
209 MLIL_FREE_VAR_SLOT => Op::FreeVarSlot(FreeVarSlot {
210 dest: get_var(op.operands[0]),
211 }),
212 MLIL_SET_VAR_FIELD => Op::SetVarField(SetVarField {
213 dest: get_var(op.operands[0]),
214 offset: op.operands[1],
215 src: MediumLevelExpressionIndex::from(op.operands[2]),
216 }),
217 MLIL_SET_VAR => Op::SetVar(SetVar {
218 dest: get_var(op.operands[0]),
219 src: MediumLevelExpressionIndex::from(op.operands[1]),
220 }),
221 MLIL_FREE_VAR_SLOT_SSA => Op::FreeVarSlotSsa(FreeVarSlotSsa {
222 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
223 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
224 }),
225 MLIL_SET_VAR_SSA_FIELD => Op::SetVarSsaField(SetVarSsaField {
226 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
227 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
228 offset: op.operands[3],
229 src: MediumLevelExpressionIndex::from(op.operands[4]),
230 }),
231 MLIL_SET_VAR_ALIASED_FIELD => Op::SetVarAliasedField(SetVarSsaField {
232 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
233 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
234 offset: op.operands[3],
235 src: MediumLevelExpressionIndex::from(op.operands[4]),
236 }),
237 MLIL_SET_VAR_ALIASED => Op::SetVarAliased(SetVarAliased {
238 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
239 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
240 src: MediumLevelExpressionIndex::from(op.operands[3]),
241 }),
242 MLIL_SET_VAR_SSA => Op::SetVarSsa(SetVarSsa {
243 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
244 src: MediumLevelExpressionIndex::from(op.operands[2]),
245 }),
246 MLIL_VAR_PHI => Op::VarPhi(VarPhi {
247 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
248 num_operands: op.operands[2] as usize,
249 first_operand: op.operands[3] as usize,
250 }),
251 MLIL_MEM_PHI => Op::MemPhi(MemPhi {
252 dest_memory: op.operands[0],
253 num_operands: op.operands[1] as usize,
254 first_operand: op.operands[2] as usize,
255 }),
256 MLIL_VAR_SPLIT => Op::VarSplit(VarSplit {
257 high: get_var(op.operands[0]),
258 low: get_var(op.operands[1]),
259 }),
260 MLIL_SET_VAR_SPLIT => Op::SetVarSplit(SetVarSplit {
261 high: get_var(op.operands[0]),
262 low: get_var(op.operands[1]),
263 src: MediumLevelExpressionIndex::from(op.operands[2]),
264 }),
265 MLIL_VAR_SPLIT_SSA => Op::VarSplitSsa(VarSplitSsa {
266 high: get_var_ssa(op.operands[0], op.operands[1] as usize),
267 low: get_var_ssa(op.operands[2], op.operands[3] as usize),
268 }),
269 MLIL_SET_VAR_SPLIT_SSA => Op::SetVarSplitSsa(SetVarSplitSsa {
270 high: get_var_ssa(op.operands[0], op.operands[1] as usize),
271 low: get_var_ssa(op.operands[2], op.operands[3] as usize),
272 src: MediumLevelExpressionIndex::from(op.operands[4]),
273 }),
274 MLIL_ADD => Op::Add(BinaryOp {
275 left: MediumLevelExpressionIndex::from(op.operands[0]),
276 right: MediumLevelExpressionIndex::from(op.operands[1]),
277 }),
278 MLIL_SUB => Op::Sub(BinaryOp {
279 left: MediumLevelExpressionIndex::from(op.operands[0]),
280 right: MediumLevelExpressionIndex::from(op.operands[1]),
281 }),
282 MLIL_AND => Op::And(BinaryOp {
283 left: MediumLevelExpressionIndex::from(op.operands[0]),
284 right: MediumLevelExpressionIndex::from(op.operands[1]),
285 }),
286 MLIL_OR => Op::Or(BinaryOp {
287 left: MediumLevelExpressionIndex::from(op.operands[0]),
288 right: MediumLevelExpressionIndex::from(op.operands[1]),
289 }),
290 MLIL_XOR => Op::Xor(BinaryOp {
291 left: MediumLevelExpressionIndex::from(op.operands[0]),
292 right: MediumLevelExpressionIndex::from(op.operands[1]),
293 }),
294 MLIL_LSL => Op::Lsl(BinaryOp {
295 left: MediumLevelExpressionIndex::from(op.operands[0]),
296 right: MediumLevelExpressionIndex::from(op.operands[1]),
297 }),
298 MLIL_LSR => Op::Lsr(BinaryOp {
299 left: MediumLevelExpressionIndex::from(op.operands[0]),
300 right: MediumLevelExpressionIndex::from(op.operands[1]),
301 }),
302 MLIL_ASR => Op::Asr(BinaryOp {
303 left: MediumLevelExpressionIndex::from(op.operands[0]),
304 right: MediumLevelExpressionIndex::from(op.operands[1]),
305 }),
306 MLIL_ROL => Op::Rol(BinaryOp {
307 left: MediumLevelExpressionIndex::from(op.operands[0]),
308 right: MediumLevelExpressionIndex::from(op.operands[1]),
309 }),
310 MLIL_ROR => Op::Ror(BinaryOp {
311 left: MediumLevelExpressionIndex::from(op.operands[0]),
312 right: MediumLevelExpressionIndex::from(op.operands[1]),
313 }),
314 MLIL_MUL => Op::Mul(BinaryOp {
315 left: MediumLevelExpressionIndex::from(op.operands[0]),
316 right: MediumLevelExpressionIndex::from(op.operands[1]),
317 }),
318 MLIL_MULU_DP => Op::MuluDp(BinaryOp {
319 left: MediumLevelExpressionIndex::from(op.operands[0]),
320 right: MediumLevelExpressionIndex::from(op.operands[1]),
321 }),
322 MLIL_MULS_DP => Op::MulsDp(BinaryOp {
323 left: MediumLevelExpressionIndex::from(op.operands[0]),
324 right: MediumLevelExpressionIndex::from(op.operands[1]),
325 }),
326 MLIL_DIVU => Op::Divu(BinaryOp {
327 left: MediumLevelExpressionIndex::from(op.operands[0]),
328 right: MediumLevelExpressionIndex::from(op.operands[1]),
329 }),
330 MLIL_DIVU_DP => Op::DivuDp(BinaryOp {
331 left: MediumLevelExpressionIndex::from(op.operands[0]),
332 right: MediumLevelExpressionIndex::from(op.operands[1]),
333 }),
334 MLIL_DIVS => Op::Divs(BinaryOp {
335 left: MediumLevelExpressionIndex::from(op.operands[0]),
336 right: MediumLevelExpressionIndex::from(op.operands[1]),
337 }),
338 MLIL_DIVS_DP => Op::DivsDp(BinaryOp {
339 left: MediumLevelExpressionIndex::from(op.operands[0]),
340 right: MediumLevelExpressionIndex::from(op.operands[1]),
341 }),
342 MLIL_MODU => Op::Modu(BinaryOp {
343 left: MediumLevelExpressionIndex::from(op.operands[0]),
344 right: MediumLevelExpressionIndex::from(op.operands[1]),
345 }),
346 MLIL_MODU_DP => Op::ModuDp(BinaryOp {
347 left: MediumLevelExpressionIndex::from(op.operands[0]),
348 right: MediumLevelExpressionIndex::from(op.operands[1]),
349 }),
350 MLIL_MODS => Op::Mods(BinaryOp {
351 left: MediumLevelExpressionIndex::from(op.operands[0]),
352 right: MediumLevelExpressionIndex::from(op.operands[1]),
353 }),
354 MLIL_MODS_DP => Op::ModsDp(BinaryOp {
355 left: MediumLevelExpressionIndex::from(op.operands[0]),
356 right: MediumLevelExpressionIndex::from(op.operands[1]),
357 }),
358 MLIL_MINS => Op::MinSigned(BinaryOp {
359 left: MediumLevelExpressionIndex::from(op.operands[0]),
360 right: MediumLevelExpressionIndex::from(op.operands[1]),
361 }),
362 MLIL_MAXS => Op::MaxSigned(BinaryOp {
363 left: MediumLevelExpressionIndex::from(op.operands[0]),
364 right: MediumLevelExpressionIndex::from(op.operands[1]),
365 }),
366 MLIL_MINU => Op::MinUnsigned(BinaryOp {
367 left: MediumLevelExpressionIndex::from(op.operands[0]),
368 right: MediumLevelExpressionIndex::from(op.operands[1]),
369 }),
370 MLIL_MAXU => Op::MaxUnsigned(BinaryOp {
371 left: MediumLevelExpressionIndex::from(op.operands[0]),
372 right: MediumLevelExpressionIndex::from(op.operands[1]),
373 }),
374 MLIL_CMP_E => Op::CmpE(BinaryOp {
375 left: MediumLevelExpressionIndex::from(op.operands[0]),
376 right: MediumLevelExpressionIndex::from(op.operands[1]),
377 }),
378 MLIL_CMP_NE => Op::CmpNe(BinaryOp {
379 left: MediumLevelExpressionIndex::from(op.operands[0]),
380 right: MediumLevelExpressionIndex::from(op.operands[1]),
381 }),
382 MLIL_CMP_SLT => Op::CmpSlt(BinaryOp {
383 left: MediumLevelExpressionIndex::from(op.operands[0]),
384 right: MediumLevelExpressionIndex::from(op.operands[1]),
385 }),
386 MLIL_CMP_ULT => Op::CmpUlt(BinaryOp {
387 left: MediumLevelExpressionIndex::from(op.operands[0]),
388 right: MediumLevelExpressionIndex::from(op.operands[1]),
389 }),
390 MLIL_CMP_SLE => Op::CmpSle(BinaryOp {
391 left: MediumLevelExpressionIndex::from(op.operands[0]),
392 right: MediumLevelExpressionIndex::from(op.operands[1]),
393 }),
394 MLIL_CMP_ULE => Op::CmpUle(BinaryOp {
395 left: MediumLevelExpressionIndex::from(op.operands[0]),
396 right: MediumLevelExpressionIndex::from(op.operands[1]),
397 }),
398 MLIL_CMP_SGE => Op::CmpSge(BinaryOp {
399 left: MediumLevelExpressionIndex::from(op.operands[0]),
400 right: MediumLevelExpressionIndex::from(op.operands[1]),
401 }),
402 MLIL_CMP_UGE => Op::CmpUge(BinaryOp {
403 left: MediumLevelExpressionIndex::from(op.operands[0]),
404 right: MediumLevelExpressionIndex::from(op.operands[1]),
405 }),
406 MLIL_CMP_SGT => Op::CmpSgt(BinaryOp {
407 left: MediumLevelExpressionIndex::from(op.operands[0]),
408 right: MediumLevelExpressionIndex::from(op.operands[1]),
409 }),
410 MLIL_CMP_UGT => Op::CmpUgt(BinaryOp {
411 left: MediumLevelExpressionIndex::from(op.operands[0]),
412 right: MediumLevelExpressionIndex::from(op.operands[1]),
413 }),
414 MLIL_TEST_BIT => Op::TestBit(BinaryOp {
415 left: MediumLevelExpressionIndex::from(op.operands[0]),
416 right: MediumLevelExpressionIndex::from(op.operands[1]),
417 }),
418 MLIL_ADD_OVERFLOW => Op::AddOverflow(BinaryOp {
419 left: MediumLevelExpressionIndex::from(op.operands[0]),
420 right: MediumLevelExpressionIndex::from(op.operands[1]),
421 }),
422 MLIL_FCMP_E => Op::FcmpE(BinaryOp {
423 left: MediumLevelExpressionIndex::from(op.operands[0]),
424 right: MediumLevelExpressionIndex::from(op.operands[1]),
425 }),
426 MLIL_FCMP_NE => Op::FcmpNe(BinaryOp {
427 left: MediumLevelExpressionIndex::from(op.operands[0]),
428 right: MediumLevelExpressionIndex::from(op.operands[1]),
429 }),
430 MLIL_FCMP_LT => Op::FcmpLt(BinaryOp {
431 left: MediumLevelExpressionIndex::from(op.operands[0]),
432 right: MediumLevelExpressionIndex::from(op.operands[1]),
433 }),
434 MLIL_FCMP_LE => Op::FcmpLe(BinaryOp {
435 left: MediumLevelExpressionIndex::from(op.operands[0]),
436 right: MediumLevelExpressionIndex::from(op.operands[1]),
437 }),
438 MLIL_FCMP_GE => Op::FcmpGe(BinaryOp {
439 left: MediumLevelExpressionIndex::from(op.operands[0]),
440 right: MediumLevelExpressionIndex::from(op.operands[1]),
441 }),
442 MLIL_FCMP_GT => Op::FcmpGt(BinaryOp {
443 left: MediumLevelExpressionIndex::from(op.operands[0]),
444 right: MediumLevelExpressionIndex::from(op.operands[1]),
445 }),
446 MLIL_FCMP_O => Op::FcmpO(BinaryOp {
447 left: MediumLevelExpressionIndex::from(op.operands[0]),
448 right: MediumLevelExpressionIndex::from(op.operands[1]),
449 }),
450 MLIL_FCMP_UO => Op::FcmpUo(BinaryOp {
451 left: MediumLevelExpressionIndex::from(op.operands[0]),
452 right: MediumLevelExpressionIndex::from(op.operands[1]),
453 }),
454 MLIL_FADD => Op::Fadd(BinaryOp {
455 left: MediumLevelExpressionIndex::from(op.operands[0]),
456 right: MediumLevelExpressionIndex::from(op.operands[1]),
457 }),
458 MLIL_FSUB => Op::Fsub(BinaryOp {
459 left: MediumLevelExpressionIndex::from(op.operands[0]),
460 right: MediumLevelExpressionIndex::from(op.operands[1]),
461 }),
462 MLIL_FMUL => Op::Fmul(BinaryOp {
463 left: MediumLevelExpressionIndex::from(op.operands[0]),
464 right: MediumLevelExpressionIndex::from(op.operands[1]),
465 }),
466 MLIL_FDIV => Op::Fdiv(BinaryOp {
467 left: MediumLevelExpressionIndex::from(op.operands[0]),
468 right: MediumLevelExpressionIndex::from(op.operands[1]),
469 }),
470 MLIL_ADC => Op::Adc(BinaryOpCarry {
471 left: MediumLevelExpressionIndex::from(op.operands[0]),
472 right: MediumLevelExpressionIndex::from(op.operands[1]),
473 carry: MediumLevelExpressionIndex::from(op.operands[2]),
474 }),
475 MLIL_SBB => Op::Sbb(BinaryOpCarry {
476 left: MediumLevelExpressionIndex::from(op.operands[0]),
477 right: MediumLevelExpressionIndex::from(op.operands[1]),
478 carry: MediumLevelExpressionIndex::from(op.operands[2]),
479 }),
480 MLIL_RLC => Op::Rlc(BinaryOpCarry {
481 left: MediumLevelExpressionIndex::from(op.operands[0]),
482 right: MediumLevelExpressionIndex::from(op.operands[1]),
483 carry: MediumLevelExpressionIndex::from(op.operands[2]),
484 }),
485 MLIL_RRC => Op::Rrc(BinaryOpCarry {
486 left: MediumLevelExpressionIndex::from(op.operands[0]),
487 right: MediumLevelExpressionIndex::from(op.operands[1]),
488 carry: MediumLevelExpressionIndex::from(op.operands[2]),
489 }),
490 MLIL_CALL => Op::Call(Call {
491 num_outputs: op.operands[0] as usize,
492 first_output: op.operands[1] as usize,
493 dest: MediumLevelExpressionIndex::from(op.operands[2]),
494 num_params: op.operands[3] as usize,
495 first_param: op.operands[4] as usize,
496 }),
497 MLIL_CALL_PARAM => Op::CallParam(CallParam {
498 num_params: op.operands[0] as usize,
499 first_param: op.operands[1] as usize,
500 }),
501 MLIL_CALL_OUTPUT_SSA => Op::CallOutputSsa(CallOutputSsa {
502 dest_memory: op.operands[0],
503 num_outputs: op.operands[1] as usize,
504 first_output: op.operands[2] as usize,
505 }),
506 MLIL_CALL_PARAM_SSA => Op::CallParamSsa(CallParamSsa {
507 src_memory: op.operands[0],
508 num_params: op.operands[1] as usize,
509 first_param: op.operands[2] as usize,
510 }),
511 MLIL_TAILCALL => Op::Tailcall(Call {
512 num_outputs: op.operands[0] as usize,
513 first_output: op.operands[1] as usize,
514 dest: MediumLevelExpressionIndex::from(op.operands[2]),
515 num_params: op.operands[3] as usize,
516 first_param: op.operands[4] as usize,
517 }),
518 MLIL_SYSCALL => Op::Syscall(Syscall {
519 num_outputs: op.operands[0] as usize,
520 first_output: op.operands[1] as usize,
521 num_params: op.operands[2] as usize,
522 first_param: op.operands[3] as usize,
523 }),
524 MLIL_INTRINSIC => Op::Intrinsic(Intrinsic {
525 num_outputs: op.operands[0] as usize,
526 first_output: op.operands[1] as usize,
527 intrinsic: op.operands[2] as u32,
528 num_params: op.operands[3] as usize,
529 first_param: op.operands[4] as usize,
530 }),
531 MLIL_INTRINSIC_SSA => Op::IntrinsicSsa(IntrinsicSsa {
532 num_outputs: op.operands[0] as usize,
533 first_output: op.operands[1] as usize,
534 intrinsic: op.operands[2] as u32,
535 num_params: op.operands[3] as usize,
536 first_param: op.operands[4] as usize,
537 }),
538 MLIL_MEMORY_INTRINSIC_SSA => Op::MemoryIntrinsicSsa(MemoryIntrinsicSsa {
539 output: MediumLevelExpressionIndex::from(op.operands[0]),
540 intrinsic: op.operands[1] as u32,
541 num_params: op.operands[2] as usize,
542 first_param: op.operands[3] as usize,
543 src_memory: op.operands[4],
544 }),
545 MLIL_MEMORY_INTRINSIC_OUTPUT_SSA => {
546 Op::MemoryIntrinsicOutputSsa(MemoryIntrinsicOutputSsa {
547 dest_memory: op.operands[0],
548 num_outputs: op.operands[1] as usize,
549 first_output: op.operands[2] as usize,
550 })
551 }
552 MLIL_CALL_SSA => Op::CallSsa(CallSsa {
553 output: MediumLevelExpressionIndex::from(op.operands[0]),
554 dest: MediumLevelExpressionIndex::from(op.operands[1]),
555 num_params: op.operands[2] as usize,
556 first_param: op.operands[3] as usize,
557 src_memory: op.operands[4],
558 }),
559 MLIL_TAILCALL_SSA => Op::TailcallSsa(CallSsa {
560 output: MediumLevelExpressionIndex::from(op.operands[0]),
561 dest: MediumLevelExpressionIndex::from(op.operands[1]),
562 num_params: op.operands[2] as usize,
563 first_param: op.operands[3] as usize,
564 src_memory: op.operands[4],
565 }),
566 MLIL_CALL_UNTYPED_SSA => Op::CallUntypedSsa(CallUntypedSsa {
567 output: MediumLevelExpressionIndex::from(op.operands[0]),
568 dest: MediumLevelExpressionIndex::from(op.operands[1]),
569 params: MediumLevelExpressionIndex::from(op.operands[2]),
570 stack: MediumLevelExpressionIndex::from(op.operands[3]),
571 }),
572 MLIL_TAILCALL_UNTYPED_SSA => Op::TailcallUntypedSsa(CallUntypedSsa {
573 output: MediumLevelExpressionIndex::from(op.operands[0]),
574 dest: MediumLevelExpressionIndex::from(op.operands[1]),
575 params: MediumLevelExpressionIndex::from(op.operands[2]),
576 stack: MediumLevelExpressionIndex::from(op.operands[3]),
577 }),
578 MLIL_SYSCALL_SSA => Op::SyscallSsa(SyscallSsa {
579 output: MediumLevelExpressionIndex::from(op.operands[0]),
580 num_params: op.operands[1] as usize,
581 first_param: op.operands[2] as usize,
582 src_memory: op.operands[3],
583 }),
584 MLIL_SYSCALL_UNTYPED_SSA => Op::SyscallUntypedSsa(SyscallUntypedSsa {
585 output: MediumLevelExpressionIndex::from(op.operands[0]),
586 params: MediumLevelExpressionIndex::from(op.operands[1]),
587 stack: MediumLevelExpressionIndex::from(op.operands[2]),
588 }),
589 MLIL_CALL_UNTYPED => Op::CallUntyped(CallUntyped {
590 num_outputs: op.operands[0] as usize,
591 first_output: op.operands[1] as usize,
592 dest: MediumLevelExpressionIndex::from(op.operands[2]),
593 params: MediumLevelExpressionIndex::from(op.operands[3]),
594 stack: MediumLevelExpressionIndex::from(op.operands[4]),
595 }),
596 MLIL_TAILCALL_UNTYPED => Op::TailcallUntyped(CallUntyped {
597 num_outputs: op.operands[0] as usize,
598 first_output: op.operands[1] as usize,
599 dest: MediumLevelExpressionIndex::from(op.operands[2]),
600 params: MediumLevelExpressionIndex::from(op.operands[3]),
601 stack: MediumLevelExpressionIndex::from(op.operands[4]),
602 }),
603 MLIL_SYSCALL_UNTYPED => Op::SyscallUntyped(SyscallUntyped {
604 num_outputs: op.operands[0] as usize,
605 first_output: op.operands[1] as usize,
606 params: MediumLevelExpressionIndex::from(op.operands[2]),
607 stack: MediumLevelExpressionIndex::from(op.operands[3]),
608 }),
609 MLIL_NEG => Op::Neg(UnaryOp {
610 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
611 }),
612 MLIL_NOT => Op::Not(UnaryOp {
613 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
614 }),
615 MLIL_BSWAP => Op::Bswap(UnaryOp {
616 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
617 }),
618 MLIL_POPCNT => Op::Popcnt(UnaryOp {
619 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
620 }),
621 MLIL_CLZ => Op::Clz(UnaryOp {
622 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
623 }),
624 MLIL_CTZ => Op::Ctz(UnaryOp {
625 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
626 }),
627 MLIL_RBIT => Op::Rbit(UnaryOp {
628 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
629 }),
630 MLIL_CLS => Op::Cls(UnaryOp {
631 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
632 }),
633 MLIL_ABS => Op::Abs(UnaryOp {
634 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
635 }),
636 MLIL_SX => Op::Sx(UnaryOp {
637 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
638 }),
639 MLIL_ZX => Op::Zx(UnaryOp {
640 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
641 }),
642 MLIL_LOW_PART => Op::LowPart(UnaryOp {
643 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
644 }),
645 MLIL_BOOL_TO_INT => Op::BoolToInt(UnaryOp {
646 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
647 }),
648 MLIL_UNIMPL_MEM => Op::UnimplMem(UnaryOp {
649 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
650 }),
651 MLIL_FSQRT => Op::Fsqrt(UnaryOp {
652 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
653 }),
654 MLIL_FNEG => Op::Fneg(UnaryOp {
655 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
656 }),
657 MLIL_FABS => Op::Fabs(UnaryOp {
658 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
659 }),
660 MLIL_FLOAT_TO_INT => Op::FloatToInt(UnaryOp {
661 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
662 }),
663 MLIL_INT_TO_FLOAT => Op::IntToFloat(UnaryOp {
664 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
665 }),
666 MLIL_FLOAT_CONV => Op::FloatConv(UnaryOp {
667 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
668 }),
669 MLIL_ROUND_TO_INT => Op::RoundToInt(UnaryOp {
670 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
671 }),
672 MLIL_FLOOR => Op::Floor(UnaryOp {
673 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
674 }),
675 MLIL_CEIL => Op::Ceil(UnaryOp {
676 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
677 }),
678 MLIL_FTRUNC => Op::Ftrunc(UnaryOp {
679 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
680 }),
681 MLIL_LOAD => Op::Load(UnaryOp {
682 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
683 }),
684 MLIL_LOAD_STRUCT => Op::LoadStruct(LoadStruct {
685 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
686 offset: op.operands[1],
687 }),
688 MLIL_LOAD_STRUCT_SSA => Op::LoadStructSsa(LoadStructSsa {
689 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
690 offset: op.operands[1],
691 src_memory: op.operands[2],
692 }),
693 MLIL_LOAD_SSA => Op::LoadSsa(LoadSsa {
694 src: MediumLevelExpressionIndex::from(op.operands[0]),
695 src_memory: op.operands[1],
696 }),
697 MLIL_RET => Op::Ret(Ret {
698 num_operands: op.operands[0] as usize,
699 first_operand: op.operands[1] as usize,
700 }),
701 MLIL_SEPARATE_PARAM_LIST => Op::SeparateParamList(SeparateParamList {
702 num_params: op.operands[0] as usize,
703 first_param: op.operands[1] as usize,
704 }),
705 MLIL_SHARED_PARAM_SLOT => Op::SharedParamSlot(SharedParamSlot {
706 num_params: op.operands[0] as usize,
707 first_param: op.operands[1] as usize,
708 }),
709 MLIL_VAR => Op::Var(Var {
710 src: get_var(op.operands[0]),
711 }),
712 MLIL_VAR_OUTPUT => Op::VarOutput(VarOutput {
713 dest: get_var(op.operands[0]),
714 }),
715 MLIL_VAR_OUTPUT_FIELD => Op::VarOutputField(VarOutputField {
716 dest: get_var(op.operands[0]),
717 offset: op.operands[1],
718 }),
719 MLIL_STORE_OUTPUT => Op::StoreOutput(StoreOutput {
720 dest: MediumLevelExpressionIndex::from(op.operands[0]),
721 }),
722 MLIL_ADDRESS_OF => Op::AddressOf(Var {
723 src: get_var(op.operands[0]),
724 }),
725 MLIL_PASS_BY_REF => Op::PassByRef(UnaryOp {
726 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
727 }),
728 MLIL_RETURN_BY_REF => Op::ReturnByRef(UnaryOp {
729 src: MediumLevelExpressionIndex::from(op.operands[0] as usize),
730 }),
731 MLIL_VAR_FIELD => Op::VarField(Field {
732 src: get_var(op.operands[0]),
733 offset: op.operands[1],
734 }),
735 MLIL_ADDRESS_OF_FIELD => Op::AddressOfField(Field {
736 src: get_var(op.operands[0]),
737 offset: op.operands[1],
738 }),
739 MLIL_VAR_SSA => Op::VarSsa(VarSsa {
740 src: get_var_ssa(op.operands[0], op.operands[1] as usize),
741 }),
742 MLIL_VAR_ALIASED => Op::VarAliased(VarSsa {
743 src: get_var_ssa(op.operands[0], op.operands[1] as usize),
744 }),
745 MLIL_VAR_SSA_FIELD => Op::VarSsaField(VarSsaField {
746 src: get_var_ssa(op.operands[0], op.operands[1] as usize),
747 offset: op.operands[2],
748 }),
749 MLIL_VAR_ALIASED_FIELD => Op::VarAliasedField(VarSsaField {
750 src: get_var_ssa(op.operands[0], op.operands[1] as usize),
751 offset: op.operands[2],
752 }),
753 MLIL_VAR_OUTPUT_SSA => Op::VarOutputSsa(VarOutputSsa {
754 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
755 }),
756 MLIL_VAR_OUTPUT_SSA_FIELD => Op::VarOutputSsaField(VarOutputSsaField {
757 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
758 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
759 offset: op.operands[3],
760 }),
761 MLIL_VAR_OUTPUT_ALIASED => Op::VarOutputAliased(VarOutputAliased {
762 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
763 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
764 }),
765 MLIL_VAR_OUTPUT_ALIASED_FIELD => Op::VarOutputAliasedField(VarOutputAliasedField {
766 dest: get_var_ssa(op.operands[0], op.operands[1] as usize),
767 prev: get_var_ssa(op.operands[0], op.operands[2] as usize),
768 offset: op.operands[3],
769 }),
770 MLIL_TRAP => Op::Trap(Trap {
771 vector: op.operands[0],
772 }),
773 MLIL_BLOCK_TO_EXPAND => Op::BlockToExpand(BlockToExpand {
774 num_operands: op.operands[0] as usize,
775 first_operand: op.operands[1] as usize,
776 }),
777 };
778
779 Self {
780 function,
781 address: op.address,
782 instr_index,
783 expr_index,
784 size: op.size,
785 kind,
786 }
787 }
788
789 fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
790 let mut count = 0;
791 let raw_list_ptr = unsafe {
792 BNMediumLevelILGetOperandList(
793 self.function.handle,
794 self.expr_index.0,
795 operand_idx,
796 &mut count,
797 )
798 };
799 assert!(!raw_list_ptr.is_null());
800 let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
801 unsafe { BNMediumLevelILFreeOperandList(raw_list_ptr) };
802 list
803 }
804
805 fn get_var_list(&self, operand_idx: usize) -> Vec<Variable> {
806 self.get_operand_list(operand_idx)
807 .into_iter()
808 .map(Variable::from_identifier)
809 .collect()
810 }
811
812 fn get_ssa_var_list(&self, operand_idx: usize) -> Vec<SSAVariable> {
813 self.get_operand_list(operand_idx)
814 .chunks(2)
815 .map(|chunk| (Variable::from_identifier(chunk[0]), chunk[1] as usize))
816 .map(|(var, version)| SSAVariable::new(var, version))
817 .collect()
818 }
819
820 fn get_expr_list(&self, operand_idx: usize) -> Vec<MediumLevelILInstruction> {
821 self.get_operand_list(operand_idx)
822 .into_iter()
823 .map(|val| MediumLevelExpressionIndex(val as usize))
824 .filter_map(|idx| self.function.instruction_from_expr_index(idx))
825 .collect()
826 }
827
828 fn get_target_map(&self, operand_idx: usize) -> BTreeMap<u64, MediumLevelInstructionIndex> {
829 self.get_operand_list(operand_idx)
830 .chunks(2)
831 .filter_map(|chunk| chunk.get(0..2))
833 .map(|chunk| (chunk[0], MediumLevelInstructionIndex(chunk[1] as usize)))
834 .collect()
835 }
836
837 pub fn lift(&self) -> MediumLevelILLiftedInstruction {
838 use MediumLevelILInstructionKind::*;
839 use MediumLevelILLiftedInstructionKind as Lifted;
840
841 let kind = match self.kind {
842 Nop => Lifted::Nop,
843 Noret => Lifted::Noret,
844 Bp => Lifted::Bp,
845 Undef => Lifted::Undef,
846 Unimpl => Lifted::Unimpl,
847 If(op) => Lifted::If(LiftedIf {
848 condition: self.lift_operand(op.condition),
849 dest_true: op.dest_true,
850 dest_false: op.dest_false,
851 }),
852
853 FloatConst(op) => Lifted::FloatConst(op),
854 Const(op) => Lifted::Const(op),
855 ConstPtr(op) => Lifted::ConstPtr(op),
856 Import(op) => Lifted::Import(op),
857 ExternPtr(op) => Lifted::ExternPtr(op),
858
859 ConstData(op) => Lifted::ConstData(LiftedConstData {
860 constant_data: ConstantData::new(
861 self.function.function(),
862 RegisterValue {
863 state: unsafe {
867 std::mem::transmute::<u32, BNRegisterValueType>(op.constant_data_kind)
868 },
869 value: op.constant_data_value,
870 offset: 0,
871 size: op.size,
872 },
873 ),
874 }),
875 Jump(op) => Lifted::Jump(LiftedJump {
876 dest: self.lift_operand(op.dest),
877 }),
878 RetHint(op) => Lifted::RetHint(LiftedJump {
879 dest: self.lift_operand(op.dest),
880 }),
881 StoreSsa(op) => Lifted::StoreSsa(LiftedStoreSsa {
882 dest: self.lift_operand(op.dest),
883 dest_memory: op.dest_memory,
884 src_memory: op.src_memory,
885 src: self.lift_operand(op.src),
886 }),
887 StoreStructSsa(op) => Lifted::StoreStructSsa(LiftedStoreStructSsa {
888 dest: self.lift_operand(op.dest),
889 offset: op.offset,
890 dest_memory: op.dest_memory,
891 src_memory: op.src_memory,
892 src: self.lift_operand(op.src),
893 }),
894 StoreStruct(op) => Lifted::StoreStruct(LiftedStoreStruct {
895 dest: self.lift_operand(op.dest),
896 offset: op.offset,
897 src: self.lift_operand(op.src),
898 }),
899 Store(op) => Lifted::Store(LiftedStore {
900 dest: self.lift_operand(op.dest),
901 src: self.lift_operand(op.src),
902 }),
903 JumpTo(op) => Lifted::JumpTo(LiftedJumpTo {
904 dest: self.lift_operand(op.dest),
905 targets: self.get_target_map(1),
906 }),
907 Goto(op) => Lifted::Goto(op),
908 FreeVarSlot(op) => Lifted::FreeVarSlot(op),
909 SetVarField(op) => Lifted::SetVarField(LiftedSetVarField {
910 dest: op.dest,
911 offset: op.offset,
912 src: self.lift_operand(op.src),
913 }),
914 SetVar(op) => Lifted::SetVar(LiftedSetVar {
915 dest: op.dest,
916 src: self.lift_operand(op.src),
917 }),
918 FreeVarSlotSsa(op) => Lifted::FreeVarSlotSsa(op),
919 SetVarSsaField(op) => Lifted::SetVarSsaField(LiftedSetVarSsaField {
920 dest: op.dest,
921 prev: op.prev,
922 offset: op.offset,
923 src: self.lift_operand(op.src),
924 }),
925 SetVarAliasedField(op) => Lifted::SetVarAliasedField(LiftedSetVarSsaField {
926 dest: op.dest,
927 prev: op.prev,
928 offset: op.offset,
929 src: self.lift_operand(op.src),
930 }),
931 SetVarAliased(op) => Lifted::SetVarAliased(LiftedSetVarAliased {
932 dest: op.dest,
933 prev: op.prev,
934 src: self.lift_operand(op.src),
935 }),
936 SetVarSsa(op) => Lifted::SetVarSsa(LiftedSetVarSsa {
937 dest: op.dest,
938 src: self.lift_operand(op.src),
939 }),
940 VarPhi(op) => Lifted::VarPhi(LiftedVarPhi {
941 dest: op.dest,
942 src: self.get_ssa_var_list(2),
943 }),
944 MemPhi(op) => Lifted::MemPhi(LiftedMemPhi {
945 dest_memory: op.dest_memory,
946 src_memory: self.get_operand_list(1),
948 }),
949 VarSplit(op) => Lifted::VarSplit(op),
950 SetVarSplit(op) => Lifted::SetVarSplit(LiftedSetVarSplit {
951 high: op.high,
952 low: op.low,
953 src: self.lift_operand(op.src),
954 }),
955 VarSplitSsa(op) => Lifted::VarSplitSsa(op),
956 SetVarSplitSsa(op) => Lifted::SetVarSplitSsa(LiftedSetVarSplitSsa {
957 high: op.high,
958 low: op.low,
959 src: self.lift_operand(op.src),
960 }),
961 Assert(op) => Lifted::Assert(LiftedAssert {
962 src: op.src,
963 constraint: PossibleValueSet::from_owned_core_raw(unsafe {
964 BNGetCachedMediumLevelILPossibleValueSet(
965 self.function.handle,
966 op.constraint_index,
967 )
968 }),
969 }),
970 ForceVer(op) => Lifted::ForceVer(op),
971 AssertSsa(op) => Lifted::AssertSsa(LiftedAssertSsa {
972 src: op.src,
973 constraint: PossibleValueSet::from_owned_core_raw(unsafe {
974 BNGetCachedMediumLevelILPossibleValueSet(
975 self.function.handle,
976 op.constraint_index,
977 )
978 }),
979 }),
980 ForceVerSsa(op) => Lifted::ForceVerSsa(op),
981
982 Add(op) => Lifted::Add(self.lift_binary_op(op)),
983 Sub(op) => Lifted::Sub(self.lift_binary_op(op)),
984 And(op) => Lifted::And(self.lift_binary_op(op)),
985 Or(op) => Lifted::Or(self.lift_binary_op(op)),
986 Xor(op) => Lifted::Xor(self.lift_binary_op(op)),
987 Lsl(op) => Lifted::Lsl(self.lift_binary_op(op)),
988 Lsr(op) => Lifted::Lsr(self.lift_binary_op(op)),
989 Asr(op) => Lifted::Asr(self.lift_binary_op(op)),
990 Rol(op) => Lifted::Rol(self.lift_binary_op(op)),
991 Ror(op) => Lifted::Ror(self.lift_binary_op(op)),
992 Mul(op) => Lifted::Mul(self.lift_binary_op(op)),
993 MuluDp(op) => Lifted::MuluDp(self.lift_binary_op(op)),
994 MulsDp(op) => Lifted::MulsDp(self.lift_binary_op(op)),
995 Divu(op) => Lifted::Divu(self.lift_binary_op(op)),
996 DivuDp(op) => Lifted::DivuDp(self.lift_binary_op(op)),
997 Divs(op) => Lifted::Divs(self.lift_binary_op(op)),
998 DivsDp(op) => Lifted::DivsDp(self.lift_binary_op(op)),
999 Modu(op) => Lifted::Modu(self.lift_binary_op(op)),
1000 ModuDp(op) => Lifted::ModuDp(self.lift_binary_op(op)),
1001 Mods(op) => Lifted::Mods(self.lift_binary_op(op)),
1002 ModsDp(op) => Lifted::ModsDp(self.lift_binary_op(op)),
1003 MinSigned(op) => Lifted::MinSigned(self.lift_binary_op(op)),
1004 MaxSigned(op) => Lifted::MaxSigned(self.lift_binary_op(op)),
1005 MinUnsigned(op) => Lifted::MinUnsigned(self.lift_binary_op(op)),
1006 MaxUnsigned(op) => Lifted::MaxUnsigned(self.lift_binary_op(op)),
1007 CmpE(op) => Lifted::CmpE(self.lift_binary_op(op)),
1008 CmpNe(op) => Lifted::CmpNe(self.lift_binary_op(op)),
1009 CmpSlt(op) => Lifted::CmpSlt(self.lift_binary_op(op)),
1010 CmpUlt(op) => Lifted::CmpUlt(self.lift_binary_op(op)),
1011 CmpSle(op) => Lifted::CmpSle(self.lift_binary_op(op)),
1012 CmpUle(op) => Lifted::CmpUle(self.lift_binary_op(op)),
1013 CmpSge(op) => Lifted::CmpSge(self.lift_binary_op(op)),
1014 CmpUge(op) => Lifted::CmpUge(self.lift_binary_op(op)),
1015 CmpSgt(op) => Lifted::CmpSgt(self.lift_binary_op(op)),
1016 CmpUgt(op) => Lifted::CmpUgt(self.lift_binary_op(op)),
1017 TestBit(op) => Lifted::TestBit(self.lift_binary_op(op)),
1018 AddOverflow(op) => Lifted::AddOverflow(self.lift_binary_op(op)),
1019 FcmpE(op) => Lifted::FcmpE(self.lift_binary_op(op)),
1020 FcmpNe(op) => Lifted::FcmpNe(self.lift_binary_op(op)),
1021 FcmpLt(op) => Lifted::FcmpLt(self.lift_binary_op(op)),
1022 FcmpLe(op) => Lifted::FcmpLe(self.lift_binary_op(op)),
1023 FcmpGe(op) => Lifted::FcmpGe(self.lift_binary_op(op)),
1024 FcmpGt(op) => Lifted::FcmpGt(self.lift_binary_op(op)),
1025 FcmpO(op) => Lifted::FcmpO(self.lift_binary_op(op)),
1026 FcmpUo(op) => Lifted::FcmpUo(self.lift_binary_op(op)),
1027 Fadd(op) => Lifted::Fadd(self.lift_binary_op(op)),
1028 Fsub(op) => Lifted::Fsub(self.lift_binary_op(op)),
1029 Fmul(op) => Lifted::Fmul(self.lift_binary_op(op)),
1030 Fdiv(op) => Lifted::Fdiv(self.lift_binary_op(op)),
1031
1032 Adc(op) => Lifted::Adc(self.lift_binary_op_carry(op)),
1033 Sbb(op) => Lifted::Sbb(self.lift_binary_op_carry(op)),
1034 Rlc(op) => Lifted::Rlc(self.lift_binary_op_carry(op)),
1035 Rrc(op) => Lifted::Rrc(self.lift_binary_op_carry(op)),
1036
1037 Call(op) => Lifted::Call(self.lift_call(op)),
1038 CallParam(_op) => Lifted::CallParam(LiftedCallParam {
1039 params: self.get_expr_list(0).iter().map(|i| i.lift()).collect(),
1040 }),
1041 CallOutputSsa(op) => Lifted::CallOutputSsa(LiftedCallOutputSsa {
1042 dest_memory: op.dest_memory,
1043 output: self.get_expr_list(1).iter().map(|i| i.lift()).collect(),
1044 }),
1045 CallParamSsa(op) => Lifted::CallParamSsa(LiftedCallParamSsa {
1046 src_memory: op.src_memory,
1047 params: self.get_expr_list(1).iter().map(|i| i.lift()).collect(),
1048 }),
1049
1050 Tailcall(op) => Lifted::Tailcall(self.lift_call(op)),
1051
1052 Intrinsic(op) => Lifted::Intrinsic(LiftedIntrinsic {
1053 output: self.get_var_list(0),
1054 intrinsic: CoreIntrinsic::new(
1055 self.function.function().arch(),
1056 IntrinsicId(op.intrinsic),
1057 )
1058 .expect("Valid intrinsic"),
1059 params: self
1060 .get_expr_list(3)
1061 .iter()
1062 .map(|expr| expr.lift())
1063 .collect(),
1064 }),
1065 Syscall(_op) => Lifted::Syscall(LiftedSyscallCall {
1066 output: self
1067 .get_expr_list(0)
1068 .iter()
1069 .map(|expr| expr.lift())
1070 .collect(),
1071 params: self
1072 .get_expr_list(2)
1073 .iter()
1074 .map(|expr| expr.lift())
1075 .collect(),
1076 }),
1077 IntrinsicSsa(op) => Lifted::IntrinsicSsa(LiftedIntrinsicSsa {
1078 output: self.get_ssa_var_list(0),
1079 intrinsic: CoreIntrinsic::new(
1080 self.function.function().arch(),
1081 IntrinsicId(op.intrinsic),
1082 )
1083 .expect("Valid intrinsic"),
1084 params: self
1085 .get_expr_list(3)
1086 .iter()
1087 .map(|expr| expr.lift())
1088 .collect(),
1089 }),
1090 MemoryIntrinsicSsa(op) => Lifted::MemoryIntrinsicSsa(LiftedMemoryIntrinsicSsa {
1091 output: self.lift_operand(op.output),
1092 intrinsic: CoreIntrinsic::new(
1093 self.function.function().arch(),
1094 IntrinsicId(op.intrinsic),
1095 )
1096 .expect("Valid intrinsic"),
1097 params: self
1098 .get_expr_list(2)
1099 .iter()
1100 .map(|expr| expr.lift())
1101 .collect(),
1102 src_memory: op.src_memory,
1103 }),
1104 MemoryIntrinsicOutputSsa(op) => {
1105 Lifted::MemoryIntrinsicOutputSsa(LiftedMemoryIntrinsicOutputSsa {
1106 dest_memory: op.dest_memory,
1107 output: self.get_ssa_var_list(1),
1108 })
1109 }
1110
1111 CallSsa(op) => Lifted::CallSsa(self.lift_call_ssa(op)),
1112 TailcallSsa(op) => Lifted::TailcallSsa(self.lift_call_ssa(op)),
1113
1114 CallUntypedSsa(op) => Lifted::CallUntypedSsa(self.lift_call_untyped_ssa(op)),
1115 TailcallUntypedSsa(op) => Lifted::TailcallUntypedSsa(self.lift_call_untyped_ssa(op)),
1116
1117 SyscallSsa(op) => {
1118 let output_instr = self
1119 .function
1120 .instruction_from_expr_index(op.output)
1121 .expect("Valid output expression index");
1122 Lifted::SyscallSsa(LiftedSyscallSsa {
1123 output: get_call_output_ssa(&output_instr)
1124 .iter()
1125 .map(|expr| expr.lift())
1126 .collect(),
1127 params: self
1128 .get_expr_list(1)
1129 .iter()
1130 .map(|expr| expr.lift())
1131 .collect(),
1132 src_memory: op.src_memory,
1133 })
1134 }
1135 SyscallUntypedSsa(op) => {
1136 let output_instr = self
1137 .function
1138 .instruction_from_expr_index(op.output)
1139 .expect("Valid output expression index");
1140 let params_instr = self
1141 .function
1142 .instruction_from_expr_index(op.params)
1143 .expect("Valid params expression index");
1144 Lifted::SyscallUntypedSsa(LiftedSyscallUntypedSsa {
1145 output: get_call_output_ssa(&output_instr)
1146 .iter()
1147 .map(|expr| expr.lift())
1148 .collect(),
1149 params: get_call_params_ssa(¶ms_instr)
1150 .iter()
1151 .map(|param| param.lift())
1152 .collect(),
1153 stack: self.lift_operand(op.stack),
1154 })
1155 }
1156
1157 CallUntyped(op) => Lifted::CallUntyped(self.lift_call_untyped(op)),
1158 TailcallUntyped(op) => Lifted::TailcallUntyped(self.lift_call_untyped(op)),
1159 SyscallUntyped(op) => {
1160 let params_instr = self
1161 .function
1162 .instruction_from_expr_index(op.params)
1163 .expect("Valid params expression index");
1164 Lifted::SyscallUntyped(LiftedSyscallUntyped {
1165 output: self
1166 .get_expr_list(0)
1167 .iter()
1168 .map(|expr| expr.lift())
1169 .collect(),
1170 params: get_call_params(¶ms_instr)
1171 .iter()
1172 .map(|param| param.lift())
1173 .collect(),
1174 stack: self.lift_operand(op.stack),
1175 })
1176 }
1177
1178 Neg(op) => Lifted::Neg(self.lift_unary_op(op)),
1179 Not(op) => Lifted::Not(self.lift_unary_op(op)),
1180 Bswap(op) => Lifted::Bswap(self.lift_unary_op(op)),
1181 Popcnt(op) => Lifted::Popcnt(self.lift_unary_op(op)),
1182 Clz(op) => Lifted::Clz(self.lift_unary_op(op)),
1183 Ctz(op) => Lifted::Ctz(self.lift_unary_op(op)),
1184 Rbit(op) => Lifted::Rbit(self.lift_unary_op(op)),
1185 Cls(op) => Lifted::Cls(self.lift_unary_op(op)),
1186 Abs(op) => Lifted::Abs(self.lift_unary_op(op)),
1187 Sx(op) => Lifted::Sx(self.lift_unary_op(op)),
1188 Zx(op) => Lifted::Zx(self.lift_unary_op(op)),
1189 LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)),
1190 BoolToInt(op) => Lifted::BoolToInt(self.lift_unary_op(op)),
1191 UnimplMem(op) => Lifted::UnimplMem(self.lift_unary_op(op)),
1192 Fsqrt(op) => Lifted::Fsqrt(self.lift_unary_op(op)),
1193 Fneg(op) => Lifted::Fneg(self.lift_unary_op(op)),
1194 Fabs(op) => Lifted::Fabs(self.lift_unary_op(op)),
1195 FloatToInt(op) => Lifted::FloatToInt(self.lift_unary_op(op)),
1196 IntToFloat(op) => Lifted::IntToFloat(self.lift_unary_op(op)),
1197 FloatConv(op) => Lifted::FloatConv(self.lift_unary_op(op)),
1198 RoundToInt(op) => Lifted::RoundToInt(self.lift_unary_op(op)),
1199 Floor(op) => Lifted::Floor(self.lift_unary_op(op)),
1200 Ceil(op) => Lifted::Ceil(self.lift_unary_op(op)),
1201 Ftrunc(op) => Lifted::Ftrunc(self.lift_unary_op(op)),
1202 Load(op) => Lifted::Load(self.lift_unary_op(op)),
1203
1204 LoadStruct(op) => Lifted::LoadStruct(LiftedLoadStruct {
1205 src: self.lift_operand(op.src),
1206 offset: op.offset,
1207 }),
1208 LoadStructSsa(op) => Lifted::LoadStructSsa(LiftedLoadStructSsa {
1209 src: self.lift_operand(op.src),
1210 offset: op.offset,
1211 src_memory: op.src_memory,
1212 }),
1213 LoadSsa(op) => Lifted::LoadSsa(LiftedLoadSsa {
1214 src: self.lift_operand(op.src),
1215 src_memory: op.src_memory,
1216 }),
1217 Ret(_op) => Lifted::Ret(LiftedRet {
1218 src: self
1219 .get_expr_list(0)
1220 .iter()
1221 .map(|expr| expr.lift())
1222 .collect(),
1223 }),
1224 SeparateParamList(_op) => Lifted::SeparateParamList(LiftedSeparateParamList {
1225 params: self
1226 .get_expr_list(0)
1227 .iter()
1228 .map(|expr| expr.lift())
1229 .collect(),
1230 }),
1231 SharedParamSlot(_op) => Lifted::SharedParamSlot(LiftedSharedParamSlot {
1232 params: self
1233 .get_expr_list(0)
1234 .iter()
1235 .map(|expr| expr.lift())
1236 .collect(),
1237 }),
1238 Var(op) => Lifted::Var(op),
1239 VarOutput(op) => Lifted::VarOutput(op),
1240 VarOutputField(op) => Lifted::VarOutputField(op),
1241 StoreOutput(op) => Lifted::StoreOutput(LiftedStoreOutput {
1242 dest: self.lift_operand(op.dest),
1243 }),
1244 AddressOf(op) => Lifted::AddressOf(op),
1245 PassByRef(op) => Lifted::PassByRef(self.lift_unary_op(op)),
1246 ReturnByRef(op) => Lifted::ReturnByRef(self.lift_unary_op(op)),
1247 VarField(op) => Lifted::VarField(op),
1248 AddressOfField(op) => Lifted::AddressOfField(op),
1249 VarSsa(op) => Lifted::VarSsa(op),
1250 VarAliased(op) => Lifted::VarAliased(op),
1251 VarSsaField(op) => Lifted::VarSsaField(op),
1252 VarAliasedField(op) => Lifted::VarAliasedField(op),
1253 VarOutputSsa(op) => Lifted::VarOutputSsa(op),
1254 VarOutputSsaField(op) => Lifted::VarOutputSsaField(op),
1255 VarOutputAliased(op) => Lifted::VarOutputAliased(op),
1256 VarOutputAliasedField(op) => Lifted::VarOutputAliasedField(op),
1257 Trap(op) => Lifted::Trap(op),
1258 BlockToExpand(_op) => Lifted::BlockToExpand(LiftedBlockToExpand {
1259 exprs: self
1260 .get_expr_list(0)
1261 .iter()
1262 .map(|expr| expr.lift())
1263 .collect(),
1264 }),
1265 };
1266
1267 MediumLevelILLiftedInstruction {
1268 function: self.function.clone(),
1269 address: self.address,
1270 instr_index: self.instr_index,
1271 expr_index: self.expr_index,
1272 size: self.size,
1273 kind,
1274 }
1275 }
1276
1277 pub fn tokens(&self) -> Array<InstructionTextToken> {
1278 let mut count = 0;
1279 let mut tokens = core::ptr::null_mut();
1280 assert!(unsafe {
1281 BNGetMediumLevelILExprText(
1282 self.function.handle,
1283 self.function.function().arch().handle,
1284 self.expr_index.0,
1285 &mut tokens,
1286 &mut count,
1287 core::ptr::null_mut(),
1288 )
1289 });
1290 unsafe { Array::new(tokens, count, ()) }
1291 }
1292
1293 pub fn value(&self) -> RegisterValue {
1295 unsafe { BNGetMediumLevelILExprValue(self.function.handle, self.expr_index.0) }.into()
1296 }
1297
1298 pub fn basic_block(&self) -> Option<Ref<BasicBlock<MediumLevelILBlock>>> {
1300 self.function.basic_block_containing_index(self.instr_index)
1302 }
1303
1304 pub fn possible_values(&self) -> PossibleValueSet {
1306 self.possible_values_with_opts(&[])
1307 }
1308
1309 pub fn possible_values_with_opts(&self, options: &[DataFlowQueryOption]) -> PossibleValueSet {
1311 let value = unsafe {
1312 BNGetMediumLevelILPossibleExprValues(
1313 self.function.handle,
1314 self.expr_index.0,
1315 options.as_ptr() as *mut _,
1316 options.len(),
1317 )
1318 };
1319 PossibleValueSet::from_owned_core_raw(value)
1320 }
1321
1322 pub fn possible_ssa_variable_values(&self, ssa_var: &SSAVariable) -> PossibleValueSet {
1323 self.possible_ssa_variable_values_with_opts(ssa_var, &[])
1324 }
1325
1326 pub fn possible_ssa_variable_values_with_opts(
1327 &self,
1328 ssa_var: &SSAVariable,
1329 options: &[DataFlowQueryOption],
1330 ) -> PossibleValueSet {
1331 let raw_var = BNVariable::from(ssa_var.variable);
1332 let value = unsafe {
1333 BNGetMediumLevelILPossibleSSAVarValues(
1334 self.function.handle,
1335 &raw_var,
1336 ssa_var.version,
1337 self.instr_index.0,
1338 options.as_ptr() as *mut _,
1339 options.len(),
1340 )
1341 };
1342 PossibleValueSet::from_owned_core_raw(value)
1343 }
1344
1345 pub fn ssa_variable_version(&self, var: Variable) -> SSAVariable {
1347 let raw_var = BNVariable::from(var);
1348 let version = unsafe {
1349 BNGetMediumLevelILSSAVarVersionAtILInstruction(
1350 self.function.handle,
1351 &raw_var,
1352 self.instr_index.0,
1353 )
1354 };
1355 SSAVariable::new(var, version)
1356 }
1357
1358 pub fn ssa_variable_version_after(&self, var: Variable) -> SSAVariable {
1360 let raw_var = BNVariable::from(var);
1361 let version = unsafe {
1362 BNGetMediumLevelILSSAVarVersionAfterILInstruction(
1363 self.function.handle,
1364 &raw_var,
1365 self.instr_index.0,
1366 )
1367 };
1368 SSAVariable::new(var, version)
1369 }
1370
1371 pub fn branch_dependencies(&self) -> Array<BranchDependence> {
1373 let mut count = 0;
1374 let deps = unsafe {
1375 BNGetAllMediumLevelILBranchDependence(
1376 self.function.handle,
1377 self.instr_index.0,
1378 &mut count,
1379 )
1380 };
1381 assert!(!deps.is_null());
1382 unsafe { Array::new(deps, count, self.function.clone()) }
1383 }
1384
1385 pub fn branch_dependence_at(
1386 &self,
1387 branch_instruction: MediumLevelILInstruction,
1388 ) -> BranchDependence {
1389 let deps = unsafe {
1390 BNGetMediumLevelILBranchDependence(
1391 self.function.handle,
1392 self.instr_index.0,
1393 branch_instruction.instr_index.0,
1394 )
1395 };
1396 BranchDependence {
1397 instruction: branch_instruction,
1398 dependence: deps,
1399 }
1400 }
1401
1402 pub fn ssa_memory_version(&self) -> usize {
1404 unsafe {
1405 BNGetMediumLevelILSSAMemoryVersionAtILInstruction(
1406 self.function.handle,
1407 self.instr_index.0,
1408 )
1409 }
1410 }
1411
1412 pub fn ssa_memory_version_after(&self) -> usize {
1414 unsafe {
1415 BNGetMediumLevelILSSAMemoryVersionAfterILInstruction(
1416 self.function.handle,
1417 self.instr_index.0,
1418 )
1419 }
1420 }
1421
1422 pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
1424 let result = unsafe { BNGetMediumLevelILExprType(self.function.handle, self.expr_index.0) };
1425 (!result.type_.is_null()).then(|| Conf::<Ref<Type>>::from_owned_raw(result))
1426 }
1427
1428 pub fn set_expr_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) {
1435 let mut ty: BNTypeWithConfidence = Conf::<&Type>::into_raw(ty.into());
1436 unsafe { BNSetMediumLevelILExprType(self.function.handle, self.expr_index.0, &mut ty) }
1437 }
1438
1439 pub fn variable_for_register(&self, reg_id: RegisterId) -> Variable {
1440 let result = unsafe {
1441 BNGetMediumLevelILVariableForRegisterAtInstruction(
1442 self.function.handle,
1443 reg_id.0,
1444 self.instr_index.0,
1445 )
1446 };
1447 Variable::from(result)
1448 }
1449
1450 pub fn variable_for_register_after(&self, reg_id: RegisterId) -> Variable {
1451 let result = unsafe {
1452 BNGetMediumLevelILVariableForRegisterAfterInstruction(
1453 self.function.handle,
1454 reg_id.0,
1455 self.instr_index.0,
1456 )
1457 };
1458 Variable::from(result)
1459 }
1460
1461 pub fn variable_for_flag(&self, flag_id: FlagId) -> Variable {
1462 let result = unsafe {
1463 BNGetMediumLevelILVariableForFlagAtInstruction(
1464 self.function.handle,
1465 flag_id.0,
1466 self.instr_index.0,
1467 )
1468 };
1469 Variable::from(result)
1470 }
1471
1472 pub fn variable_for_flag_after(&self, flag_id: FlagId) -> Variable {
1473 let result = unsafe {
1474 BNGetMediumLevelILVariableForFlagAfterInstruction(
1475 self.function.handle,
1476 flag_id.0,
1477 self.instr_index.0,
1478 )
1479 };
1480 Variable::from(result)
1481 }
1482
1483 pub fn variable_for_stack_location(&self, offset: i64) -> Variable {
1484 let result = unsafe {
1485 BNGetMediumLevelILVariableForStackLocationAtInstruction(
1486 self.function.handle,
1487 offset,
1488 self.instr_index.0,
1489 )
1490 };
1491 Variable::from(result)
1492 }
1493
1494 pub fn variable_for_stack_location_after(&self, offset: i64) -> Variable {
1495 let result = unsafe {
1496 BNGetMediumLevelILVariableForStackLocationAfterInstruction(
1497 self.function.handle,
1498 offset,
1499 self.instr_index.0,
1500 )
1501 };
1502 Variable::from(result)
1503 }
1504
1505 pub fn register_value(&self, reg_id: RegisterId) -> RegisterValue {
1506 unsafe {
1507 BNGetMediumLevelILRegisterValueAtInstruction(
1508 self.function.handle,
1509 reg_id.0,
1510 self.instr_index.0,
1511 )
1512 }
1513 .into()
1514 }
1515
1516 pub fn register_value_after(&self, reg_id: RegisterId) -> RegisterValue {
1517 unsafe {
1518 BNGetMediumLevelILRegisterValueAfterInstruction(
1519 self.function.handle,
1520 reg_id.0,
1521 self.instr_index.0,
1522 )
1523 }
1524 .into()
1525 }
1526
1527 pub fn possible_register_values(&self, reg_id: RegisterId) -> PossibleValueSet {
1528 self.possible_register_values_with_opts(reg_id, &[])
1529 }
1530
1531 pub fn possible_register_values_with_opts(
1532 &self,
1533 reg_id: RegisterId,
1534 options: &[DataFlowQueryOption],
1535 ) -> PossibleValueSet {
1536 let value = unsafe {
1537 BNGetMediumLevelILPossibleRegisterValuesAtInstruction(
1538 self.function.handle,
1539 reg_id.0,
1540 self.instr_index.0,
1541 options.as_ptr() as *mut _,
1542 options.len(),
1543 )
1544 };
1545 PossibleValueSet::from_owned_core_raw(value)
1546 }
1547
1548 pub fn possible_register_values_after(&self, reg_id: RegisterId) -> PossibleValueSet {
1549 self.possible_register_values_after_with_opts(reg_id, &[])
1550 }
1551
1552 pub fn possible_register_values_after_with_opts(
1553 &self,
1554 reg_id: RegisterId,
1555 options: &[DataFlowQueryOption],
1556 ) -> PossibleValueSet {
1557 let value = unsafe {
1558 BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(
1559 self.function.handle,
1560 reg_id.0,
1561 self.instr_index.0,
1562 options.as_ptr() as *mut _,
1563 options.len(),
1564 )
1565 };
1566 PossibleValueSet::from_owned_core_raw(value)
1567 }
1568
1569 pub fn flag_value(&self, flag_id: FlagId) -> RegisterValue {
1570 unsafe {
1571 BNGetMediumLevelILFlagValueAtInstruction(
1572 self.function.handle,
1573 flag_id.0,
1574 self.instr_index.0,
1575 )
1576 }
1577 .into()
1578 }
1579
1580 pub fn flag_value_after(&self, flag_id: FlagId) -> RegisterValue {
1581 unsafe {
1582 BNGetMediumLevelILFlagValueAfterInstruction(
1583 self.function.handle,
1584 flag_id.0,
1585 self.instr_index.0,
1586 )
1587 }
1588 .into()
1589 }
1590
1591 pub fn possible_flag_values(&self, flag_id: FlagId) -> PossibleValueSet {
1592 self.possible_flag_values_with_opts(flag_id, &[])
1593 }
1594
1595 pub fn possible_flag_values_with_opts(
1596 &self,
1597 flag_id: FlagId,
1598 options: &[DataFlowQueryOption],
1599 ) -> PossibleValueSet {
1600 let value = unsafe {
1601 BNGetMediumLevelILPossibleFlagValuesAtInstruction(
1602 self.function.handle,
1603 flag_id.0,
1604 self.instr_index.0,
1605 options.as_ptr() as *mut _,
1606 options.len(),
1607 )
1608 };
1609 PossibleValueSet::from_owned_core_raw(value)
1610 }
1611
1612 pub fn possible_flag_values_after_with_opts(
1613 &self,
1614 flag_id: FlagId,
1615 options: &[DataFlowQueryOption],
1616 ) -> PossibleValueSet {
1617 let value = unsafe {
1618 BNGetMediumLevelILPossibleFlagValuesAfterInstruction(
1619 self.function.handle,
1620 flag_id.0,
1621 self.instr_index.0,
1622 options.as_ptr() as *mut _,
1623 options.len(),
1624 )
1625 };
1626 PossibleValueSet::from_owned_core_raw(value)
1627 }
1628
1629 pub fn stack_contents(&self, offset: i64, size: usize) -> RegisterValue {
1630 unsafe {
1631 BNGetMediumLevelILStackContentsAtInstruction(
1632 self.function.handle,
1633 offset,
1634 size,
1635 self.instr_index.0,
1636 )
1637 }
1638 .into()
1639 }
1640
1641 pub fn stack_contents_after(&self, offset: i64, size: usize) -> RegisterValue {
1642 unsafe {
1643 BNGetMediumLevelILStackContentsAfterInstruction(
1644 self.function.handle,
1645 offset,
1646 size,
1647 self.instr_index.0,
1648 )
1649 }
1650 .into()
1651 }
1652
1653 pub fn possible_stack_contents_with_opts(
1654 &self,
1655 offset: i64,
1656 size: usize,
1657 options: &[DataFlowQueryOption],
1658 ) -> PossibleValueSet {
1659 let value = unsafe {
1660 BNGetMediumLevelILPossibleStackContentsAtInstruction(
1661 self.function.handle,
1662 offset,
1663 size,
1664 self.instr_index.0,
1665 options.as_ptr() as *mut _,
1666 options.len(),
1667 )
1668 };
1669 PossibleValueSet::from_owned_core_raw(value)
1670 }
1671
1672 pub fn possible_stack_contents_after_with_opts(
1673 &self,
1674 offset: i64,
1675 size: usize,
1676 options: &[DataFlowQueryOption],
1677 ) -> PossibleValueSet {
1678 let value = unsafe {
1679 BNGetMediumLevelILPossibleStackContentsAfterInstruction(
1680 self.function.handle,
1681 offset,
1682 size,
1683 self.instr_index.0,
1684 options.as_ptr() as *mut _,
1685 options.len(),
1686 )
1687 };
1688 PossibleValueSet::from_owned_core_raw(value)
1689 }
1690
1691 pub fn split_var_for_definition(&self, var: &Variable) -> Variable {
1697 let raw_var = BNVariable::from(var);
1698 let index = unsafe {
1699 BNGetDefaultIndexForMediumLevelILVariableDefinition(
1700 self.function.handle,
1701 &raw_var,
1702 self.instr_index.0,
1703 )
1704 };
1705 Variable::new(var.ty, index, var.storage)
1706 }
1707
1708 fn lift_operand(
1709 &self,
1710 expr_idx: MediumLevelExpressionIndex,
1711 ) -> Box<MediumLevelILLiftedInstruction> {
1712 let operand_instr = self
1713 .function
1714 .instruction_from_expr_index(expr_idx)
1715 .expect("Invalid operand expression index");
1716 Box::new(operand_instr.lift())
1717 }
1718
1719 fn lift_binary_op(&self, op: BinaryOp) -> LiftedBinaryOp {
1720 LiftedBinaryOp {
1721 left: self.lift_operand(op.left),
1722 right: self.lift_operand(op.right),
1723 }
1724 }
1725
1726 fn lift_binary_op_carry(&self, op: BinaryOpCarry) -> LiftedBinaryOpCarry {
1727 LiftedBinaryOpCarry {
1728 left: self.lift_operand(op.left),
1729 right: self.lift_operand(op.right),
1730 carry: self.lift_operand(op.carry),
1731 }
1732 }
1733
1734 fn lift_unary_op(&self, op: UnaryOp) -> LiftedUnaryOp {
1735 LiftedUnaryOp {
1736 src: self.lift_operand(op.src),
1737 }
1738 }
1739
1740 fn lift_call(&self, op: Call) -> LiftedCall {
1741 LiftedCall {
1742 output: self
1743 .get_expr_list(0)
1744 .iter()
1745 .map(|expr| expr.lift())
1746 .collect(),
1747 dest: self.lift_operand(op.dest),
1748 params: self
1749 .get_expr_list(3)
1750 .iter()
1751 .map(|expr| expr.lift())
1752 .collect(),
1753 }
1754 }
1755
1756 fn lift_call_untyped(&self, op: CallUntyped) -> LiftedCallUntyped {
1757 let params_instr = self
1758 .function
1759 .instruction_from_expr_index(op.params)
1760 .expect("Valid params expression index");
1761 LiftedCallUntyped {
1762 output: self
1763 .get_expr_list(0)
1764 .iter()
1765 .map(|expr| expr.lift())
1766 .collect(),
1767 dest: self.lift_operand(op.dest),
1768 params: get_call_params(¶ms_instr)
1769 .iter()
1770 .map(|expr| expr.lift())
1771 .collect(),
1772 stack: self.lift_operand(op.stack),
1773 }
1774 }
1775
1776 fn lift_call_ssa(&self, op: CallSsa) -> LiftedCallSsa {
1777 let output_instr = self
1778 .function
1779 .instruction_from_expr_index(op.output)
1780 .expect("Valid output expression index");
1781 LiftedCallSsa {
1782 output: get_call_output_ssa(&output_instr)
1783 .iter()
1784 .map(|expr| expr.lift())
1785 .collect(),
1786 dest: self.lift_operand(op.dest),
1787 params: self
1788 .get_expr_list(2)
1789 .iter()
1790 .map(|expr| expr.lift())
1791 .collect(),
1792 src_memory: op.src_memory,
1793 }
1794 }
1795
1796 fn lift_call_untyped_ssa(&self, op: CallUntypedSsa) -> LiftedCallUntypedSsa {
1797 let output_instr = self
1798 .function
1799 .instruction_from_expr_index(op.output)
1800 .expect("Valid output expression index");
1801 let params_instr = self
1802 .function
1803 .instruction_from_expr_index(op.params)
1804 .expect("Valid params expression index");
1805 LiftedCallUntypedSsa {
1806 output: get_call_output_ssa(&output_instr)
1807 .iter()
1808 .map(|expr| expr.lift())
1809 .collect(),
1810 dest: self.lift_operand(op.dest),
1811 params: get_call_params_ssa(¶ms_instr)
1812 .iter()
1813 .map(|param| param.lift())
1814 .collect(),
1815 stack: self.lift_operand(op.stack),
1816 }
1817 }
1818}
1819
1820impl Debug for MediumLevelILInstruction {
1821 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1822 f.debug_struct("MediumLevelILInstruction")
1823 .field("address", &self.address)
1824 .field("instr_index", &self.instr_index)
1825 .field("expr_index", &self.expr_index)
1826 .field("size", &self.size)
1827 .field("kind", &self.kind)
1828 .finish()
1829 }
1830}
1831
1832impl CoreArrayProvider for MediumLevelILInstruction {
1833 type Raw = usize;
1834 type Context = Ref<MediumLevelILFunction>;
1835 type Wrapped<'a> = Self;
1836}
1837
1838unsafe impl CoreArrayProviderInner for MediumLevelILInstruction {
1839 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1840 BNFreeILInstructionList(raw)
1841 }
1842
1843 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1844 context
1845 .instruction_from_index(MediumLevelInstructionIndex(*raw))
1846 .unwrap()
1847 }
1848}
1849
1850#[derive(Debug, Copy, Clone)]
1851pub enum MediumLevelILInstructionKind {
1852 Nop,
1853 Noret,
1854 Bp,
1855 Undef,
1856 Unimpl,
1857 If(MediumLevelILOperationIf),
1858 FloatConst(FloatConst),
1859 Const(Constant),
1860 ConstPtr(Constant),
1861 Import(Constant),
1862 ExternPtr(ExternPtr),
1863 ConstData(ConstData),
1864 Jump(Jump),
1865 RetHint(Jump),
1866 StoreSsa(StoreSsa),
1867 StoreStructSsa(StoreStructSsa),
1868 StoreStruct(StoreStruct),
1869 Store(Store),
1870 JumpTo(JumpTo),
1871 Goto(Goto),
1872 FreeVarSlot(FreeVarSlot),
1873 SetVarField(SetVarField),
1874 SetVar(SetVar),
1875 FreeVarSlotSsa(FreeVarSlotSsa),
1876 SetVarSsaField(SetVarSsaField),
1877 SetVarAliasedField(SetVarSsaField),
1878 SetVarAliased(SetVarAliased),
1879 SetVarSsa(SetVarSsa),
1880 VarPhi(VarPhi),
1881 MemPhi(MemPhi),
1882 VarSplit(VarSplit),
1883 SetVarSplit(SetVarSplit),
1884 Assert(Assert),
1885 ForceVer(ForceVer),
1886 VarSplitSsa(VarSplitSsa),
1887 SetVarSplitSsa(SetVarSplitSsa),
1888 AssertSsa(AssertSsa),
1889 ForceVerSsa(ForceVerSsa),
1890 Add(BinaryOp),
1891 Sub(BinaryOp),
1892 And(BinaryOp),
1893 Or(BinaryOp),
1894 Xor(BinaryOp),
1895 Lsl(BinaryOp),
1896 Lsr(BinaryOp),
1897 Asr(BinaryOp),
1898 Rol(BinaryOp),
1899 Ror(BinaryOp),
1900 Mul(BinaryOp),
1901 MuluDp(BinaryOp),
1902 MulsDp(BinaryOp),
1903 Divu(BinaryOp),
1904 DivuDp(BinaryOp),
1905 Divs(BinaryOp),
1906 DivsDp(BinaryOp),
1907 Modu(BinaryOp),
1908 ModuDp(BinaryOp),
1909 Mods(BinaryOp),
1910 ModsDp(BinaryOp),
1911 MinSigned(BinaryOp),
1912 MaxSigned(BinaryOp),
1913 MinUnsigned(BinaryOp),
1914 MaxUnsigned(BinaryOp),
1915 CmpE(BinaryOp),
1916 CmpNe(BinaryOp),
1917 CmpSlt(BinaryOp),
1918 CmpUlt(BinaryOp),
1919 CmpSle(BinaryOp),
1920 CmpUle(BinaryOp),
1921 CmpSge(BinaryOp),
1922 CmpUge(BinaryOp),
1923 CmpSgt(BinaryOp),
1924 CmpUgt(BinaryOp),
1925 TestBit(BinaryOp),
1926 AddOverflow(BinaryOp),
1927 FcmpE(BinaryOp),
1928 FcmpNe(BinaryOp),
1929 FcmpLt(BinaryOp),
1930 FcmpLe(BinaryOp),
1931 FcmpGe(BinaryOp),
1932 FcmpGt(BinaryOp),
1933 FcmpO(BinaryOp),
1934 FcmpUo(BinaryOp),
1935 Fadd(BinaryOp),
1936 Fsub(BinaryOp),
1937 Fmul(BinaryOp),
1938 Fdiv(BinaryOp),
1939 Adc(BinaryOpCarry),
1940 Sbb(BinaryOpCarry),
1941 Rlc(BinaryOpCarry),
1942 Rrc(BinaryOpCarry),
1943 Call(Call),
1944 CallParam(CallParam),
1945 CallOutputSsa(CallOutputSsa),
1946 CallParamSsa(CallParamSsa),
1947 Tailcall(Call),
1948 Syscall(Syscall),
1949 Intrinsic(Intrinsic),
1950 IntrinsicSsa(IntrinsicSsa),
1951 MemoryIntrinsicSsa(MemoryIntrinsicSsa),
1952 MemoryIntrinsicOutputSsa(MemoryIntrinsicOutputSsa),
1953 CallSsa(CallSsa),
1954 TailcallSsa(CallSsa),
1955 CallUntypedSsa(CallUntypedSsa),
1956 TailcallUntypedSsa(CallUntypedSsa),
1957 SyscallSsa(SyscallSsa),
1958 SyscallUntypedSsa(SyscallUntypedSsa),
1959 CallUntyped(CallUntyped),
1960 TailcallUntyped(CallUntyped),
1961 SyscallUntyped(SyscallUntyped),
1962 SeparateParamList(SeparateParamList),
1963 SharedParamSlot(SharedParamSlot),
1964 VarOutput(VarOutput),
1965 VarOutputField(VarOutputField),
1966 StoreOutput(StoreOutput),
1967 Neg(UnaryOp),
1968 Not(UnaryOp),
1969 Bswap(UnaryOp),
1970 Popcnt(UnaryOp),
1971 Clz(UnaryOp),
1972 Ctz(UnaryOp),
1973 Rbit(UnaryOp),
1974 Cls(UnaryOp),
1975 Abs(UnaryOp),
1976 Sx(UnaryOp),
1977 Zx(UnaryOp),
1978 LowPart(UnaryOp),
1979 BoolToInt(UnaryOp),
1980 UnimplMem(UnaryOp),
1981 Fsqrt(UnaryOp),
1982 Fneg(UnaryOp),
1983 Fabs(UnaryOp),
1984 FloatToInt(UnaryOp),
1985 IntToFloat(UnaryOp),
1986 FloatConv(UnaryOp),
1987 RoundToInt(UnaryOp),
1988 Floor(UnaryOp),
1989 Ceil(UnaryOp),
1990 Ftrunc(UnaryOp),
1991 Load(UnaryOp),
1992 LoadStruct(LoadStruct),
1993 LoadStructSsa(LoadStructSsa),
1994 LoadSsa(LoadSsa),
1995 Ret(Ret),
1996 Var(Var),
1997 AddressOf(Var),
1998 PassByRef(UnaryOp),
1999 ReturnByRef(UnaryOp),
2000 VarField(Field),
2001 AddressOfField(Field),
2002 VarSsa(VarSsa),
2003 VarAliased(VarSsa),
2004 VarSsaField(VarSsaField),
2005 VarAliasedField(VarSsaField),
2006 VarOutputSsa(VarOutputSsa),
2007 VarOutputSsaField(VarOutputSsaField),
2008 VarOutputAliased(VarOutputAliased),
2009 VarOutputAliasedField(VarOutputAliasedField),
2010 Trap(Trap),
2011 BlockToExpand(BlockToExpand),
2012}
2013
2014fn get_float(value: u64, size: usize) -> f64 {
2015 match size {
2016 4 => f32::from_bits(value as u32) as f64,
2017 8 => f64::from_bits(value),
2018 size => todo!("float size {}", size),
2020 }
2021}
2022
2023fn get_var(id: u64) -> Variable {
2024 Variable::from_identifier(id)
2025}
2026
2027fn get_var_ssa(id: u64, version: usize) -> SSAVariable {
2028 SSAVariable::new(get_var(id), version)
2029}
2030
2031fn get_call_params(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> {
2032 match instr.kind {
2033 MediumLevelILInstructionKind::CallParam(_op) => instr.get_expr_list(0),
2034 _ => vec![],
2035 }
2036}
2037
2038fn get_call_output_ssa(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> {
2039 match instr.kind {
2040 MediumLevelILInstructionKind::CallOutputSsa(_op) => instr.get_expr_list(1),
2041 _ => vec![],
2042 }
2043}
2044
2045fn get_call_params_ssa(instr: &MediumLevelILInstruction) -> Vec<MediumLevelILInstruction> {
2046 match instr.kind {
2047 MediumLevelILInstructionKind::CallParamSsa(_op) => instr.get_expr_list(1),
2048 _ => vec![],
2049 }
2050}
2051
2052pub struct BranchDependence {
2054 pub instruction: MediumLevelILInstruction,
2055 pub dependence: ILBranchDependence,
2056}
2057
2058impl CoreArrayProvider for BranchDependence {
2059 type Raw = BNILBranchInstructionAndDependence;
2060 type Context = Ref<MediumLevelILFunction>;
2061 type Wrapped<'a> = Self;
2062}
2063
2064unsafe impl CoreArrayProviderInner for BranchDependence {
2065 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2066 unsafe { BNFreeILBranchDependenceList(raw) };
2067 }
2068
2069 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
2070 Self {
2071 instruction: MediumLevelILInstruction::from_instr_index(
2072 context.clone(),
2073 MediumLevelInstructionIndex(raw.branch),
2074 ),
2075 dependence: raw.dependence,
2076 }
2077 }
2078}