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 no_arg_lifter!(undefined, LLIL_UNDEF, ValueExpr);
1111 no_arg_lifter!(nop, LLIL_NOP, VoidExpr);
1112
1113 no_arg_lifter!(no_ret, LLIL_NORET, VoidExpr);
1114 no_arg_lifter!(syscall, LLIL_SYSCALL, VoidExpr);
1115 no_arg_lifter!(bp, LLIL_BP, VoidExpr);
1116
1117 unsized_unary_op_lifter!(call, LLIL_CALL, VoidExpr);
1118 unsized_unary_op_lifter!(tailcall, LLIL_TAILCALL, VoidExpr);
1119 unsized_unary_op_lifter!(ret, LLIL_RET, VoidExpr);
1120 unsized_unary_op_lifter!(jump, LLIL_JUMP, VoidExpr);
1121 pub fn if_expr<'a: 'b, 'b, C>(
1124 &'a self,
1125 cond: C,
1126 true_label: &'b mut LowLevelILLabel,
1127 false_label: &'b mut LowLevelILLabel,
1128 ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr>
1129 where
1130 C: LiftableLowLevelIL<'b, Result = ValueExpr>,
1131 {
1132 use binaryninjacore_sys::BNLowLevelILIf;
1133
1134 let cond = C::lift(self, cond);
1135
1136 let mut raw_true_label = BNLowLevelILLabel::from(*true_label);
1137 let mut raw_false_label = BNLowLevelILLabel::from(*false_label);
1138 let expr_idx = unsafe {
1139 BNLowLevelILIf(
1140 self.handle,
1141 cond.index.0 as u64,
1142 &mut raw_true_label,
1143 &mut raw_false_label,
1144 )
1145 };
1146
1147 let mut new_true_label = LowLevelILLabel::from(raw_true_label);
1149 let mut new_false_label = LowLevelILLabel::from(raw_false_label);
1150 if let Some(location) = true_label.location {
1151 new_true_label.location = Some(location);
1152 self.update_label_map_for_label(&new_true_label);
1153 }
1154 if let Some(location) = false_label.location {
1155 new_false_label.location = Some(location);
1156 self.update_label_map_for_label(&new_false_label);
1157 }
1158 *true_label = new_true_label;
1159 *false_label = new_false_label;
1160
1161 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1162 }
1163
1164 pub fn goto<'a: 'b, 'b>(
1166 &'a self,
1167 label: &'b mut LowLevelILLabel,
1168 ) -> LowLevelILExpression<'a, Mutable, NonSSA, VoidExpr> {
1169 use binaryninjacore_sys::BNLowLevelILGoto;
1170
1171 let mut raw_label = BNLowLevelILLabel::from(*label);
1172 let expr_idx = unsafe { BNLowLevelILGoto(self.handle, &mut raw_label) };
1173
1174 let mut new_label = LowLevelILLabel::from(raw_label);
1176 if let Some(location) = label.location {
1177 new_label.location = Some(location);
1178 self.update_label_map_for_label(&new_label);
1179 }
1180 *label = new_label;
1181
1182 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1183 }
1184
1185 pub fn reg<R: ArchReg, LR: Into<LowLevelILRegisterKind<R>>>(
1186 &self,
1187 size: usize,
1188 reg: LR,
1189 ) -> LowLevelILMutableExpression<'_, ValueExpr> {
1190 use binaryninjacore_sys::BNLowLevelILAddExpr;
1191 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG;
1192
1193 let reg = reg.into().id();
1195
1196 let expr_idx =
1197 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_REG, size, 0, reg.0 as u64, 0, 0, 0) };
1198
1199 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1200 }
1201
1202 pub fn reg_split<R: ArchReg, LR: Into<LowLevelILRegisterKind<R>>>(
1203 &self,
1204 size: usize,
1205 hi_reg: LR,
1206 lo_reg: LR,
1207 ) -> LowLevelILMutableExpression<'_, ValueExpr> {
1208 use binaryninjacore_sys::BNLowLevelILAddExpr;
1209 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT;
1210
1211 let hi_reg = hi_reg.into().id();
1213 let lo_reg = lo_reg.into().id();
1214
1215 let expr_idx = unsafe {
1216 BNLowLevelILAddExpr(
1217 self.handle,
1218 LLIL_REG_SPLIT,
1219 size,
1220 0,
1221 hi_reg.0 as u64,
1222 lo_reg.0 as u64,
1223 0,
1224 0,
1225 )
1226 };
1227
1228 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1229 }
1230
1231 pub fn set_reg<'a, R, LR, E>(
1232 &'a self,
1233 size: usize,
1234 dest_reg: LR,
1235 expr: E,
1236 ) -> ExpressionBuilder<'a, VoidExpr>
1237 where
1238 R: ArchReg,
1239 LR: Into<LowLevelILRegisterKind<R>>,
1240 E: LiftableLowLevelILWithSize<'a>,
1241 {
1242 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG;
1243
1244 let dest_reg = dest_reg.into().id();
1246
1247 let expr = E::lift_with_size(self, expr, size);
1248
1249 ExpressionBuilder {
1250 function: self,
1251 op: LLIL_SET_REG,
1252 size,
1253 flag_write: FlagWriteId(0),
1255 op1: dest_reg.0 as u64,
1256 op2: expr.index.0 as u64,
1257 op3: 0,
1258 op4: 0,
1259 _ty: PhantomData,
1260 }
1261 }
1262
1263 pub fn set_reg_split<'a, R, LR, E>(
1264 &'a self,
1265 size: usize,
1266 hi_reg: LR,
1267 lo_reg: LR,
1268 expr: E,
1269 ) -> ExpressionBuilder<'a, VoidExpr>
1270 where
1271 R: ArchReg,
1272 LR: Into<LowLevelILRegisterKind<R>>,
1273 E: LiftableLowLevelILWithSize<'a>,
1274 {
1275 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_REG_SPLIT;
1276
1277 let hi_reg = hi_reg.into().id();
1279 let lo_reg = lo_reg.into().id();
1280
1281 let expr = E::lift_with_size(self, expr, size);
1282
1283 ExpressionBuilder {
1284 function: self,
1285 op: LLIL_SET_REG_SPLIT,
1286 size,
1287 flag_write: FlagWriteId(0),
1288 op1: hi_reg.0 as u64,
1289 op2: lo_reg.0 as u64,
1290 op3: expr.index.0 as u64,
1291 op4: 0,
1292 _ty: PhantomData,
1293 }
1294 }
1295
1296 pub fn flag(&self, flag: impl Flag) -> LowLevelILMutableExpression<'_, ValueExpr> {
1297 use binaryninjacore_sys::BNLowLevelILAddExpr;
1298 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG;
1299
1300 let expr_idx = unsafe {
1302 BNLowLevelILAddExpr(self.handle, LLIL_FLAG, 0, 0, flag.id().0 as u64, 0, 0, 0)
1303 };
1304
1305 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1306 }
1307
1308 pub fn flag_cond(&self, cond: FlagCondition) -> LowLevelILMutableExpression<'_, ValueExpr> {
1309 use binaryninjacore_sys::BNLowLevelILAddExpr;
1310 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_COND;
1311
1312 let expr_idx =
1314 unsafe { BNLowLevelILAddExpr(self.handle, LLIL_FLAG_COND, 0, 0, cond as u64, 0, 0, 0) };
1315
1316 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1317 }
1318
1319 pub fn flag_group(&self, group: impl FlagGroup) -> LowLevelILMutableExpression<'_, ValueExpr> {
1320 use binaryninjacore_sys::BNLowLevelILAddExpr;
1321 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_FLAG_GROUP;
1322
1323 let expr_idx = unsafe {
1325 BNLowLevelILAddExpr(
1326 self.handle,
1327 LLIL_FLAG_GROUP,
1328 0,
1329 0,
1330 group.id().0 as u64,
1331 0,
1332 0,
1333 0,
1334 )
1335 };
1336
1337 LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
1338 }
1339
1340 pub fn set_flag<'a, E>(
1341 &'a self,
1342 dest_flag: impl Flag,
1343 expr: E,
1344 ) -> ExpressionBuilder<'a, VoidExpr>
1345 where
1346 E: LiftableLowLevelILWithSize<'a>,
1347 {
1348 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_SET_FLAG;
1349
1350 let expr = E::lift_with_size(self, expr, 0);
1353
1354 ExpressionBuilder {
1355 function: self,
1356 op: LLIL_SET_FLAG,
1357 size: 0,
1358 flag_write: FlagWriteId(0),
1359 op1: dest_flag.id().0 as u64,
1360 op2: expr.index.0 as u64,
1361 op3: 0,
1362 op4: 0,
1363 _ty: PhantomData,
1364 }
1365 }
1366
1367 pub fn load<'a, E>(&'a self, size: usize, source_mem: E) -> ExpressionBuilder<'a, ValueExpr>
1373 where
1374 E: LiftableLowLevelIL<'a, Result = ValueExpr>,
1375 {
1376 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_LOAD;
1377
1378 let expr = E::lift(self, source_mem);
1379
1380 ExpressionBuilder {
1381 function: self,
1382 op: LLIL_LOAD,
1383 size,
1384 flag_write: FlagWriteId(0),
1385 op1: expr.index.0 as u64,
1386 op2: 0,
1387 op3: 0,
1388 op4: 0,
1389 _ty: PhantomData,
1390 }
1391 }
1392
1393 pub fn store<'a, D, V>(
1394 &'a self,
1395 size: usize,
1396 dest_mem: D,
1397 value: V,
1398 ) -> ExpressionBuilder<'a, VoidExpr>
1399 where
1400 D: LiftableLowLevelIL<'a, Result = ValueExpr>,
1401 V: LiftableLowLevelILWithSize<'a>,
1402 {
1403 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_STORE;
1404
1405 let dest_mem = D::lift(self, dest_mem);
1406 let value = V::lift_with_size(self, value, size);
1407
1408 ExpressionBuilder {
1409 function: self,
1410 op: LLIL_STORE,
1411 size,
1412 flag_write: FlagWriteId(0),
1413 op1: dest_mem.index.0 as u64,
1414 op2: value.index.0 as u64,
1415 op3: 0,
1416 op4: 0,
1417 _ty: PhantomData,
1418 }
1419 }
1420
1421 pub fn intrinsic<'a, R, O, P>(
1423 &'a self,
1424 outputs: impl IntoIterator<Item = O>,
1425 intrinsic: impl Intrinsic,
1426 inputs: impl IntoIterator<Item = P>,
1427 ) -> ExpressionBuilder<'a, VoidExpr>
1428 where
1429 R: ArchReg,
1430 O: Into<LowLevelILRegisterKind<R>>,
1431 P: LiftableLowLevelIL<'a, Result = ValueExpr>,
1432 {
1433 use binaryninjacore_sys::BNLowLevelILOperation::{LLIL_CALL_PARAM, LLIL_INTRINSIC};
1434 use binaryninjacore_sys::{BNLowLevelILAddExpr, BNLowLevelILAddOperandList};
1435
1436 let mut outputs: Vec<u64> = outputs
1437 .into_iter()
1438 .map(|output| output.into().id().0 as u64)
1439 .collect();
1440 let output_expr_idx =
1441 unsafe { BNLowLevelILAddOperandList(self.handle, outputs.as_mut_ptr(), outputs.len()) };
1442
1443 let mut inputs: Vec<u64> = inputs
1444 .into_iter()
1445 .map(|input| {
1446 let input = P::lift(self, input);
1447 input.index.0 as u64
1448 })
1449 .collect();
1450 let input_list_expr_idx =
1451 unsafe { BNLowLevelILAddOperandList(self.handle, inputs.as_mut_ptr(), inputs.len()) };
1452 let input_expr_idx = unsafe {
1453 BNLowLevelILAddExpr(
1454 self.handle,
1455 LLIL_CALL_PARAM,
1456 0,
1457 0,
1458 inputs.len() as u64,
1459 input_list_expr_idx as u64,
1460 0,
1461 0,
1462 )
1463 };
1464
1465 ExpressionBuilder {
1466 function: self,
1467 op: LLIL_INTRINSIC,
1468 size: 0,
1469 flag_write: FlagWriteId(0),
1470 op1: outputs.len() as u64,
1471 op2: output_expr_idx as u64,
1472 op3: intrinsic.id().0 as u64,
1473 op4: input_expr_idx as u64,
1474 _ty: PhantomData,
1475 }
1476 }
1477
1478 sized_unary_op_lifter!(push, LLIL_PUSH, VoidExpr);
1479 sized_no_arg_lifter!(pop, LLIL_POP, ValueExpr);
1480
1481 size_changing_unary_op_lifter!(unimplemented_mem, LLIL_UNIMPL_MEM, ValueExpr);
1482
1483 sized_unary_op_lifter!(neg, LLIL_NEG, ValueExpr);
1484 sized_unary_op_lifter!(not, LLIL_NOT, ValueExpr);
1485 sized_unary_op_lifter!(bswap, LLIL_BSWAP, ValueExpr);
1486 sized_unary_op_lifter!(popcnt, LLIL_POPCNT, ValueExpr);
1487 sized_unary_op_lifter!(clz, LLIL_CLZ, ValueExpr);
1488 sized_unary_op_lifter!(ctz, LLIL_CTZ, ValueExpr);
1489 sized_unary_op_lifter!(rbit, LLIL_RBIT, ValueExpr);
1490 sized_unary_op_lifter!(cls, LLIL_CLS, ValueExpr);
1491 sized_unary_op_lifter!(abs, LLIL_ABS, ValueExpr);
1492
1493 size_changing_unary_op_lifter!(sx, LLIL_SX, ValueExpr);
1494 size_changing_unary_op_lifter!(zx, LLIL_ZX, ValueExpr);
1495 size_changing_unary_op_lifter!(low_part, LLIL_LOW_PART, ValueExpr);
1496
1497 binary_op_lifter!(add, LLIL_ADD);
1498 binary_op_lifter!(add_overflow, LLIL_ADD_OVERFLOW);
1499 binary_op_lifter!(sub, LLIL_SUB);
1500 binary_op_lifter!(and, LLIL_AND);
1501 binary_op_lifter!(or, LLIL_OR);
1502 binary_op_lifter!(xor, LLIL_XOR);
1503 binary_op_lifter!(lsl, LLIL_LSL);
1504 binary_op_lifter!(lsr, LLIL_LSR);
1505 binary_op_lifter!(asr, LLIL_ASR);
1506
1507 binary_op_lifter!(rol, LLIL_ROL);
1508 binary_op_lifter!(rlc, LLIL_RLC);
1509 binary_op_lifter!(ror, LLIL_ROR);
1510 binary_op_lifter!(rrc, LLIL_RRC);
1511 binary_op_lifter!(mul, LLIL_MUL);
1512 binary_op_lifter!(muls_dp, LLIL_MULS_DP);
1513 binary_op_lifter!(mulu_dp, LLIL_MULU_DP);
1514 binary_op_lifter!(divs, LLIL_DIVS);
1515 binary_op_lifter!(divu, LLIL_DIVU);
1516 binary_op_lifter!(mods, LLIL_MODS);
1517 binary_op_lifter!(modu, LLIL_MODU);
1518 binary_op_lifter!(min_signed, LLIL_MINS);
1519 binary_op_lifter!(max_signed, LLIL_MAXS);
1520 binary_op_lifter!(min_unsigned, LLIL_MINU);
1521 binary_op_lifter!(max_unsigned, LLIL_MAXU);
1522
1523 binary_op_carry_lifter!(adc, LLIL_ADC);
1524 binary_op_carry_lifter!(sbb, LLIL_SBB);
1525
1526 binary_op_lifter!(cmp_e, LLIL_CMP_E);
1536 binary_op_lifter!(cmp_ne, LLIL_CMP_NE);
1537 binary_op_lifter!(cmp_slt, LLIL_CMP_SLT);
1538 binary_op_lifter!(cmp_ult, LLIL_CMP_ULT);
1539 binary_op_lifter!(cmp_sle, LLIL_CMP_SLE);
1540 binary_op_lifter!(cmp_ule, LLIL_CMP_ULE);
1541 binary_op_lifter!(cmp_sge, LLIL_CMP_SGE);
1542 binary_op_lifter!(cmp_uge, LLIL_CMP_UGE);
1543 binary_op_lifter!(cmp_sgt, LLIL_CMP_SGT);
1544 binary_op_lifter!(cmp_ugt, LLIL_CMP_UGT);
1545 binary_op_lifter!(test_bit, LLIL_TEST_BIT);
1546
1547 size_changing_unary_op_lifter!(bool_to_int, LLIL_BOOL_TO_INT, ValueExpr);
1549
1550 binary_op_lifter!(fadd, LLIL_FADD);
1551 binary_op_lifter!(fsub, LLIL_FSUB);
1552 binary_op_lifter!(fmul, LLIL_FMUL);
1553 binary_op_lifter!(fdiv, LLIL_FDIV);
1554 sized_unary_op_lifter!(fsqrt, LLIL_FSQRT, ValueExpr);
1555 sized_unary_op_lifter!(fneg, LLIL_FNEG, ValueExpr);
1556 sized_unary_op_lifter!(fabs, LLIL_FABS, ValueExpr);
1557 sized_unary_op_lifter!(float_to_int, LLIL_FLOAT_TO_INT, ValueExpr);
1558 sized_unary_op_lifter!(int_to_float, LLIL_INT_TO_FLOAT, ValueExpr);
1559 sized_unary_op_lifter!(float_conv, LLIL_FLOAT_CONV, ValueExpr);
1560 sized_unary_op_lifter!(round_to_int, LLIL_ROUND_TO_INT, ValueExpr);
1561 sized_unary_op_lifter!(floor, LLIL_FLOOR, ValueExpr);
1562 sized_unary_op_lifter!(ceil, LLIL_CEIL, ValueExpr);
1563 sized_unary_op_lifter!(ftrunc, LLIL_FTRUNC, ValueExpr);
1564 binary_op_lifter!(fcmp_e, LLIL_FCMP_E);
1565 binary_op_lifter!(fcmp_ne, LLIL_FCMP_NE);
1566 binary_op_lifter!(fcmp_lt, LLIL_FCMP_LT);
1567 binary_op_lifter!(fcmp_le, LLIL_FCMP_LE);
1568 binary_op_lifter!(fcmp_ge, LLIL_FCMP_GE);
1569 binary_op_lifter!(fcmp_gt, LLIL_FCMP_GT);
1570 binary_op_lifter!(fcmp_o, LLIL_FCMP_O);
1571 binary_op_lifter!(fcmp_uo, LLIL_FCMP_UO);
1572
1573 pub fn current_address(&self) -> u64 {
1574 use binaryninjacore_sys::BNLowLevelILGetCurrentAddress;
1575 unsafe { BNLowLevelILGetCurrentAddress(self.handle) }
1576 }
1577
1578 pub fn set_current_address<L: Into<Location>>(&self, loc: L) {
1579 use binaryninjacore_sys::BNLowLevelILSetCurrentAddress;
1580
1581 let loc: Location = loc.into();
1582 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1583
1584 unsafe {
1585 BNLowLevelILSetCurrentAddress(self.handle, arch.handle, loc.addr);
1586 }
1587 }
1588
1589 pub fn set_current_source_block(&self, source: &BasicBlock<NativeBlock>) {
1590 use binaryninjacore_sys::BNLowLevelILSetCurrentSourceBlock;
1591 unsafe {
1592 BNLowLevelILSetCurrentSourceBlock(self.handle, source.handle);
1593 }
1594 }
1595
1596 pub fn label_for_address<L: Into<Location>>(&self, loc: L) -> Option<LowLevelILLabel> {
1597 use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
1598
1599 let loc: Location = loc.into();
1600 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1601 let raw_label =
1602 unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1603 match raw_label.is_null() {
1604 false => {
1605 let mut label = unsafe { LowLevelILLabel::from(*raw_label) };
1606 label.location = Some(loc);
1608 Some(label)
1609 }
1610 true => None,
1611 }
1612 }
1613
1614 fn update_label_map_for_label(&self, label: &LowLevelILLabel) {
1616 use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
1617
1618 if let Some(loc) = label.location {
1620 let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1621 unsafe { BNAddLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1623 let raw_label =
1625 unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1626 assert!(!raw_label.is_null(), "Failed to add label for address!");
1628 unsafe { *raw_label = label.into() };
1630 }
1631 }
1632
1633 pub fn mark_label(&self, label: &mut LowLevelILLabel) {
1634 use binaryninjacore_sys::BNLowLevelILMarkLabel;
1635
1636 let mut raw_label = BNLowLevelILLabel::from(*label);
1637 unsafe { BNLowLevelILMarkLabel(self.handle, &mut raw_label) };
1638 let mut new_label = LowLevelILLabel::from(raw_label);
1639 if let Some(location) = label.location {
1640 new_label.location = Some(location);
1641 self.update_label_map_for_label(&new_label);
1642 }
1643 *label = new_label;
1644 }
1645
1646 pub fn set_expr_attributes(
1647 &self,
1648 expr: LowLevelExpressionIndex,
1649 value: &ILInstructionAttributeSet,
1650 ) {
1651 let mut result = 0u32;
1652 for flag in value {
1653 result |= flag.value();
1654 }
1655
1656 unsafe {
1657 BNSetLowLevelILExprAttributes(self.handle, expr.0, result);
1658 }
1659 }
1660
1661 pub fn clear_indirect_branches(&self) {
1662 unsafe { BNLowLevelILClearIndirectBranches(self.handle) };
1663 }
1664}
1665
1666#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1667pub struct LowLevelILLabel {
1668 pub location: Option<Location>,
1670 pub resolved: bool,
1671 pub expr_ref: LowLevelExpressionIndex,
1674 pub operand: usize,
1676}
1677
1678impl LowLevelILLabel {
1679 pub fn new() -> Self {
1680 use binaryninjacore_sys::BNLowLevelILInitLabel;
1681
1682 let mut raw_label = BNLowLevelILLabel::default();
1683 unsafe { BNLowLevelILInitLabel(&mut raw_label) };
1684 raw_label.into()
1685 }
1686}
1687
1688impl From<BNLowLevelILLabel> for LowLevelILLabel {
1689 fn from(value: BNLowLevelILLabel) -> Self {
1690 Self {
1691 location: None,
1692 resolved: value.resolved,
1693 expr_ref: LowLevelExpressionIndex(value.ref_),
1694 operand: value.operand,
1695 }
1696 }
1697}
1698
1699impl From<LowLevelILLabel> for BNLowLevelILLabel {
1700 fn from(value: LowLevelILLabel) -> Self {
1701 Self {
1702 resolved: value.resolved,
1703 ref_: value.expr_ref.0,
1704 operand: value.operand,
1705 }
1706 }
1707}
1708
1709impl From<&LowLevelILLabel> for BNLowLevelILLabel {
1710 fn from(value: &LowLevelILLabel) -> Self {
1711 Self::from(*value)
1712 }
1713}
1714
1715impl Default for LowLevelILLabel {
1716 fn default() -> Self {
1717 Self::new()
1718 }
1719}