1use std::marker::PhantomData;
16
17use binaryninjacore_sys::{BNAddLowLevelILLabelForAddress, BNLowLevelILOperation};
18use binaryninjacore_sys::{BNLowLevelILLabel, BNRegisterOrConstant};
19
20use super::*;
21use crate::architecture::{Architecture, FlagWriteId, RegisterId};
22use crate::architecture::{CoreRegister, Register as ArchReg};
23use crate::architecture::{
24 Flag, FlagClass, FlagCondition, FlagGroup, FlagRole, FlagWrite, Intrinsic,
25};
26use crate::function::Location;
27
28pub trait LiftableLowLevelIL<'func> {
29 type Result: ExpressionResultType;
30
31 fn lift(
32 il: &'func LowLevelILMutableFunction,
33 expr: Self,
34 ) -> LowLevelILMutableExpression<'func, Self::Result>;
35}
36
37pub trait LiftableLowLevelILWithSize<'func>: LiftableLowLevelIL<'func, Result = ValueExpr> {
38 fn lift_with_size(
39 il: &'func LowLevelILMutableFunction,
40 expr: Self,
41 size: usize,
42 ) -> LowLevelILMutableExpression<'func, ValueExpr>;
43}
44
45#[derive(Copy, Clone)]
46pub enum LowLevelILRegisterOrConstant<R: ArchReg> {
47 Register(usize, LowLevelILRegisterKind<R>),
48 Constant(usize, u64),
49}
50
51impl<R: ArchReg> From<LowLevelILRegisterOrConstant<R>> for BNRegisterOrConstant {
52 fn from(value: LowLevelILRegisterOrConstant<R>) -> Self {
53 match value {
54 LowLevelILRegisterOrConstant::Register(_, r) => Self {
55 constant: false,
56 reg: r.id().0,
57 value: 0,
58 },
59 LowLevelILRegisterOrConstant::Constant(_, value) => Self {
60 constant: true,
61 reg: 0,
62 value,
63 },
64 }
65 }
66}
67
68#[derive(Copy, Clone)]
70pub enum LowLevelILFlagWriteOp<R: ArchReg> {
71 SetReg(usize, LowLevelILRegisterOrConstant<R>),
72 SetRegSplit(
73 usize,
74 LowLevelILRegisterOrConstant<R>,
75 LowLevelILRegisterOrConstant<R>,
76 ),
77
78 Sub(
79 usize,
80 LowLevelILRegisterOrConstant<R>,
81 LowLevelILRegisterOrConstant<R>,
82 ),
83 Add(
84 usize,
85 LowLevelILRegisterOrConstant<R>,
86 LowLevelILRegisterOrConstant<R>,
87 ),
88
89 Load(usize, LowLevelILRegisterOrConstant<R>),
90
91 Push(usize, LowLevelILRegisterOrConstant<R>),
92 Neg(usize, LowLevelILRegisterOrConstant<R>),
93 Not(usize, LowLevelILRegisterOrConstant<R>),
94 Sx(usize, LowLevelILRegisterOrConstant<R>),
95 Zx(usize, LowLevelILRegisterOrConstant<R>),
96 LowPart(usize, LowLevelILRegisterOrConstant<R>),
97 BoolToInt(usize, LowLevelILRegisterOrConstant<R>),
98 FloatToInt(usize, LowLevelILRegisterOrConstant<R>),
99
100 Store(
101 usize,
102 LowLevelILRegisterOrConstant<R>,
103 LowLevelILRegisterOrConstant<R>,
104 ),
105
106 And(
107 usize,
108 LowLevelILRegisterOrConstant<R>,
109 LowLevelILRegisterOrConstant<R>,
110 ),
111 Or(
112 usize,
113 LowLevelILRegisterOrConstant<R>,
114 LowLevelILRegisterOrConstant<R>,
115 ),
116 Xor(
117 usize,
118 LowLevelILRegisterOrConstant<R>,
119 LowLevelILRegisterOrConstant<R>,
120 ),
121 Lsl(
122 usize,
123 LowLevelILRegisterOrConstant<R>,
124 LowLevelILRegisterOrConstant<R>,
125 ),
126 Lsr(
127 usize,
128 LowLevelILRegisterOrConstant<R>,
129 LowLevelILRegisterOrConstant<R>,
130 ),
131 Asr(
132 usize,
133 LowLevelILRegisterOrConstant<R>,
134 LowLevelILRegisterOrConstant<R>,
135 ),
136 Rol(
137 usize,
138 LowLevelILRegisterOrConstant<R>,
139 LowLevelILRegisterOrConstant<R>,
140 ),
141 Ror(
142 usize,
143 LowLevelILRegisterOrConstant<R>,
144 LowLevelILRegisterOrConstant<R>,
145 ),
146 Mul(
147 usize,
148 LowLevelILRegisterOrConstant<R>,
149 LowLevelILRegisterOrConstant<R>,
150 ),
151 MuluDp(
152 usize,
153 LowLevelILRegisterOrConstant<R>,
154 LowLevelILRegisterOrConstant<R>,
155 ),
156 MulsDp(
157 usize,
158 LowLevelILRegisterOrConstant<R>,
159 LowLevelILRegisterOrConstant<R>,
160 ),
161 Divu(
162 usize,
163 LowLevelILRegisterOrConstant<R>,
164 LowLevelILRegisterOrConstant<R>,
165 ),
166 Divs(
167 usize,
168 LowLevelILRegisterOrConstant<R>,
169 LowLevelILRegisterOrConstant<R>,
170 ),
171 Modu(
172 usize,
173 LowLevelILRegisterOrConstant<R>,
174 LowLevelILRegisterOrConstant<R>,
175 ),
176 Mods(
177 usize,
178 LowLevelILRegisterOrConstant<R>,
179 LowLevelILRegisterOrConstant<R>,
180 ),
181 DivuDp(
182 usize,
183 LowLevelILRegisterOrConstant<R>,
184 LowLevelILRegisterOrConstant<R>,
185 ),
186 DivsDp(
187 usize,
188 LowLevelILRegisterOrConstant<R>,
189 LowLevelILRegisterOrConstant<R>,
190 ),
191 ModuDp(
192 usize,
193 LowLevelILRegisterOrConstant<R>,
194 LowLevelILRegisterOrConstant<R>,
195 ),
196 ModsDp(
197 usize,
198 LowLevelILRegisterOrConstant<R>,
199 LowLevelILRegisterOrConstant<R>,
200 ),
201
202 TestBit(
203 usize,
204 LowLevelILRegisterOrConstant<R>,
205 LowLevelILRegisterOrConstant<R>,
206 ),
207 AddOverflow(
208 usize,
209 LowLevelILRegisterOrConstant<R>,
210 LowLevelILRegisterOrConstant<R>,
211 ),
212
213 Adc(
214 usize,
215 LowLevelILRegisterOrConstant<R>,
216 LowLevelILRegisterOrConstant<R>,
217 LowLevelILRegisterOrConstant<R>,
218 ),
219 Sbb(
220 usize,
221 LowLevelILRegisterOrConstant<R>,
222 LowLevelILRegisterOrConstant<R>,
223 LowLevelILRegisterOrConstant<R>,
224 ),
225 Rlc(
226 usize,
227 LowLevelILRegisterOrConstant<R>,
228 LowLevelILRegisterOrConstant<R>,
229 LowLevelILRegisterOrConstant<R>,
230 ),
231 Rrc(
232 usize,
233 LowLevelILRegisterOrConstant<R>,
234 LowLevelILRegisterOrConstant<R>,
235 LowLevelILRegisterOrConstant<R>,
236 ),
237
238 Pop(usize),
239 }
241
242impl<R: ArchReg> LowLevelILFlagWriteOp<R> {
243 pub(crate) fn from_op<A>(
244 arch: &A,
245 size: usize,
246 op: BNLowLevelILOperation,
247 operands: &[BNRegisterOrConstant],
248 ) -> Option<Self>
249 where
250 A: Architecture<Register = R>,
251 R: ArchReg<InfoType = A::RegisterInfo>,
252 {
253 use self::LowLevelILFlagWriteOp::*;
254 use binaryninjacore_sys::BNLowLevelILOperation::*;
255
256 fn build_op<A, R>(
257 arch: &A,
258 size: usize,
259 operand: &BNRegisterOrConstant,
260 ) -> LowLevelILRegisterOrConstant<R>
261 where
262 A: Architecture<Register = R>,
263 R: ArchReg<InfoType = A::RegisterInfo>,
264 {
265 if operand.constant {
266 LowLevelILRegisterOrConstant::Constant(size, operand.value)
267 } else {
268 let raw_id = RegisterId(operand.reg);
269 let il_reg =
270 LowLevelILRegisterKind::from_raw(arch, raw_id).expect("Bad register ID");
271 LowLevelILRegisterOrConstant::Register(size, il_reg)
272 }
273 }
274
275 macro_rules! op {
276 ($x:ident, $($ops:expr),*) => {
277 ( $x(size, $( build_op(arch, size, &operands[$ops]), )* ) )
278 };
279 }
280
281 Some(match (operands.len(), op) {
282 (1, LLIL_SET_REG) => op!(SetReg, 0),
283 (2, LLIL_SET_REG_SPLIT) => op!(SetRegSplit, 0, 1),
284
285 (2, LLIL_SUB) => op!(Sub, 0, 1),
286 (2, LLIL_ADD) => op!(Add, 0, 1),
287
288 (1, LLIL_LOAD) => op!(Load, 0),
289
290 (1, LLIL_PUSH) => op!(Push, 0),
291 (1, LLIL_NEG) => op!(Neg, 0),
292 (1, LLIL_NOT) => op!(Not, 0),
293 (1, LLIL_SX) => op!(Sx, 0),
294 (1, LLIL_ZX) => op!(Zx, 0),
295 (1, LLIL_LOW_PART) => op!(LowPart, 0),
296 (1, LLIL_BOOL_TO_INT) => op!(BoolToInt, 0),
297 (1, LLIL_FLOAT_TO_INT) => op!(FloatToInt, 0),
298
299 (2, LLIL_STORE) => op!(Store, 0, 1),
300
301 (2, LLIL_AND) => op!(And, 0, 1),
302 (2, LLIL_OR) => op!(Or, 0, 1),
303 (2, LLIL_XOR) => op!(Xor, 0, 1),
304 (2, LLIL_LSL) => op!(Lsl, 0, 1),
305 (2, LLIL_LSR) => op!(Lsr, 0, 1),
306 (2, LLIL_ASR) => op!(Asr, 0, 1),
307 (2, LLIL_ROL) => op!(Rol, 0, 1),
308 (2, LLIL_ROR) => op!(Ror, 0, 1),
309 (2, LLIL_MUL) => op!(Mul, 0, 1),
310 (2, LLIL_MULU_DP) => op!(MuluDp, 0, 1),
311 (2, LLIL_MULS_DP) => op!(MulsDp, 0, 1),
312 (2, LLIL_DIVU) => op!(Divu, 0, 1),
313 (2, LLIL_DIVS) => op!(Divs, 0, 1),
314 (2, LLIL_MODU) => op!(Modu, 0, 1),
315 (2, LLIL_MODS) => op!(Mods, 0, 1),
316 (2, LLIL_DIVU_DP) => op!(DivuDp, 0, 1),
317 (2, LLIL_DIVS_DP) => op!(DivsDp, 0, 1),
318 (2, LLIL_MODU_DP) => op!(ModuDp, 0, 1),
319 (2, LLIL_MODS_DP) => op!(ModsDp, 0, 1),
320
321 (2, LLIL_TEST_BIT) => op!(TestBit, 0, 1),
322 (2, LLIL_ADD_OVERFLOW) => op!(AddOverflow, 0, 1),
323
324 (3, LLIL_ADC) => op!(Adc, 0, 1, 2),
325 (3, LLIL_SBB) => op!(Sbb, 0, 1, 2),
326 (3, LLIL_RLC) => op!(Rlc, 0, 1, 2),
327 (3, LLIL_RRC) => op!(Rrc, 0, 1, 2),
328
329 (0, LLIL_POP) => op!(Pop,),
330
331 _ => return None,
332 })
333 }
334
335 pub(crate) fn size_and_op(&self) -> (usize, BNLowLevelILOperation) {
336 use self::LowLevelILFlagWriteOp::*;
337 use binaryninjacore_sys::BNLowLevelILOperation::*;
338
339 match *self {
340 SetReg(size, ..) => (size, LLIL_SET_REG),
341 SetRegSplit(size, ..) => (size, LLIL_SET_REG_SPLIT),
342
343 Sub(size, ..) => (size, LLIL_SUB),
344 Add(size, ..) => (size, LLIL_ADD),
345
346 Load(size, ..) => (size, LLIL_LOAD),
347
348 Push(size, ..) => (size, LLIL_PUSH),
349 Neg(size, ..) => (size, LLIL_NEG),
350 Not(size, ..) => (size, LLIL_NOT),
351 Sx(size, ..) => (size, LLIL_SX),
352 Zx(size, ..) => (size, LLIL_ZX),
353 LowPart(size, ..) => (size, LLIL_LOW_PART),
354 BoolToInt(size, ..) => (size, LLIL_BOOL_TO_INT),
355 FloatToInt(size, ..) => (size, LLIL_FLOAT_TO_INT),
356
357 Store(size, ..) => (size, LLIL_STORE),
358
359 And(size, ..) => (size, LLIL_AND),
360 Or(size, ..) => (size, LLIL_OR),
361 Xor(size, ..) => (size, LLIL_XOR),
362 Lsl(size, ..) => (size, LLIL_LSL),
363 Lsr(size, ..) => (size, LLIL_LSR),
364 Asr(size, ..) => (size, LLIL_ASR),
365 Rol(size, ..) => (size, LLIL_ROL),
366 Ror(size, ..) => (size, LLIL_ROR),
367 Mul(size, ..) => (size, LLIL_MUL),
368 MuluDp(size, ..) => (size, LLIL_MULU_DP),
369 MulsDp(size, ..) => (size, LLIL_MULS_DP),
370 Divu(size, ..) => (size, LLIL_DIVU),
371 Divs(size, ..) => (size, LLIL_DIVS),
372 Modu(size, ..) => (size, LLIL_MODU),
373 Mods(size, ..) => (size, LLIL_MODS),
374 DivuDp(size, ..) => (size, LLIL_DIVU_DP),
375 DivsDp(size, ..) => (size, LLIL_DIVS_DP),
376 ModuDp(size, ..) => (size, LLIL_MODU_DP),
377 ModsDp(size, ..) => (size, LLIL_MODS_DP),
378
379 TestBit(size, ..) => (size, LLIL_TEST_BIT),
380 AddOverflow(size, ..) => (size, LLIL_ADD_OVERFLOW),
381
382 Adc(size, ..) => (size, LLIL_ADC),
383 Sbb(size, ..) => (size, LLIL_SBB),
384 Rlc(size, ..) => (size, LLIL_RLC),
385 Rrc(size, ..) => (size, LLIL_RRC),
386
387 Pop(size) => (size, LLIL_POP),
388 }
389 }
390
391 pub(crate) fn raw_operands(&self) -> (usize, [BNRegisterOrConstant; 5]) {
392 use self::LowLevelILFlagWriteOp::*;
393
394 let mut operands: [BNRegisterOrConstant; 5] = [BNRegisterOrConstant::default(); 5];
395
396 let count = match *self {
397 Pop(_) => 0,
398
399 SetReg(_, op0)
400 | Load(_, op0)
401 | Push(_, op0)
402 | Neg(_, op0)
403 | Not(_, op0)
404 | Sx(_, op0)
405 | Zx(_, op0)
406 | LowPart(_, op0)
407 | BoolToInt(_, op0)
408 | FloatToInt(_, op0) => {
409 operands[0] = op0.into();
410 1
411 }
412
413 SetRegSplit(_, op0, op1)
414 | Sub(_, op0, op1)
415 | Add(_, op0, op1)
416 | Store(_, op0, op1)
417 | And(_, op0, op1)
418 | Or(_, op0, op1)
419 | Xor(_, op0, op1)
420 | Lsl(_, op0, op1)
421 | Lsr(_, op0, op1)
422 | Asr(_, op0, op1)
423 | Rol(_, op0, op1)
424 | Ror(_, op0, op1)
425 | Mul(_, op0, op1)
426 | MuluDp(_, op0, op1)
427 | MulsDp(_, op0, op1)
428 | Divu(_, op0, op1)
429 | Divs(_, op0, op1)
430 | Modu(_, op0, op1)
431 | Mods(_, op0, op1)
432 | DivuDp(_, op0, op1)
433 | DivsDp(_, op0, op1)
434 | ModuDp(_, op0, op1)
435 | ModsDp(_, op0, op1)
436 | TestBit(_, op0, op1)
437 | AddOverflow(_, op0, op1) => {
438 operands[0] = op0.into();
439 operands[1] = op1.into();
440 2
441 }
442
443 Adc(_, op0, op1, op2)
444 | Sbb(_, op0, op1, op2)
445 | Rlc(_, op0, op1, op2)
446 | Rrc(_, op0, op1, op2) => {
447 operands[0] = op0.into();
448 operands[1] = op1.into();
449 operands[2] = op2.into();
450 3
451 }
452 };
453
454 (count, operands)
455 }
456}
457
458pub fn get_default_flag_write_llil<'func, A>(
459 arch: &A,
460 role: FlagRole,
461 op: LowLevelILFlagWriteOp<A::Register>,
462 il: &'func LowLevelILMutableFunction,
463) -> LowLevelILMutableExpression<'func, ValueExpr>
464where
465 A: 'func + Architecture,
466{
467 let (size, operation) = op.size_and_op();
468 let (count, operands) = op.raw_operands();
469
470 let expr_idx = unsafe {
471 use binaryninjacore_sys::BNGetDefaultArchitectureFlagWriteLowLevelIL;
472 BNGetDefaultArchitectureFlagWriteLowLevelIL(
473 arch.as_ref().handle,
474 operation,
475 size,
476 role,
477 operands.as_ptr() as *mut _,
478 count,
479 il.handle,
480 )
481 };
482
483 LowLevelILExpression::new(il, LowLevelExpressionIndex(expr_idx))
484}
485
486pub fn get_default_flag_cond_llil<'func, A>(
487 arch: &A,
488 cond: FlagCondition,
489 class: Option<A::FlagClass>,
490 il: &'func LowLevelILMutableFunction,
491) -> LowLevelILMutableExpression<'func, ValueExpr>
492where
493 A: 'func + Architecture,
494{
495 use binaryninjacore_sys::BNGetDefaultArchitectureFlagConditionLowLevelIL;
496 let class_id = class.map(|c| c.id().0).unwrap_or(0);
497
498 unsafe {
499 let expr_idx = BNGetDefaultArchitectureFlagConditionLowLevelIL(
500 arch.as_ref().handle,
501 cond,
502 class_id,
503 il.handle,
504 );
505
506 LowLevelILExpression::new(il, LowLevelExpressionIndex(expr_idx))
507 }
508}
509
510macro_rules! prim_int_lifter {
511 ($x:ty) => {
512 impl<'a> LiftableLowLevelIL<'a> for $x {
513 type Result = ValueExpr;
514
515 fn lift(il: &'a LowLevelILMutableFunction, val: Self)
516 -> LowLevelILMutableExpression<'a, Self::Result>
517 {
518 il.const_int(std::mem::size_of::<Self>(), val as i64 as u64)
519 }
520 }
521
522 impl<'a> LiftableLowLevelILWithSize<'a> for $x {
523 fn lift_with_size(il: &'a LowLevelILMutableFunction, val: Self, size: usize)
524 -> LowLevelILMutableExpression<'a, ValueExpr>
525 {
526 let raw = val as i64;
527
528 #[cfg(debug_assertions)]
529 {
530 let is_safe = match raw.overflowing_shr(size as u32 * 8) {
531 (_, true) => true,
532 (res, false) => [-1, 0].contains(&res),
533 };
534
535 if !is_safe {
536 log::error!("il @ {:x} attempted to lift constant 0x{:x} as {} byte expr (won't fit!)",
537 il.current_address(), val, size);
538 }
539 }
540
541 il.const_int(size, raw as u64)
542 }
543 }
544 }
545}
546
547prim_int_lifter!(i8);
548prim_int_lifter!(i16);
549prim_int_lifter!(i32);
550prim_int_lifter!(i64);
551
552prim_int_lifter!(u8);
553prim_int_lifter!(u16);
554prim_int_lifter!(u32);
555prim_int_lifter!(u64);
556
557impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILRegisterKind<R>
558where
559 R: LiftableLowLevelIL<'a, Result = ValueExpr> + Into<LowLevelILRegisterKind<R>> + ArchReg,
560{
561 type Result = ValueExpr;
562
563 fn lift(
564 il: &'a LowLevelILMutableFunction,
565 reg: Self,
566 ) -> LowLevelILMutableExpression<'a, Self::Result> {
567 match reg {
568 LowLevelILRegisterKind::Arch(r) => R::lift(il, r),
569 LowLevelILRegisterKind::Temp(t) => il.reg(
570 il.arch().default_integer_size(),
571 LowLevelILRegisterKind::Temp::<R>(t),
572 ),
573 }
574 }
575}
576
577impl<'a, R> LiftableLowLevelILWithSize<'a> for LowLevelILRegisterKind<R>
578where
579 R: LiftableLowLevelILWithSize<'a> + Into<LowLevelILRegisterKind<R>> + ArchReg,
580{
581 fn lift_with_size(
582 il: &'a LowLevelILMutableFunction,
583 reg: Self,
584 size: usize,
585 ) -> LowLevelILMutableExpression<'a, ValueExpr> {
586 match reg {
587 LowLevelILRegisterKind::Arch(r) => R::lift_with_size(il, r, size),
588 LowLevelILRegisterKind::Temp(t) => il.reg(size, LowLevelILRegisterKind::<R>::Temp(t)),
589 }
590 }
591}
592
593impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILRegisterOrConstant<R>
594where
595 R: LiftableLowLevelILWithSize<'a, Result = ValueExpr>
596 + Into<LowLevelILRegisterKind<R>>
597 + ArchReg,
598{
599 type Result = ValueExpr;
600
601 fn lift(
602 il: &'a LowLevelILMutableFunction,
603 reg: Self,
604 ) -> LowLevelILMutableExpression<'a, Self::Result> {
605 match reg {
606 LowLevelILRegisterOrConstant::Register(size, r) => {
607 LowLevelILRegisterKind::<R>::lift_with_size(il, r, size)
608 }
609 LowLevelILRegisterOrConstant::Constant(size, value) => {
610 u64::lift_with_size(il, value, size)
611 }
612 }
613 }
614}
615
616impl<'a, R> LiftableLowLevelILWithSize<'a> for LowLevelILRegisterOrConstant<R>
617where
618 R: LiftableLowLevelILWithSize<'a> + Into<LowLevelILRegisterKind<R>> + ArchReg,
619{
620 fn lift_with_size(
621 il: &'a LowLevelILMutableFunction,
622 reg: Self,
623 size: usize,
624 ) -> LowLevelILMutableExpression<'a, ValueExpr> {
625 match reg {
627 LowLevelILRegisterOrConstant::Register(_, r) => {
628 LowLevelILRegisterKind::<R>::lift_with_size(il, r, size)
629 }
630 LowLevelILRegisterOrConstant::Constant(_, value) => {
631 u64::lift_with_size(il, value, size)
632 }
633 }
634 }
635}
636
637impl<'a, R> LiftableLowLevelIL<'a> for LowLevelILExpression<'a, Mutable, NonSSA, R>
638where
639 R: ExpressionResultType,
640{
641 type Result = R;
642
643 fn lift(
644 il: &'a LowLevelILMutableFunction,
645 expr: Self,
646 ) -> LowLevelILMutableExpression<'a, Self::Result> {
647 debug_assert!(expr.function.handle == il.handle);
648 expr
649 }
650}
651
652impl<'a> LiftableLowLevelILWithSize<'a> for LowLevelILExpression<'a, Mutable, NonSSA, ValueExpr> {
653 fn lift_with_size(
654 il: &'a LowLevelILMutableFunction,
655 expr: Self,
656 _size: usize,
657 ) -> LowLevelILMutableExpression<'a, Self::Result> {
658 #[cfg(debug_assertions)]
659 {
660 use crate::low_level_il::ExpressionHandler;
661 if let Some(expr_size) = expr.kind().size() {
662 if expr_size != _size {
663 log::warn!(
664 "il @ {:x} attempted to lift {} byte expression as {} bytes",
665 il.current_address(),
666 expr_size,
667 _size
668 );
669 }
670 }
671 }
672
673 LiftableLowLevelIL::lift(il, expr)
674 }
675}
676
677impl<R> LowLevelILExpression<'_, Mutable, NonSSA, R>
678where
679 R: ExpressionResultType,
680{
681 pub fn with_source_operand(self, op: u32) -> Self {
682 use binaryninjacore_sys::BNLowLevelILSetExprSourceOperand;
683 unsafe { BNLowLevelILSetExprSourceOperand(self.function.handle, self.index.0, op) }
684 self
685 }
686
687 pub fn append(self) {
688 self.function.add_instruction(self);
689 }
690}
691
692pub struct ExpressionBuilder<'func, R>
693where
694 R: ExpressionResultType,
695{
696 function: &'func LowLevelILFunction<Mutable, NonSSA>,
697 op: BNLowLevelILOperation,
698 size: usize,
699 flag_write: FlagWriteId,
700 op1: u64,
701 op2: u64,
702 op3: u64,
703 op4: u64,
704 _ty: PhantomData<R>,
705}
706
707impl<'a, R> ExpressionBuilder<'a, R>
708where
709 R: ExpressionResultType,
710{
711 pub fn from_expr(expr: LowLevelILExpression<'a, Mutable, NonSSA, R>) -> Self {
712 use binaryninjacore_sys::BNGetLowLevelILByIndex;
713
714 let instr = unsafe { BNGetLowLevelILByIndex(expr.function.handle, expr.index.0) };
715
716 ExpressionBuilder {
717 function: expr.function,
718 op: instr.operation,
719 size: instr.size,
720 flag_write: FlagWriteId(instr.flags),
721 op1: instr.operands[0],
722 op2: instr.operands[1],
723 op3: instr.operands[2],
724 op4: instr.operands[3],
725 _ty: PhantomData,
726 }
727 }
728
729 pub fn with_flag_write(mut self, flag_write: impl FlagWrite) -> Self {
730 self.flag_write = flag_write.id();
732 self
733 }
734
735 pub fn build(self) -> LowLevelILExpression<'a, Mutable, NonSSA, R> {
736 use binaryninjacore_sys::BNLowLevelILAddExpr;
737
738 let expr_idx = unsafe {
739 BNLowLevelILAddExpr(
740 self.function.handle,
741 self.op,
742 self.size,
743 self.flag_write.0,
744 self.op1,
745 self.op2,
746 self.op3,
747 self.op4,
748 )
749 };
750
751 LowLevelILExpression::new(self.function, LowLevelExpressionIndex(expr_idx))
752 }
753
754 pub fn with_source_operand(self, op: u32) -> LowLevelILExpression<'a, Mutable, NonSSA, R> {
755 self.build().with_source_operand(op)
756 }
757
758 pub fn append(self) {
759 let expr = self.build();
760 expr.function.add_instruction(expr);
761 }
762}
763
764impl<'a, R> LiftableLowLevelIL<'a> for ExpressionBuilder<'a, R>
765where
766 R: ExpressionResultType,
767{
768 type Result = R;
769
770 fn lift(
771 il: &'a LowLevelILMutableFunction,
772 expr: Self,
773 ) -> LowLevelILMutableExpression<'a, Self::Result> {
774 debug_assert!(expr.function.handle == il.handle);
775
776 expr.build()
777 }
778}
779
780impl<'a> LiftableLowLevelILWithSize<'a> for ExpressionBuilder<'a, ValueExpr> {
781 fn lift_with_size(
782 il: &'a LowLevelILMutableFunction,
783 expr: Self,
784 _size: usize,
785 ) -> LowLevelILMutableExpression<'a, ValueExpr> {
786 #[cfg(debug_assertions)]
787 {
788 use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_UNIMPL, LLIL_UNIMPL_MEM};
789
790 if expr.size != _size && ![LLIL_UNIMPL, LLIL_UNIMPL_MEM].contains(&expr.op) {
791 log::warn!(
792 "il @ {:x} attempted to lift {} byte expression builder as {} bytes",
793 il.current_address(),
794 expr.size,
795 _size
796 );
797 }
798 }
799
800 LiftableLowLevelIL::lift(il, expr)
801 }
802}
803
804macro_rules! no_arg_lifter {
805 ($name:ident, $op:ident, $result:ty) => {
806 pub fn $name(&self) -> LowLevelILExpression<'_, Mutable, NonSSA, $result> {
807 use binaryninjacore_sys::BNLowLevelILAddExpr;
808 use binaryninjacore_sys::BNLowLevelILOperation::$op;
809
810 let expr_idx = unsafe { BNLowLevelILAddExpr(self.handle, $op, 0, 0, 0, 0, 0, 0) };
811
812 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
813 }
814 };
815}
816
817macro_rules! sized_no_arg_lifter {
818 ($name:ident, $op:ident, $result:ty) => {
819 pub fn $name(&self, size: usize) -> ExpressionBuilder<'_, $result> {
820 use binaryninjacore_sys::BNLowLevelILOperation::$op;
821
822 ExpressionBuilder {
823 function: self,
824 op: $op,
825 size,
826 flag_write: FlagWriteId(0),
827 op1: 0,
828 op2: 0,
829 op3: 0,
830 op4: 0,
831 _ty: PhantomData,
832 }
833 }
834 };
835}
836
837macro_rules! unsized_unary_op_lifter {
838 ($name:ident, $op:ident, $result:ty) => {
839 pub fn $name<'a, E>(&'a self, expr: E) -> LowLevelILExpression<'a, Mutable, NonSSA, $result>
840 where
841 E: LiftableLowLevelIL<'a, Result = ValueExpr>,
842 {
843 use binaryninjacore_sys::BNLowLevelILAddExpr;
844 use binaryninjacore_sys::BNLowLevelILOperation::$op;
845
846 let expr = E::lift(self, expr);
847
848 let expr_idx = unsafe {
849 BNLowLevelILAddExpr(self.handle, $op, 0, 0, expr.index.0 as u64, 0, 0, 0)
850 };
851
852 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
853 }
854 };
855}
856
857macro_rules! sized_unary_op_lifter {
858 ($name:ident, $op:ident, $result:ty) => {
859 pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, $result>
860 where
861 E: LiftableLowLevelILWithSize<'a>,
862 {
863 use binaryninjacore_sys::BNLowLevelILOperation::$op;
864
865 let expr = E::lift_with_size(self, expr, size);
866
867 ExpressionBuilder {
868 function: self,
869 op: $op,
870 size,
871 flag_write: FlagWriteId(0),
872 op1: expr.index.0 as u64,
873 op2: 0,
874 op3: 0,
875 op4: 0,
876 _ty: PhantomData,
877 }
878 }
879 };
880}
881
882macro_rules! size_changing_unary_op_lifter {
883 ($name:ident, $op:ident, $result:ty) => {
884 pub fn $name<'a, E>(&'a self, size: usize, expr: E) -> ExpressionBuilder<'a, $result>
885 where
886 E: LiftableLowLevelILWithSize<'a>,
887 {
888 use binaryninjacore_sys::BNLowLevelILOperation::$op;
889
890 let expr = E::lift(self, expr);
891
892 ExpressionBuilder {
893 function: self,
894 op: $op,
895 size,
896 flag_write: FlagWriteId(0),
897 op1: expr.index.0 as u64,
898 op2: 0,
899 op3: 0,
900 op4: 0,
901 _ty: PhantomData,
902 }
903 }
904 };
905}
906
907macro_rules! binary_op_lifter {
908 ($name:ident, $op:ident) => {
909 pub fn $name<'a, L, R>(
910 &'a self,
911 size: usize,
912 left: L,
913 right: R,
914 ) -> ExpressionBuilder<'a, ValueExpr>
915 where
916 L: LiftableLowLevelILWithSize<'a>,
917 R: LiftableLowLevelILWithSize<'a>,
918 {
919 use binaryninjacore_sys::BNLowLevelILOperation::$op;
920
921 let left = L::lift_with_size(self, left, size);
922 let right = R::lift_with_size(self, right, size);
923
924 ExpressionBuilder {
925 function: self,
926 op: $op,
927 size,
928 flag_write: FlagWriteId(0),
929 op1: left.index.0 as u64,
930 op2: right.index.0 as u64,
931 op3: 0,
932 op4: 0,
933 _ty: PhantomData,
934 }
935 }
936 };
937}
938
939macro_rules! binary_op_carry_lifter {
940 ($name:ident, $op:ident) => {
941 pub fn $name<'a, L, R, C>(
942 &'a self,
943 size: usize,
944 left: L,
945 right: R,
946 carry: C,
947 ) -> ExpressionBuilder<'a, ValueExpr>
948 where
949 L: LiftableLowLevelILWithSize<'a>,
950 R: LiftableLowLevelILWithSize<'a>,
951 C: LiftableLowLevelILWithSize<'a>,
952 {
953 use binaryninjacore_sys::BNLowLevelILOperation::$op;
954
955 let left = L::lift_with_size(self, left, size);
956 let right = R::lift_with_size(self, right, size);
957 let carry = C::lift_with_size(self, carry, 0);
958
959 ExpressionBuilder {
960 function: self,
961 op: $op,
962 size,
963 flag_write: FlagWriteId(0),
964 op1: left.index.0 as u64,
965 op2: right.index.0 as u64,
966 op3: carry.index.0 as u64,
967 op4: 0,
968 _ty: PhantomData,
969 }
970 }
971 };
972}
973
974impl LowLevelILMutableFunction {
975 pub const NO_INPUTS: [ExpressionBuilder<'static, ValueExpr>; 0] = [];
976 pub const NO_OUTPUTS: [LowLevelILRegisterKind<CoreRegister>; 0] = [];
977
978 pub fn expression<'a, E: LiftableLowLevelIL<'a>>(
979 &'a self,
980 expr: E,
981 ) -> LowLevelILExpression<'a, Mutable, NonSSA, E::Result> {
982 E::lift(self, expr)
983 }
984
985 pub fn add_instruction<'a, E: LiftableLowLevelIL<'a>>(&'a self, expr: E) {
986 let expr = self.expression(expr);
987
988 unsafe {
989 use binaryninjacore_sys::BNLowLevelILAddInstruction;
990 BNLowLevelILAddInstruction(self.handle, expr.index.0);
991 }
992 }
993
994 pub unsafe fn replace_expression<'a, E: LiftableLowLevelIL<'a>>(
995 &'a self,
996 replaced_expr_index: LowLevelExpressionIndex,
997 replacement: E,
998 ) -> bool {
999 use binaryninjacore_sys::BNReplaceLowLevelILExpr;
1000 if replaced_expr_index.0 >= self.expression_count() {
1001 return false;
1003 }
1004 let expr = self.expression(replacement);
1005 BNReplaceLowLevelILExpr(self.handle, replaced_expr_index.0, expr.index.0);
1006 true
1007 }
1008
1009 pub fn const_int(&self, size: usize, val: u64) -> LowLevelILMutableExpression<'_, ValueExpr> {
1010 use binaryninjacore_sys::BNLowLevelILAddExpr;
1011 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST;
1012
1013 let expr_idx =
1014 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_CONST, size, 0, val, 0, 0, 0) };
1015
1016 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1017 }
1018
1019 pub fn const_ptr_sized(
1020 &self,
1021 size: usize,
1022 val: u64,
1023 ) -> LowLevelILMutableExpression<'_, ValueExpr> {
1024 use binaryninjacore_sys::BNLowLevelILAddExpr;
1025 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CONST_PTR;
1026
1027 let expr_idx =
1028 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_CONST_PTR, size, 0, val, 0, 0, 0) };
1029
1030 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1031 }
1032
1033 pub fn const_ptr(&self, val: u64) -> LowLevelILMutableExpression<'_, ValueExpr> {
1034 self.const_ptr_sized(self.arch().address_size(), val)
1035 }
1036
1037 pub fn trap(&self, val: u64) -> LowLevelILExpression<'_, Mutable, NonSSA, VoidExpr> {
1038 use binaryninjacore_sys::BNLowLevelILAddExpr;
1039 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_TRAP;
1040
1041 let expr_idx = unsafe { BNLowLevelILAddExpr(self.handle, LLIL_TRAP, 0, 0, val, 0, 0, 0) };
1042
1043 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1044 }
1045
1046 no_arg_lifter!(unimplemented, LLIL_UNIMPL, ValueExpr);
1047 no_arg_lifter!(undefined, LLIL_UNDEF, ValueExpr);
1048 no_arg_lifter!(nop, LLIL_NOP, VoidExpr);
1049
1050 no_arg_lifter!(no_ret, LLIL_NORET, VoidExpr);
1051 no_arg_lifter!(syscall, LLIL_SYSCALL, VoidExpr);
1052 no_arg_lifter!(bp, LLIL_BP, VoidExpr);
1053
1054 unsized_unary_op_lifter!(call, LLIL_CALL, VoidExpr);
1055 unsized_unary_op_lifter!(tailcall, LLIL_TAILCALL, VoidExpr);
1056 unsized_unary_op_lifter!(ret, LLIL_RET, VoidExpr);
1057 unsized_unary_op_lifter!(jump, LLIL_JUMP, VoidExpr);
1058 pub fn if_expr<'a: 'b, 'b, C>(
1061 &'a self,
1062 cond: C,
1063 true_label: &'b mut LowLevelILLabel,
1064 false_label: &'b mut LowLevelILLabel,
1065 ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr>
1066 where
1067 C: LiftableLowLevelIL<'b, Result = ValueExpr>,
1068 {
1069 use binaryninjacore_sys::BNLowLevelILIf;
1070
1071 let cond = C::lift(self, cond);
1072
1073 let mut raw_true_label = BNLowLevelILLabel::from(*true_label);
1074 let mut raw_false_label = BNLowLevelILLabel::from(*false_label);
1075 let expr_idx = unsafe {
1076 BNLowLevelILIf(
1077 self.handle,
1078 cond.index.0 as u64,
1079 &mut raw_true_label,
1080 &mut raw_false_label,
1081 )
1082 };
1083
1084 let mut new_true_label = LowLevelILLabel::from(raw_true_label);
1086 let mut new_false_label = LowLevelILLabel::from(raw_false_label);
1087 if let Some(location) = true_label.location {
1088 new_true_label.location = Some(location);
1089 self.update_label_map_for_label(&new_true_label);
1090 }
1091 if let Some(location) = false_label.location {
1092 new_false_label.location = Some(location);
1093 self.update_label_map_for_label(&new_false_label);
1094 }
1095 *true_label = new_true_label;
1096 *false_label = new_false_label;
1097
1098 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1099 }
1100
1101 pub fn goto<'a: 'b, 'b>(
1103 &'a self,
1104 label: &'b mut LowLevelILLabel,
1105 ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr> {
1106 use binaryninjacore_sys::BNLowLevelILGoto;
1107
1108 let mut raw_label = BNLowLevelILLabel::from(*label);
1109 let expr_idx = unsafe { BNLowLevelILGoto(self.handle, &mut raw_label) };
1110
1111 let mut new_label = LowLevelILLabel::from(raw_label);
1113 if let Some(location) = label.location {
1114 new_label.location = Some(location);
1115 self.update_label_map_for_label(&new_label);
1116 }
1117 *label = new_label;
1118
1119 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1120 }
1121
1122 pub fn reg<R: ArchReg, LR: Into<LowLevelILRegisterKind<R>>>(
1123 &self,
1124 size: usize,
1125 reg: LR,
1126 ) -> LowLevelILMutableExpression<'_, ValueExpr> {
1127 use binaryninjacore_sys::BNLowLevelILAddExpr;
1128 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG;
1129
1130 let reg = reg.into().id();
1132
1133 let expr_idx =
1134 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_REG, size, 0, reg.0 as u64, 0, 0, 0) };
1135
1136 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1137 }
1138
1139 pub fn reg_split<R: ArchReg, LR: Into<LowLevelILRegisterKind<R>>>(
1140 &self,
1141 size: usize,
1142 hi_reg: LR,
1143 lo_reg: LR,
1144 ) -> LowLevelILMutableExpression<'_, ValueExpr> {
1145 use binaryninjacore_sys::BNLowLevelILAddExpr;
1146 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT;
1147
1148 let hi_reg = hi_reg.into().id();
1150 let lo_reg = lo_reg.into().id();
1151
1152 let expr_idx = unsafe {
1153 BNLowLevelILAddExpr(
1154 self.handle,
1155 LLIL_REG_SPLIT,
1156 size,
1157 0,
1158 hi_reg.0 as u64,
1159 lo_reg.0 as u64,
1160 0,
1161 0,
1162 )
1163 };
1164
1165 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1166 }
1167
1168 pub fn set_reg<'a, R, LR, E>(
1169 &'a self,
1170 size: usize,
1171 dest_reg: LR,
1172 expr: E,
1173 ) -> ExpressionBuilder<'a, VoidExpr>
1174 where
1175 R: ArchReg,
1176 LR: Into<LowLevelILRegisterKind<R>>,
1177 E: LiftableLowLevelILWithSize<'a>,
1178 {
1179 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG;
1180
1181 let dest_reg = dest_reg.into().id();
1183
1184 let expr = E::lift_with_size(self, expr, size);
1185
1186 ExpressionBuilder {
1187 function: self,
1188 op: LLIL_SET_REG,
1189 size,
1190 flag_write: FlagWriteId(0),
1192 op1: dest_reg.0 as u64,
1193 op2: expr.index.0 as u64,
1194 op3: 0,
1195 op4: 0,
1196 _ty: PhantomData,
1197 }
1198 }
1199
1200 pub fn set_reg_split<'a, R, LR, E>(
1201 &'a self,
1202 size: usize,
1203 hi_reg: LR,
1204 lo_reg: LR,
1205 expr: E,
1206 ) -> ExpressionBuilder<'a, VoidExpr>
1207 where
1208 R: ArchReg,
1209 LR: Into<LowLevelILRegisterKind<R>>,
1210 E: LiftableLowLevelILWithSize<'a>,
1211 {
1212 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG_SPLIT;
1213
1214 let hi_reg = hi_reg.into().id();
1216 let lo_reg = lo_reg.into().id();
1217
1218 let expr = E::lift_with_size(self, expr, size);
1219
1220 ExpressionBuilder {
1221 function: self,
1222 op: LLIL_SET_REG_SPLIT,
1223 size,
1224 flag_write: FlagWriteId(0),
1225 op1: hi_reg.0 as u64,
1226 op2: lo_reg.0 as u64,
1227 op3: expr.index.0 as u64,
1228 op4: 0,
1229 _ty: PhantomData,
1230 }
1231 }
1232
1233 pub fn flag(&self, flag: impl Flag) -> LowLevelILMutableExpression<'_, ValueExpr> {
1234 use binaryninjacore_sys::BNLowLevelILAddExpr;
1235 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG;
1236
1237 let expr_idx = unsafe {
1239 BNLowLevelILAddExpr(self.handle, LLIL_FLAG, 0, 0, flag.id().0 as u64, 0, 0, 0)
1240 };
1241
1242 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1243 }
1244
1245 pub fn flag_cond(&self, cond: FlagCondition) -> LowLevelILMutableExpression<'_, ValueExpr> {
1246 use binaryninjacore_sys::BNLowLevelILAddExpr;
1247 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_COND;
1248
1249 let expr_idx =
1251 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_FLAG_COND, 0, 0, cond as u64, 0, 0, 0) };
1252
1253 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1254 }
1255
1256 pub fn flag_group(&self, group: impl FlagGroup) -> LowLevelILMutableExpression<'_, ValueExpr> {
1257 use binaryninjacore_sys::BNLowLevelILAddExpr;
1258 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_GROUP;
1259
1260 let expr_idx = unsafe {
1262 BNLowLevelILAddExpr(
1263 self.handle,
1264 LLIL_FLAG_GROUP,
1265 0,
1266 0,
1267 group.id().0 as u64,
1268 0,
1269 0,
1270 0,
1271 )
1272 };
1273
1274 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1275 }
1276
1277 pub fn set_flag<'a, E>(
1278 &'a self,
1279 dest_flag: impl Flag,
1280 expr: E,
1281 ) -> ExpressionBuilder<'a, VoidExpr>
1282 where
1283 E: LiftableLowLevelILWithSize<'a>,
1284 {
1285 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_FLAG;
1286
1287 let expr = E::lift_with_size(self, expr, 0);
1290
1291 ExpressionBuilder {
1292 function: self,
1293 op: LLIL_SET_FLAG,
1294 size: 0,
1295 flag_write: FlagWriteId(0),
1296 op1: dest_flag.id().0 as u64,
1297 op2: expr.index.0 as u64,
1298 op3: 0,
1299 op4: 0,
1300 _ty: PhantomData,
1301 }
1302 }
1303
1304 pub fn load<'a, E>(&'a self, size: usize, source_mem: E) -> ExpressionBuilder<'a, ValueExpr>
1310 where
1311 E: LiftableLowLevelIL<'a, Result = ValueExpr>,
1312 {
1313 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_LOAD;
1314
1315 let expr = E::lift(self, source_mem);
1316
1317 ExpressionBuilder {
1318 function: self,
1319 op: LLIL_LOAD,
1320 size,
1321 flag_write: FlagWriteId(0),
1322 op1: expr.index.0 as u64,
1323 op2: 0,
1324 op3: 0,
1325 op4: 0,
1326 _ty: PhantomData,
1327 }
1328 }
1329
1330 pub fn store<'a, D, V>(
1331 &'a self,
1332 size: usize,
1333 dest_mem: D,
1334 value: V,
1335 ) -> ExpressionBuilder<'a, VoidExpr>
1336 where
1337 D: LiftableLowLevelIL<'a, Result = ValueExpr>,
1338 V: LiftableLowLevelILWithSize<'a>,
1339 {
1340 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_STORE;
1341
1342 let dest_mem = D::lift(self, dest_mem);
1343 let value = V::lift_with_size(self, value, size);
1344
1345 ExpressionBuilder {
1346 function: self,
1347 op: LLIL_STORE,
1348 size,
1349 flag_write: FlagWriteId(0),
1350 op1: dest_mem.index.0 as u64,
1351 op2: value.index.0 as u64,
1352 op3: 0,
1353 op4: 0,
1354 _ty: PhantomData,
1355 }
1356 }
1357
1358 pub fn intrinsic<'a, R, O, P>(
1360 &'a self,
1361 outputs: impl IntoIterator<Item = O>,
1362 intrinsic: impl Intrinsic,
1363 inputs: impl IntoIterator<Item = P>,
1364 ) -> ExpressionBuilder<'a, VoidExpr>
1365 where
1366 R: ArchReg,
1367 O: Into<LowLevelILRegisterKind<R>>,
1368 P: LiftableLowLevelIL<'a, Result = ValueExpr>,
1369 {
1370 use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_CALL_PARAM, LLIL_INTRINSIC};
1371 use binaryninjacore_sys::{BNLowLevelILAddExpr, BNLowLevelILAddOperandList};
1372
1373 let mut outputs: Vec<u64> = outputs
1374 .into_iter()
1375 .map(|output| output.into().id().0 as u64)
1376 .collect();
1377 let output_expr_idx =
1378 unsafe { BNLowLevelILAddOperandList(self.handle, outputs.as_mut_ptr(), outputs.len()) };
1379
1380 let mut inputs: Vec<u64> = inputs
1381 .into_iter()
1382 .map(|input| {
1383 let input = P::lift(self, input);
1384 input.index.0 as u64
1385 })
1386 .collect();
1387 let input_list_expr_idx =
1388 unsafe { BNLowLevelILAddOperandList(self.handle, inputs.as_mut_ptr(), inputs.len()) };
1389 let input_expr_idx = unsafe {
1390 BNLowLevelILAddExpr(
1391 self.handle,
1392 LLIL_CALL_PARAM,
1393 0,
1394 0,
1395 inputs.len() as u64,
1396 input_list_expr_idx as u64,
1397 0,
1398 0,
1399 )
1400 };
1401
1402 ExpressionBuilder {
1403 function: self,
1404 op: LLIL_INTRINSIC,
1405 size: 0,
1406 flag_write: FlagWriteId(0),
1407 op1: outputs.len() as u64,
1408 op2: output_expr_idx as u64,
1409 op3: intrinsic.id().0 as u64,
1410 op4: input_expr_idx as u64,
1411 _ty: PhantomData,
1412 }
1413 }
1414
1415 sized_unary_op_lifter!(push, LLIL_PUSH, VoidExpr);
1416 sized_no_arg_lifter!(pop, LLIL_POP, ValueExpr);
1417
1418 size_changing_unary_op_lifter!(unimplemented_mem, LLIL_UNIMPL_MEM, ValueExpr);
1419
1420 sized_unary_op_lifter!(neg, LLIL_NEG, ValueExpr);
1421 sized_unary_op_lifter!(not, LLIL_NOT, ValueExpr);
1422
1423 size_changing_unary_op_lifter!(sx, LLIL_SX, ValueExpr);
1424 size_changing_unary_op_lifter!(zx, LLIL_ZX, ValueExpr);
1425 size_changing_unary_op_lifter!(low_part, LLIL_LOW_PART, ValueExpr);
1426
1427 binary_op_lifter!(add, LLIL_ADD);
1428 binary_op_lifter!(add_overflow, LLIL_ADD_OVERFLOW);
1429 binary_op_lifter!(sub, LLIL_SUB);
1430 binary_op_lifter!(and, LLIL_AND);
1431 binary_op_lifter!(or, LLIL_OR);
1432 binary_op_lifter!(xor, LLIL_XOR);
1433 binary_op_lifter!(lsl, LLIL_LSL);
1434 binary_op_lifter!(lsr, LLIL_LSR);
1435 binary_op_lifter!(asr, LLIL_ASR);
1436
1437 binary_op_lifter!(rol, LLIL_ROL);
1438 binary_op_lifter!(rlc, LLIL_RLC);
1439 binary_op_lifter!(ror, LLIL_ROR);
1440 binary_op_lifter!(rrc, LLIL_RRC);
1441 binary_op_lifter!(mul, LLIL_MUL);
1442 binary_op_lifter!(muls_dp, LLIL_MULS_DP);
1443 binary_op_lifter!(mulu_dp, LLIL_MULU_DP);
1444 binary_op_lifter!(divs, LLIL_DIVS);
1445 binary_op_lifter!(divu, LLIL_DIVU);
1446 binary_op_lifter!(mods, LLIL_MODS);
1447 binary_op_lifter!(modu, LLIL_MODU);
1448
1449 binary_op_carry_lifter!(adc, LLIL_ADC);
1450 binary_op_carry_lifter!(sbb, LLIL_SBB);
1451
1452 binary_op_lifter!(cmp_e, LLIL_CMP_E);
1462 binary_op_lifter!(cmp_ne, LLIL_CMP_NE);
1463 binary_op_lifter!(cmp_slt, LLIL_CMP_SLT);
1464 binary_op_lifter!(cmp_ult, LLIL_CMP_ULT);
1465 binary_op_lifter!(cmp_sle, LLIL_CMP_SLE);
1466 binary_op_lifter!(cmp_ule, LLIL_CMP_ULE);
1467 binary_op_lifter!(cmp_sge, LLIL_CMP_SGE);
1468 binary_op_lifter!(cmp_uge, LLIL_CMP_UGE);
1469 binary_op_lifter!(cmp_sgt, LLIL_CMP_SGT);
1470 binary_op_lifter!(cmp_ugt, LLIL_CMP_UGT);
1471 binary_op_lifter!(test_bit, LLIL_TEST_BIT);
1472
1473 size_changing_unary_op_lifter!(bool_to_int, LLIL_BOOL_TO_INT, ValueExpr);
1475
1476 binary_op_lifter!(fadd, LLIL_FADD);
1477 binary_op_lifter!(fsub, LLIL_FSUB);
1478 binary_op_lifter!(fmul, LLIL_FMUL);
1479 binary_op_lifter!(fdiv, LLIL_FDIV);
1480 sized_unary_op_lifter!(fsqrt, LLIL_FSQRT, ValueExpr);
1481 sized_unary_op_lifter!(fneg, LLIL_FNEG, ValueExpr);
1482 sized_unary_op_lifter!(fabs, LLIL_FABS, ValueExpr);
1483 sized_unary_op_lifter!(float_to_int, LLIL_FLOAT_TO_INT, ValueExpr);
1484 sized_unary_op_lifter!(int_to_float, LLIL_INT_TO_FLOAT, ValueExpr);
1485 sized_unary_op_lifter!(float_conv, LLIL_FLOAT_CONV, ValueExpr);
1486 sized_unary_op_lifter!(round_to_int, LLIL_ROUND_TO_INT, ValueExpr);
1487 sized_unary_op_lifter!(floor, LLIL_FLOOR, ValueExpr);
1488 sized_unary_op_lifter!(ceil, LLIL_CEIL, ValueExpr);
1489 sized_unary_op_lifter!(ftrunc, LLIL_FTRUNC, ValueExpr);
1490 binary_op_lifter!(fcmp_e, LLIL_FCMP_E);
1491 binary_op_lifter!(fcmp_ne, LLIL_FCMP_NE);
1492 binary_op_lifter!(fcmp_lt, LLIL_FCMP_LT);
1493 binary_op_lifter!(fcmp_le, LLIL_FCMP_LE);
1494 binary_op_lifter!(fcmp_ge, LLIL_FCMP_GE);
1495 binary_op_lifter!(fcmp_gt, LLIL_FCMP_GT);
1496 binary_op_lifter!(fcmp_o, LLIL_FCMP_O);
1497 binary_op_lifter!(fcmp_uo, LLIL_FCMP_UO);
1498
1499 pub fn current_address(&self) -> u64 {
1500 use binaryninjacore_sys::BNLowLevelILGetCurrentAddress;
1501 unsafe { BNLowLevelILGetCurrentAddress(self.handle) }
1502 }
1503
1504 pub fn set_current_address<L: Into<Location>>(&self, loc: L) {
1505 use binaryninjacore_sys::BNLowLevelILSetCurrentAddress;
1506
1507 let loc: Location = loc.into();
1508 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1509
1510 unsafe {
1511 BNLowLevelILSetCurrentAddress(self.handle, arch.handle, loc.addr);
1512 }
1513 }
1514
1515 pub fn label_for_address<L: Into<Location>>(&self, loc: L) -> Option<LowLevelILLabel> {
1516 use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
1517
1518 let loc: Location = loc.into();
1519 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1520 let raw_label =
1521 unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1522 match raw_label.is_null() {
1523 false => {
1524 let mut label = unsafe { LowLevelILLabel::from(*raw_label) };
1525 label.location = Some(loc);
1527 Some(label)
1528 }
1529 true => None,
1530 }
1531 }
1532
1533 fn update_label_map_for_label(&self, label: &LowLevelILLabel) {
1535 use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
1536
1537 if let Some(loc) = label.location {
1539 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1540 unsafe { BNAddLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1542 let raw_label =
1544 unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1545 assert!(!raw_label.is_null(), "Failed to add label for address!");
1547 unsafe { *raw_label = label.into() };
1549 }
1550 }
1551
1552 pub fn mark_label(&self, label: &mut LowLevelILLabel) {
1553 use binaryninjacore_sys::BNLowLevelILMarkLabel;
1554
1555 let mut raw_label = BNLowLevelILLabel::from(*label);
1556 unsafe { BNLowLevelILMarkLabel(self.handle, &mut raw_label) };
1557 let mut new_label = LowLevelILLabel::from(raw_label);
1558 if let Some(location) = label.location {
1559 new_label.location = Some(location);
1560 self.update_label_map_for_label(&new_label);
1561 }
1562 *label = new_label;
1563 }
1564}
1565
1566#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1567pub struct LowLevelILLabel {
1568 pub location: Option<Location>,
1570 pub resolved: bool,
1571 pub expr_ref: LowLevelExpressionIndex,
1574 pub operand: usize,
1576}
1577
1578impl LowLevelILLabel {
1579 pub fn new() -> Self {
1580 use binaryninjacore_sys::BNLowLevelILInitLabel;
1581
1582 let mut raw_label = BNLowLevelILLabel::default();
1583 unsafe { BNLowLevelILInitLabel(&mut raw_label) };
1584 raw_label.into()
1585 }
1586}
1587
1588impl From<BNLowLevelILLabel> for LowLevelILLabel {
1589 fn from(value: BNLowLevelILLabel) -> Self {
1590 Self {
1591 location: None,
1592 resolved: value.resolved,
1593 expr_ref: LowLevelExpressionIndex(value.ref_),
1594 operand: value.operand,
1595 }
1596 }
1597}
1598
1599impl From<LowLevelILLabel> for BNLowLevelILLabel {
1600 fn from(value: LowLevelILLabel) -> Self {
1601 Self {
1602 resolved: value.resolved,
1603 ref_: value.expr_ref.0,
1604 operand: value.operand,
1605 }
1606 }
1607}
1608
1609impl From<&LowLevelILLabel> for BNLowLevelILLabel {
1610 fn from(value: &LowLevelILLabel) -> Self {
1611 Self::from(*value)
1612 }
1613}
1614
1615impl Default for LowLevelILLabel {
1616 fn default() -> Self {
1617 Self::new()
1618 }
1619}