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