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