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