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