1use binaryninjacore_sys::{
16 BNGetCachedLowLevelILPossibleValueSet, BNGetLowLevelILByIndex, BNLowLevelILFreeOperandList,
17 BNLowLevelILGetOperandList, BNLowLevelILInstruction,
18};
19
20use super::*;
21use crate::architecture::{
22 CoreFlag, CoreFlagGroup, CoreFlagWrite, CoreIntrinsic, CoreRegister, CoreRegisterStack,
23 FlagGroupId, FlagId, FlagWriteId, IntrinsicId, RegisterStackId,
24};
25use crate::variable::PossibleValueSet;
26use std::collections::BTreeMap;
27use std::fmt::{Debug, Formatter};
28use std::marker::PhantomData;
29use std::mem;
30
31pub struct Operation<'func, M, F, O>
32where
33 M: FunctionMutability,
34 F: FunctionForm,
35 O: OperationArguments,
36{
37 pub(crate) function: &'func LowLevelILFunction<M, F>,
38 pub(crate) op: BNLowLevelILInstruction,
39 pub(crate) expr_idx: LowLevelExpressionIndex,
40 _args: PhantomData<O>,
41}
42
43impl<'func, M, F, O> Operation<'func, M, F, O>
44where
45 M: FunctionMutability,
46 F: FunctionForm,
47 O: OperationArguments,
48{
49 pub(crate) fn new(
50 function: &'func LowLevelILFunction<M, F>,
51 op: BNLowLevelILInstruction,
52 expr_idx: LowLevelExpressionIndex,
53 ) -> Self {
54 Self {
55 function,
56 op,
57 expr_idx,
58 _args: PhantomData,
59 }
60 }
61
62 pub fn address(&self) -> u64 {
63 self.op.address
64 }
65
66 fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
67 let mut count = 0;
68 let raw_list_ptr = unsafe {
69 BNLowLevelILGetOperandList(
70 self.function.handle,
71 self.expr_idx.0,
72 operand_idx,
73 &mut count,
74 )
75 };
76 assert!(!raw_list_ptr.is_null());
77 let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
78 unsafe { BNLowLevelILFreeOperandList(raw_list_ptr) };
79 list
80 }
81
82 fn get_constraint(&self, operand_idx: usize) -> PossibleValueSet {
83 let raw_pvs = unsafe {
84 BNGetCachedLowLevelILPossibleValueSet(
85 self.function.handle,
86 self.op.operands[operand_idx] as usize,
87 )
88 };
89 PossibleValueSet::from_owned_core_raw(raw_pvs)
90 }
91
92 pub unsafe fn get_operand(&self, idx: usize) -> u64 {
104 assert!(idx < 4);
105 self.op.operands[idx]
106 }
107}
108
109impl<M, O> Operation<'_, M, NonSSA, O>
110where
111 M: FunctionMutability,
112 O: OperationArguments,
113{
114 pub fn flag_write(&self) -> Option<CoreFlagWrite> {
118 match self.op.flags {
119 0 => None,
120 id => self.function.arch().flag_write_from_id(FlagWriteId(id)),
121 }
122 }
123}
124
125pub struct NoArgs;
127
128impl<M, F> Debug for Operation<'_, M, F, NoArgs>
129where
130 M: FunctionMutability,
131 F: FunctionForm,
132{
133 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
134 f.debug_struct("NoArgs").finish()
135 }
136}
137
138pub struct Pop;
140
141impl<M, F> Operation<'_, M, F, Pop>
142where
143 M: FunctionMutability,
144 F: FunctionForm,
145{
146 pub fn size(&self) -> usize {
147 self.op.size
148 }
149}
150
151impl<M, F> Debug for Operation<'_, M, F, Pop>
152where
153 M: FunctionMutability,
154 F: FunctionForm,
155{
156 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
157 f.debug_struct("Pop")
158 .field("address", &self.address())
159 .field("size", &self.size())
160 .finish()
161 }
162}
163
164pub struct Syscall;
166
167impl<M, F> Debug for Operation<'_, M, F, Syscall>
168where
169 M: FunctionMutability,
170 F: FunctionForm,
171{
172 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173 f.debug_struct("Syscall").finish()
174 }
175}
176
177pub struct SyscallSsa;
179
180impl<'func, M, F> Operation<'func, M, F, SyscallSsa>
181where
182 M: FunctionMutability,
183 F: FunctionForm,
184{
185 pub fn output_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
189 LowLevelILExpression::new(
190 self.function,
191 LowLevelExpressionIndex(self.op.operands[0] as usize),
192 )
193 }
194
195 pub fn param_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
199 LowLevelILExpression::new(
200 self.function,
201 LowLevelExpressionIndex(self.op.operands[2] as usize),
202 )
203 }
204
205 pub fn stack_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
209 LowLevelILExpression::new(
210 self.function,
211 LowLevelExpressionIndex(self.op.operands[1] as usize),
212 )
213 }
214}
215
216impl<M, F> Debug for Operation<'_, M, F, SyscallSsa>
217where
218 M: FunctionMutability,
219 F: FunctionForm,
220{
221 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
222 f.debug_struct("SyscallSsa")
223 .field("output_expr", &self.output_expr())
224 .field("param_expr", &self.param_expr())
225 .field("stack_expr", &self.stack_expr())
226 .finish()
227 }
228}
229
230pub struct Intrinsic;
232
233#[derive(Debug, Clone, Copy, PartialEq)]
234pub enum IntrinsicOutput {
235 Reg(CoreRegister),
236 Flag(CoreFlag),
237}
238
239impl From<CoreRegister> for IntrinsicOutput {
240 fn from(value: CoreRegister) -> Self {
241 Self::Reg(value)
242 }
243}
244
245impl From<CoreFlag> for IntrinsicOutput {
246 fn from(value: CoreFlag) -> Self {
247 Self::Flag(value)
248 }
249}
250
251impl<M, F> Operation<'_, M, F, Intrinsic>
252where
253 M: FunctionMutability,
254 F: FunctionForm,
255{
256 pub fn intrinsic(&self) -> Option<CoreIntrinsic> {
257 let raw_id = self.op.operands[2] as u32;
258 self.function.arch().intrinsic_from_id(IntrinsicId(raw_id))
259 }
260
261 pub fn outputs(&self) -> Vec<IntrinsicOutput> {
263 let operand_to_output = |o: u64| {
265 if o & (1 << 32) != 0 {
266 self.function
267 .arch()
268 .flag_from_id(FlagId((o & 0xffffffff) as u32))
269 .expect("Invalid core flag ID")
270 .into()
271 } else {
272 self.function
273 .arch()
274 .register_from_id(RegisterId((o & 0xffffffff) as u32))
275 .expect("Invalid register ID")
276 .into()
277 }
278 };
279
280 self.get_operand_list(0)
281 .into_iter()
282 .map(operand_to_output)
283 .collect::<Vec<_>>()
284 }
285
286 #[inline]
290 pub fn inputs(&self) -> LowLevelILExpression<'_, M, F, ValueExpr> {
291 LowLevelILExpression::new(
292 self.function,
293 LowLevelExpressionIndex(self.op.operands[3] as usize),
294 )
295 }
296}
297
298impl<M, F> Debug for Operation<'_, M, F, Intrinsic>
299where
300 M: FunctionMutability,
301 F: FunctionForm,
302{
303 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304 use crate::architecture::Intrinsic;
305 f.debug_struct("Intrinsic")
306 .field("address", &self.address())
307 .field(
308 "intrinsic",
309 &self.intrinsic().expect("Valid intrinsic").name(),
310 )
311 .field("outputs", &self.outputs())
312 .field("inputs", &self.inputs())
313 .finish()
314 }
315}
316
317pub struct SetReg;
319
320impl<'func, M, F> Operation<'func, M, F, SetReg>
321where
322 M: FunctionMutability,
323 F: FunctionForm,
324{
325 pub fn size(&self) -> usize {
326 self.op.size
327 }
328
329 pub fn dest_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
330 let raw_id = RegisterId(self.op.operands[0] as u32);
331 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
332 }
333
334 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
335 LowLevelILExpression::new(
336 self.function,
337 LowLevelExpressionIndex(self.op.operands[1] as usize),
338 )
339 }
340}
341
342impl<M, F> Debug for Operation<'_, M, F, SetReg>
343where
344 M: FunctionMutability,
345 F: FunctionForm,
346{
347 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
348 f.debug_struct("SetReg")
349 .field("address", &self.address())
350 .field("size", &self.size())
351 .field("dest_reg", &self.dest_reg())
352 .field("source_expr", &self.source_expr())
353 .finish()
354 }
355}
356
357pub struct SetRegSsa;
359
360impl<'func, M, F> Operation<'func, M, F, SetRegSsa>
361where
362 M: FunctionMutability,
363 F: FunctionForm,
364{
365 pub fn size(&self) -> usize {
366 self.op.size
367 }
368
369 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
370 let raw_id = RegisterId(self.op.operands[0] as u32);
371 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
372 .expect("Bad register ID");
373 let version = self.op.operands[1] as u32;
374 LowLevelILSSARegisterKind::new_full(reg_kind, version)
375 }
376
377 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
378 LowLevelILExpression::new(
379 self.function,
380 LowLevelExpressionIndex(self.op.operands[2] as usize),
381 )
382 }
383}
384
385impl<M, F> Debug for Operation<'_, M, F, SetRegSsa>
386where
387 M: FunctionMutability,
388 F: FunctionForm,
389{
390 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
391 f.debug_struct("SetRegSsa")
392 .field("address", &self.address())
393 .field("size", &self.size())
394 .field("dest_reg", &self.dest_reg())
395 .field("source_expr", &self.source_expr())
396 .finish()
397 }
398}
399
400pub struct SetRegPartialSsa;
402
403impl<'func, M, F> Operation<'func, M, F, SetRegPartialSsa>
404where
405 M: FunctionMutability,
406 F: FunctionForm,
407{
408 pub fn size(&self) -> usize {
409 self.op.size
410 }
411
412 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
413 let full_raw_id = RegisterId(self.op.operands[0] as u32);
414 let version = self.op.operands[1] as u32;
415 let partial_raw_id = RegisterId(self.op.operands[2] as u32);
416 let full_reg =
417 CoreRegister::new(self.function.arch(), full_raw_id).expect("Bad register ID");
418 let partial_reg =
419 CoreRegister::new(self.function.arch(), partial_raw_id).expect("Bad register ID");
420 LowLevelILSSARegisterKind::new_partial(full_reg, partial_reg, version)
421 }
422
423 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
424 LowLevelILExpression::new(
425 self.function,
426 LowLevelExpressionIndex(self.op.operands[3] as usize),
427 )
428 }
429}
430
431impl<M, F> Debug for Operation<'_, M, F, SetRegPartialSsa>
432where
433 M: FunctionMutability,
434 F: FunctionForm,
435{
436 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
437 f.debug_struct("SetRegPartialSsa")
438 .field("address", &self.address())
439 .field("size", &self.size())
440 .field("dest_reg", &self.dest_reg())
441 .field("source_expr", &self.source_expr())
442 .finish()
443 }
444}
445
446pub struct SetRegSplit;
448
449impl<'func, M, F> Operation<'func, M, F, SetRegSplit>
450where
451 M: FunctionMutability,
452 F: FunctionForm,
453{
454 pub fn size(&self) -> usize {
455 self.op.size
456 }
457
458 pub fn dest_reg_high(&self) -> LowLevelILRegisterKind<CoreRegister> {
459 let raw_id = RegisterId(self.op.operands[0] as u32);
460 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
461 }
462
463 pub fn dest_reg_low(&self) -> LowLevelILRegisterKind<CoreRegister> {
464 let raw_id = RegisterId(self.op.operands[1] as u32);
465 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
466 }
467
468 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
469 LowLevelILExpression::new(
470 self.function,
471 LowLevelExpressionIndex(self.op.operands[2] as usize),
472 )
473 }
474}
475
476impl<M, F> Debug for Operation<'_, M, F, SetRegSplit>
477where
478 M: FunctionMutability,
479 F: FunctionForm,
480{
481 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
482 f.debug_struct("SetRegSplit")
483 .field("address", &self.address())
484 .field("size", &self.size())
485 .field("dest_reg_high", &self.dest_reg_high())
486 .field("dest_reg_low", &self.dest_reg_low())
487 .field("source_expr", &self.source_expr())
488 .finish()
489 }
490}
491
492pub struct SetRegSplitSsa;
494
495impl<'func, M, F> Operation<'func, M, F, SetRegSplitSsa>
496where
497 M: FunctionMutability,
498 F: FunctionForm,
499{
500 pub fn size(&self) -> usize {
501 self.op.size
502 }
503
504 pub fn dest_expr_high(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
508 LowLevelILExpression::new(
509 self.function,
510 LowLevelExpressionIndex(self.op.operands[0] as usize),
511 )
512 }
513
514 pub fn dest_expr_low(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
518 LowLevelILExpression::new(
519 self.function,
520 LowLevelExpressionIndex(self.op.operands[1] as usize),
521 )
522 }
523
524 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
525 LowLevelILExpression::new(
526 self.function,
527 LowLevelExpressionIndex(self.op.operands[2] as usize),
528 )
529 }
530}
531
532impl<M, F> Debug for Operation<'_, M, F, SetRegSplitSsa>
533where
534 M: FunctionMutability,
535 F: FunctionForm,
536{
537 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
538 f.debug_struct("SetRegSplitSsa")
539 .field("address", &self.address())
540 .field("size", &self.size())
541 .field("dest_expr_high", &self.dest_expr_high())
542 .field("dest_expr_low", &self.dest_expr_low())
543 .field("source_expr", &self.source_expr())
544 .finish()
545 }
546}
547
548pub struct SetFlag;
550
551impl<'func, M, F> Operation<'func, M, F, SetFlag>
552where
553 M: FunctionMutability,
554 F: FunctionForm,
555{
556 pub fn dest_flag(&self) -> CoreFlag {
557 self.function
558 .arch()
559 .flag_from_id(FlagId(self.op.operands[0] as u32))
560 .expect("Bad flag ID")
561 }
562
563 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
564 LowLevelILExpression::new(
565 self.function,
566 LowLevelExpressionIndex(self.op.operands[1] as usize),
567 )
568 }
569}
570
571impl<M, F> Debug for Operation<'_, M, F, SetFlag>
572where
573 M: FunctionMutability,
574 F: FunctionForm,
575{
576 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
577 f.debug_struct("SetFlag")
578 .field("address", &self.address())
579 .field("dest_flag", &self.dest_flag())
580 .field("source_expr", &self.source_expr())
581 .finish()
582 }
583}
584
585pub struct SetFlagSsa;
587
588impl<'func, M, F> Operation<'func, M, F, SetFlagSsa>
589where
590 M: FunctionMutability,
591 F: FunctionForm,
592{
593 pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
594 let flag = self
595 .function
596 .arch()
597 .flag_from_id(FlagId(self.op.operands[0] as u32))
598 .expect("Bad flag ID");
599 let version = self.op.operands[1] as u32;
600 LowLevelILSSAFlag::new(flag, version)
601 }
602
603 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
604 LowLevelILExpression::new(
605 self.function,
606 LowLevelExpressionIndex(self.op.operands[2] as usize),
607 )
608 }
609}
610
611impl<M, F> Debug for Operation<'_, M, F, SetFlagSsa>
612where
613 M: FunctionMutability,
614 F: FunctionForm,
615{
616 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
617 f.debug_struct("SetFlagSsa")
618 .field("address", &self.address())
619 .field("dest_flag", &self.dest_flag())
620 .field("source_expr", &self.source_expr())
621 .finish()
622 }
623}
624pub struct Load;
626
627impl<'func, M, F> Operation<'func, M, F, Load>
628where
629 M: FunctionMutability,
630 F: FunctionForm,
631{
632 pub fn size(&self) -> usize {
633 self.op.size
634 }
635
636 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
637 LowLevelILExpression::new(
638 self.function,
639 LowLevelExpressionIndex(self.op.operands[0] as usize),
640 )
641 }
642}
643
644impl<M, F> Debug for Operation<'_, M, F, Load>
645where
646 M: FunctionMutability,
647 F: FunctionForm,
648{
649 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
650 f.debug_struct("Load")
651 .field("address", &self.address())
652 .field("size", &self.size())
653 .field("source_expr", &self.source_expr())
654 .finish()
655 }
656}
657
658pub struct LoadSsa;
660
661impl<'func, M, F> Operation<'func, M, F, LoadSsa>
662where
663 M: FunctionMutability,
664 F: FunctionForm,
665{
666 pub fn size(&self) -> usize {
667 self.op.size
668 }
669
670 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
671 LowLevelILExpression::new(
672 self.function,
673 LowLevelExpressionIndex(self.op.operands[0] as usize),
674 )
675 }
676
677 pub fn source_memory_version(&self) -> u64 {
678 self.op.operands[1]
679 }
680}
681
682impl<M, F> Debug for Operation<'_, M, F, LoadSsa>
683where
684 M: FunctionMutability,
685 F: FunctionForm,
686{
687 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
688 f.debug_struct("LoadSsa")
689 .field("address", &self.address())
690 .field("size", &self.size())
691 .field("source_expr", &self.source_expr())
692 .finish()
693 }
694}
695
696pub struct Store;
698
699impl<'func, M, F> Operation<'func, M, F, Store>
700where
701 M: FunctionMutability,
702 F: FunctionForm,
703{
704 pub fn size(&self) -> usize {
705 self.op.size
706 }
707
708 pub fn dest_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
709 LowLevelILExpression::new(
710 self.function,
711 LowLevelExpressionIndex(self.op.operands[0] as usize),
712 )
713 }
714
715 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
716 LowLevelILExpression::new(
717 self.function,
718 LowLevelExpressionIndex(self.op.operands[1] as usize),
719 )
720 }
721}
722
723impl<M, F> Debug for Operation<'_, M, F, Store>
724where
725 M: FunctionMutability,
726 F: FunctionForm,
727{
728 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
729 f.debug_struct("Store")
730 .field("address", &self.address())
731 .field("size", &self.size())
732 .field("dest_expr", &self.dest_expr())
733 .field("source_expr", &self.source_expr())
734 .finish()
735 }
736}
737
738pub struct StoreSsa;
740
741impl<'func, M, F> Operation<'func, M, F, StoreSsa>
742where
743 M: FunctionMutability,
744 F: FunctionForm,
745{
746 pub fn size(&self) -> usize {
747 self.op.size
748 }
749
750 pub fn dest_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
751 LowLevelILExpression::new(
752 self.function,
753 LowLevelExpressionIndex(self.op.operands[0] as usize),
754 )
755 }
756
757 pub fn dest_memory_version(&self) -> u64 {
758 self.op.operands[1]
759 }
760
761 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
762 LowLevelILExpression::new(
763 self.function,
764 LowLevelExpressionIndex(self.op.operands[3] as usize),
765 )
766 }
767
768 pub fn source_memory_version(&self) -> u64 {
769 self.op.operands[2]
770 }
771}
772
773impl<M, F> Debug for Operation<'_, M, F, StoreSsa>
774where
775 M: FunctionMutability,
776 F: FunctionForm,
777{
778 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
779 f.debug_struct("StoreSsa")
780 .field("address", &self.address())
781 .field("size", &self.size())
782 .field("dest_expr", &self.dest_expr())
783 .field("source_expr", &self.source_expr())
784 .finish()
785 }
786}
787
788pub struct Reg;
790
791impl<M, F> Operation<'_, M, F, Reg>
792where
793 M: FunctionMutability,
794 F: FunctionForm,
795{
796 pub fn size(&self) -> usize {
797 self.op.size
798 }
799
800 pub fn source_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
801 let raw_id = RegisterId(self.op.operands[0] as u32);
802 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
803 }
804}
805
806impl<M, F> Debug for Operation<'_, M, F, Reg>
807where
808 M: FunctionMutability,
809 F: FunctionForm,
810{
811 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
812 f.debug_struct("Reg")
813 .field("address", &self.address())
814 .field("size", &self.size())
815 .field("source_reg", &self.source_reg())
816 .finish()
817 }
818}
819
820pub struct RegSsa;
822
823impl<M, F> Operation<'_, M, F, RegSsa>
824where
825 M: FunctionMutability,
826 F: FunctionForm,
827{
828 pub fn size(&self) -> usize {
829 self.op.size
830 }
831
832 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
833 let raw_id = RegisterId(self.op.operands[0] as u32);
834 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
835 .expect("Bad register ID");
836 let version = self.op.operands[1] as u32;
837 LowLevelILSSARegisterKind::new_full(reg_kind, version)
838 }
839}
840
841impl<M, F> Debug for Operation<'_, M, F, RegSsa>
842where
843 M: FunctionMutability,
844 F: FunctionForm,
845{
846 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
847 f.debug_struct("RegSsa")
848 .field("address", &self.address())
849 .field("size", &self.size())
850 .field("source_reg", &self.source_reg())
851 .finish()
852 }
853}
854
855pub struct RegPartialSsa;
857
858impl<M, F> Operation<'_, M, F, RegPartialSsa>
859where
860 M: FunctionMutability,
861 F: FunctionForm,
862{
863 pub fn size(&self) -> usize {
864 self.op.size
865 }
866
867 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
868 let full_raw_id = RegisterId(self.op.operands[0] as u32);
869 let version = self.op.operands[1] as u32;
870 let partial_raw_id = RegisterId(self.op.operands[2] as u32);
871 let full_reg =
872 CoreRegister::new(self.function.arch(), full_raw_id).expect("Bad register ID");
873 let partial_reg =
874 CoreRegister::new(self.function.arch(), partial_raw_id).expect("Bad register ID");
875 LowLevelILSSARegisterKind::new_partial(full_reg, partial_reg, version)
876 }
877}
878
879impl<M, F> Debug for Operation<'_, M, F, RegPartialSsa>
880where
881 M: FunctionMutability,
882 F: FunctionForm,
883{
884 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
885 f.debug_struct("RegPartialSsa")
886 .field("address", &self.address())
887 .field("size", &self.size())
888 .field("source_reg", &self.source_reg())
889 .finish()
890 }
891}
892
893pub struct RegSplit;
895
896impl<M, F> Operation<'_, M, F, RegSplit>
897where
898 M: FunctionMutability,
899 F: FunctionForm,
900{
901 pub fn size(&self) -> usize {
902 self.op.size
903 }
904
905 pub fn low_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
906 let raw_id = RegisterId(self.op.operands[0] as u32);
907 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
908 }
909
910 pub fn high_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
911 let raw_id = RegisterId(self.op.operands[1] as u32);
912 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
913 }
914}
915
916impl<M, F> Debug for Operation<'_, M, F, RegSplit>
917where
918 M: FunctionMutability,
919 F: FunctionForm,
920{
921 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
922 f.debug_struct("RegSplit")
923 .field("address", &self.address())
924 .field("size", &self.size())
925 .field("low_reg", &self.low_reg())
926 .field("high_reg", &self.high_reg())
927 .finish()
928 }
929}
930
931pub struct RegSplitSsa;
933
934impl<M, F> Operation<'_, M, F, RegSplitSsa>
935where
936 M: FunctionMutability,
937 F: FunctionForm,
938{
939 pub fn size(&self) -> usize {
940 self.op.size
941 }
942
943 pub fn low_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
944 let raw_id = RegisterId(self.op.operands[0] as u32);
945 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
946 .expect("Bad register ID");
947 let version = self.op.operands[1] as u32;
948 LowLevelILSSARegisterKind::new_full(reg_kind, version)
949 }
950
951 pub fn high_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
952 let raw_id = RegisterId(self.op.operands[2] as u32);
953 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
954 .expect("Bad register ID");
955 let version = self.op.operands[3] as u32;
956 LowLevelILSSARegisterKind::new_full(reg_kind, version)
957 }
958}
959
960impl<M, F> Debug for Operation<'_, M, F, RegSplitSsa>
961where
962 M: FunctionMutability,
963 F: FunctionForm,
964{
965 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
966 f.debug_struct("RegSplitSsa")
967 .field("address", &self.address())
968 .field("size", &self.size())
969 .field("low_reg", &self.low_reg())
970 .field("high_reg", &self.high_reg())
971 .finish()
972 }
973}
974
975pub struct RegStackPush;
977
978impl<'func, M, F> Operation<'func, M, F, RegStackPush>
979where
980 M: FunctionMutability,
981 F: FunctionForm,
982{
983 pub fn size(&self) -> usize {
984 self.op.size
985 }
986
987 pub fn dest_reg_stack(&self) -> CoreRegisterStack {
988 let raw_id = self.op.operands[0] as u32;
989 self.function
990 .arch()
991 .register_stack_from_id(RegisterStackId(raw_id))
992 .expect("Bad register stack ID")
993 }
994
995 pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
996 LowLevelILExpression::new(
997 self.function,
998 LowLevelExpressionIndex(self.op.operands[1] as usize),
999 )
1000 }
1001}
1002
1003impl<M, F> Debug for Operation<'_, M, F, RegStackPush>
1004where
1005 M: FunctionMutability,
1006 F: FunctionForm,
1007{
1008 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1009 f.debug_struct("RegStackPush")
1010 .field("address", &self.address())
1011 .field("size", &self.size())
1012 .field("dest_reg_stack", &self.dest_reg_stack())
1013 .field("source_expr", &self.source_expr())
1014 .finish()
1015 }
1016}
1017
1018pub struct RegStackPop;
1020
1021impl<M, F> Operation<'_, M, F, RegStackPop>
1022where
1023 M: FunctionMutability,
1024 F: FunctionForm,
1025{
1026 pub fn size(&self) -> usize {
1027 self.op.size
1028 }
1029
1030 pub fn source_reg_stack(&self) -> CoreRegisterStack {
1031 let raw_id = self.op.operands[0] as u32;
1032 self.function
1033 .arch()
1034 .register_stack_from_id(RegisterStackId(raw_id))
1035 .expect("Bad register stack ID")
1036 }
1037}
1038
1039impl<M, F> Debug for Operation<'_, M, F, RegStackPop>
1040where
1041 M: FunctionMutability,
1042 F: FunctionForm,
1043{
1044 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1045 f.debug_struct("RegStackPop")
1046 .field("address", &self.address())
1047 .field("size", &self.size())
1048 .field("source_reg_stack", &self.source_reg_stack())
1049 .finish()
1050 }
1051}
1052
1053pub struct RegStackFreeReg;
1055
1056impl<M, F> Operation<'_, M, F, RegStackFreeReg>
1057where
1058 M: FunctionMutability,
1059 F: FunctionForm,
1060{
1061 pub fn size(&self) -> usize {
1062 self.op.size
1063 }
1064
1065 pub fn dest_reg(&self) -> CoreRegister {
1066 let raw_id = self.op.operands[0] as u32;
1067 self.function
1068 .arch()
1069 .register_from_id(RegisterId(raw_id))
1070 .expect("Bad register ID")
1071 }
1072}
1073
1074impl<M, F> Debug for Operation<'_, M, F, RegStackFreeReg>
1075where
1076 M: FunctionMutability,
1077 F: FunctionForm,
1078{
1079 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1080 f.debug_struct("RegStackFreeReg")
1081 .field("address", &self.address())
1082 .field("size", &self.size())
1083 .field("dest_reg", &self.dest_reg())
1084 .finish()
1085 }
1086}
1087
1088pub struct Flag;
1090
1091impl<M, F> Operation<'_, M, F, Flag>
1092where
1093 M: FunctionMutability,
1094 F: FunctionForm,
1095{
1096 pub fn source_flag(&self) -> CoreFlag {
1097 self.function
1098 .arch()
1099 .flag_from_id(FlagId(self.op.operands[0] as u32))
1100 .expect("Bad flag ID")
1101 }
1102}
1103
1104impl<M, F> Debug for Operation<'_, M, F, Flag>
1105where
1106 M: FunctionMutability,
1107 F: FunctionForm,
1108{
1109 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1110 f.debug_struct("Flag")
1111 .field("source_flag", &self.source_flag())
1112 .finish()
1113 }
1114}
1115
1116pub struct FlagBit;
1118
1119impl<M, F> Debug for Operation<'_, M, F, FlagBit>
1120where
1121 M: FunctionMutability,
1122 F: FunctionForm,
1123{
1124 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1125 f.debug_struct("FlagBit").finish()
1126 }
1127}
1128
1129pub struct Jump;
1131
1132impl<'func, M, F> Operation<'func, M, F, Jump>
1133where
1134 M: FunctionMutability,
1135 F: FunctionForm,
1136{
1137 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1138 LowLevelILExpression::new(
1139 self.function,
1140 LowLevelExpressionIndex(self.op.operands[0] as usize),
1141 )
1142 }
1143}
1144
1145impl<M, F> Debug for Operation<'_, M, F, Jump>
1146where
1147 M: FunctionMutability,
1148 F: FunctionForm,
1149{
1150 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1151 f.debug_struct("Jump")
1152 .field("target", &self.target())
1153 .finish()
1154 }
1155}
1156
1157pub struct JumpTo;
1159
1160struct TargetListIter<'func, M, F>
1161where
1162 M: FunctionMutability,
1163 F: FunctionForm,
1164{
1165 function: &'func LowLevelILFunction<M, F>,
1166 cursor: BNLowLevelILInstruction,
1167 cursor_operand: usize,
1168}
1169
1170impl<M, F> TargetListIter<'_, M, F>
1171where
1172 M: FunctionMutability,
1173 F: FunctionForm,
1174{
1175 fn next(&mut self) -> u64 {
1176 if self.cursor_operand >= 3 {
1177 self.cursor = unsafe {
1178 BNGetLowLevelILByIndex(self.function.handle, self.cursor.operands[3] as usize)
1179 };
1180 self.cursor_operand = 0;
1181 }
1182 let result = self.cursor.operands[self.cursor_operand];
1183 self.cursor_operand += 1;
1184 result
1185 }
1186}
1187
1188impl<'func, M, F> Operation<'func, M, F, JumpTo>
1189where
1190 M: FunctionMutability,
1191 F: FunctionForm,
1192{
1193 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1194 LowLevelILExpression::new(
1195 self.function,
1196 LowLevelExpressionIndex(self.op.operands[0] as usize),
1197 )
1198 }
1199
1200 pub fn target_list(&self) -> BTreeMap<u64, LowLevelInstructionIndex> {
1201 let mut result = BTreeMap::new();
1202 let count = self.op.operands[1] as usize / 2;
1203 let mut list = TargetListIter {
1204 function: self.function,
1205 cursor: unsafe {
1206 BNGetLowLevelILByIndex(self.function.handle, self.op.operands[2] as usize)
1207 },
1208 cursor_operand: 0,
1209 };
1210
1211 for _ in 0..count {
1212 let value = list.next();
1213 let target = LowLevelInstructionIndex(list.next() as usize);
1214 result.insert(value, target);
1215 }
1216
1217 result
1218 }
1219}
1220
1221impl<M, F> Debug for Operation<'_, M, F, JumpTo>
1222where
1223 M: FunctionMutability,
1224 F: FunctionForm,
1225{
1226 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1227 f.debug_struct("JumpTo")
1228 .field("target", &self.target())
1229 .field("target_list", &self.target_list())
1230 .finish()
1231 }
1232}
1233
1234pub struct Call;
1236
1237impl<'func, M, F> Operation<'func, M, F, Call>
1238where
1239 M: FunctionMutability,
1240 F: FunctionForm,
1241{
1242 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1243 LowLevelILExpression::new(
1244 self.function,
1245 LowLevelExpressionIndex(self.op.operands[0] as usize),
1246 )
1247 }
1248
1249 pub fn stack_adjust(&self) -> Option<u64> {
1250 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CALL_STACK_ADJUST;
1251
1252 if self.op.operation == LLIL_CALL_STACK_ADJUST {
1253 Some(self.op.operands[1])
1254 } else {
1255 None
1256 }
1257 }
1258}
1259
1260impl<M, F> Debug for Operation<'_, M, F, Call>
1261where
1262 M: FunctionMutability,
1263 F: FunctionForm,
1264{
1265 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1266 f.debug_struct("Call")
1267 .field("target", &self.target())
1268 .field("stack_adjust", &self.stack_adjust())
1269 .finish()
1270 }
1271}
1272
1273pub struct CallSsa;
1275
1276impl<'func, M, F> Operation<'func, M, F, CallSsa>
1277where
1278 M: FunctionMutability,
1279 F: FunctionForm,
1280{
1281 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1282 LowLevelILExpression::new(
1283 self.function,
1284 LowLevelExpressionIndex(self.op.operands[1] as usize),
1285 )
1286 }
1287
1288 pub fn output_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1292 LowLevelILExpression::new(
1293 self.function,
1294 LowLevelExpressionIndex(self.op.operands[0] as usize),
1295 )
1296 }
1297
1298 pub fn param_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1302 LowLevelILExpression::new(
1303 self.function,
1304 LowLevelExpressionIndex(self.op.operands[3] as usize),
1305 )
1306 }
1307
1308 pub fn stack_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1312 LowLevelILExpression::new(
1313 self.function,
1314 LowLevelExpressionIndex(self.op.operands[2] as usize),
1315 )
1316 }
1317}
1318
1319impl<M, F> Debug for Operation<'_, M, F, CallSsa>
1320where
1321 M: FunctionMutability,
1322 F: FunctionForm,
1323{
1324 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1325 f.debug_struct("CallSsa")
1326 .field("target", &self.target())
1327 .field("output_expr", &self.output_expr())
1328 .field("param_expr", &self.param_expr())
1329 .field("stack_expr", &self.stack_expr())
1330 .finish()
1331 }
1332}
1333
1334pub struct CallOutputSsa;
1336
1337impl<M, F> Operation<'_, M, F, CallOutputSsa>
1338where
1339 M: FunctionMutability,
1340 F: FunctionForm,
1341{
1342 pub fn dest_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1343 let operand_list = self.get_operand_list(1);
1344
1345 let paired_ssa_reg = |paired: &[u64]| {
1347 let raw_id = RegisterId(paired[0] as u32);
1348 let version = paired[1] as u32;
1349 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1350 .expect("Bad register ID");
1351 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1352 };
1353
1354 operand_list.chunks_exact(2).map(paired_ssa_reg).collect()
1355 }
1356
1357 pub fn dest_memory_version(&self) -> u64 {
1358 self.op.operands[0]
1359 }
1360}
1361
1362impl<M, F> Debug for Operation<'_, M, F, CallOutputSsa>
1363where
1364 M: FunctionMutability,
1365 F: FunctionForm,
1366{
1367 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1368 f.debug_struct("CallOutputSsa")
1369 .field("dest_regs", &self.dest_regs())
1370 .finish()
1371 }
1372}
1373
1374pub struct CallParamSsa;
1376
1377impl<'func, M, F> Operation<'func, M, F, CallParamSsa>
1378where
1379 M: FunctionMutability,
1380 F: FunctionForm,
1381{
1382 pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
1383 self.get_operand_list(0)
1384 .into_iter()
1385 .map(|val| LowLevelExpressionIndex(val as usize))
1386 .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
1387 .collect()
1388 }
1389}
1390
1391impl<M, F> Debug for Operation<'_, M, F, CallParamSsa>
1392where
1393 M: FunctionMutability,
1394 F: FunctionForm,
1395{
1396 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1397 f.debug_struct("CallParamSsa")
1398 .field("param_exprs", &self.param_exprs())
1399 .finish()
1400 }
1401}
1402
1403pub struct CallStackSsa;
1405
1406impl<M, F> Operation<'_, M, F, CallStackSsa>
1407where
1408 M: FunctionMutability,
1409 F: FunctionForm,
1410{
1411 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1412 let raw_id = RegisterId(self.op.operands[0] as u32);
1413 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1414 .expect("Bad register ID");
1415 let version = self.op.operands[1] as u32;
1416 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1417 }
1418}
1419
1420impl<M, F> Debug for Operation<'_, M, F, CallStackSsa>
1421where
1422 M: FunctionMutability,
1423 F: FunctionForm,
1424{
1425 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1426 f.debug_struct("CallStackSsa")
1427 .field("source_reg", &self.source_reg())
1428 .finish()
1429 }
1430}
1431
1432pub struct Ret;
1434
1435impl<'func, M, F> Operation<'func, M, F, Ret>
1436where
1437 M: FunctionMutability,
1438 F: FunctionForm,
1439{
1440 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1441 LowLevelILExpression::new(
1442 self.function,
1443 LowLevelExpressionIndex(self.op.operands[0] as usize),
1444 )
1445 }
1446}
1447
1448impl<M, F> Debug for Operation<'_, M, F, Ret>
1449where
1450 M: FunctionMutability,
1451 F: FunctionForm,
1452{
1453 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1454 f.debug_struct("Ret")
1455 .field("target", &self.target())
1456 .finish()
1457 }
1458}
1459
1460pub struct If;
1462
1463impl<'func, M, F> Operation<'func, M, F, If>
1464where
1465 M: FunctionMutability,
1466 F: FunctionForm,
1467{
1468 pub fn condition(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1469 LowLevelILExpression::new(
1470 self.function,
1471 LowLevelExpressionIndex(self.op.operands[0] as usize),
1472 )
1473 }
1474
1475 pub fn true_target(&self) -> LowLevelILInstruction<'func, M, F> {
1476 LowLevelILInstruction::new(
1477 self.function,
1478 LowLevelInstructionIndex(self.op.operands[1] as usize),
1479 )
1480 }
1481
1482 pub fn false_target(&self) -> LowLevelILInstruction<'func, M, F> {
1483 LowLevelILInstruction::new(
1484 self.function,
1485 LowLevelInstructionIndex(self.op.operands[2] as usize),
1486 )
1487 }
1488}
1489
1490impl<M, F> Debug for Operation<'_, M, F, If>
1491where
1492 M: FunctionMutability,
1493 F: FunctionForm,
1494{
1495 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1496 f.debug_struct("If")
1497 .field("condition", &self.condition())
1498 .field("true_target", &self.true_target())
1499 .field("false_target", &self.false_target())
1500 .finish()
1501 }
1502}
1503
1504pub struct Goto;
1506
1507impl<'func, M, F> Operation<'func, M, F, Goto>
1508where
1509 M: FunctionMutability,
1510 F: FunctionForm,
1511{
1512 pub fn target(&self) -> LowLevelILInstruction<'func, M, F> {
1513 LowLevelILInstruction::new(
1514 self.function,
1515 LowLevelInstructionIndex(self.op.operands[0] as usize),
1516 )
1517 }
1518}
1519
1520impl<M, F> Debug for Operation<'_, M, F, Goto>
1521where
1522 M: FunctionMutability,
1523 F: FunctionForm,
1524{
1525 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1526 f.debug_struct("Goto")
1527 .field("target", &self.target())
1528 .finish()
1529 }
1530}
1531
1532pub struct FlagCond;
1535
1536impl<M, F> Debug for Operation<'_, M, F, FlagCond>
1537where
1538 M: FunctionMutability,
1539 F: FunctionForm,
1540{
1541 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1542 f.debug_struct("FlagCond").finish()
1543 }
1544}
1545
1546pub struct FlagGroup;
1549
1550impl<M, F> Operation<'_, M, F, FlagGroup>
1551where
1552 M: FunctionMutability,
1553 F: FunctionForm,
1554{
1555 pub fn flag_group(&self) -> CoreFlagGroup {
1556 let id = self.op.operands[0] as u32;
1557 self.function
1558 .arch()
1559 .flag_group_from_id(FlagGroupId(id))
1560 .unwrap()
1561 }
1562}
1563
1564impl<M, F> Debug for Operation<'_, M, F, FlagGroup>
1565where
1566 M: FunctionMutability,
1567 F: FunctionForm,
1568{
1569 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1570 f.debug_struct("FlagGroup")
1571 .field("flag_group", &self.flag_group())
1572 .finish()
1573 }
1574}
1575
1576pub struct Trap;
1578
1579impl<M, F> Operation<'_, M, F, Trap>
1580where
1581 M: FunctionMutability,
1582 F: FunctionForm,
1583{
1584 pub fn vector(&self) -> u64 {
1585 self.op.operands[0]
1586 }
1587}
1588
1589impl<M, F> Debug for Operation<'_, M, F, Trap>
1590where
1591 M: FunctionMutability,
1592 F: FunctionForm,
1593{
1594 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1595 f.debug_struct("Trap")
1596 .field("vector", &self.vector())
1597 .finish()
1598 }
1599}
1600
1601pub struct RegPhi;
1603impl<M, F> Operation<'_, M, F, RegPhi>
1604where
1605 M: FunctionMutability,
1606 F: FunctionForm,
1607{
1608 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1609 let raw_id = RegisterId(self.op.operands[0] as u32);
1610 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1611 .expect("Bad register ID");
1612 let version = self.op.operands[1] as u32;
1613 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1614 }
1615
1616 pub fn source_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1617 let operand_list = self.get_operand_list(2);
1618 let arch = self.function.arch();
1619 operand_list
1620 .chunks_exact(2)
1621 .map(|chunk| {
1622 let (register, version) = (chunk[0], chunk[1]);
1623 LowLevelILSSARegisterKind::new_full(
1624 LowLevelILRegisterKind::from_raw(&arch, RegisterId(register as u32))
1625 .expect("Bad register ID"),
1626 version as u32,
1627 )
1628 })
1629 .collect()
1630 }
1631}
1632
1633impl<M, F> Debug for Operation<'_, M, F, RegPhi>
1634where
1635 M: FunctionMutability,
1636 F: FunctionForm,
1637{
1638 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1639 f.debug_struct("RegPhi")
1640 .field("dest_reg", &self.dest_reg())
1641 .field("source_regs", &self.source_regs())
1642 .finish()
1643 }
1644}
1645
1646pub struct FlagPhi;
1648
1649impl<M, F> Operation<'_, M, F, FlagPhi>
1650where
1651 M: FunctionMutability,
1652 F: FunctionForm,
1653{
1654 pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
1655 let flag = self
1656 .function
1657 .arch()
1658 .flag_from_id(FlagId(self.op.operands[0] as u32))
1659 .expect("Bad flag ID");
1660 let version = self.op.operands[1] as u32;
1661 LowLevelILSSAFlag::new(flag, version)
1662 }
1663
1664 pub fn source_flags(&self) -> Vec<LowLevelILSSAFlag<CoreFlag>> {
1665 let operand_list = self.get_operand_list(2);
1666 operand_list
1667 .chunks_exact(2)
1668 .map(|chunk| {
1669 let (flag, version) = (chunk[0], chunk[1]);
1670 let flag = self
1671 .function
1672 .arch()
1673 .flag_from_id(FlagId(flag as u32))
1674 .expect("Bad flag ID");
1675 LowLevelILSSAFlag::new(flag, version as u32)
1676 })
1677 .collect()
1678 }
1679}
1680
1681impl<M, F> Debug for Operation<'_, M, F, FlagPhi>
1682where
1683 M: FunctionMutability,
1684 F: FunctionForm,
1685{
1686 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1687 f.debug_struct("FlagPhi")
1688 .field("dest_flag", &self.dest_flag())
1689 .field("source_flags", &self.source_flags())
1690 .finish()
1691 }
1692}
1693
1694pub struct MemPhi;
1696
1697impl<M, F> Operation<'_, M, F, MemPhi>
1698where
1699 M: FunctionMutability,
1700 F: FunctionForm,
1701{
1702 pub fn dest_memory_version(&self) -> usize {
1703 self.op.operands[0] as usize
1704 }
1705
1706 pub fn source_memory_versions(&self) -> Vec<usize> {
1707 let operand_list = self.get_operand_list(1);
1708 operand_list.into_iter().map(|op| op as usize).collect()
1709 }
1710}
1711
1712impl<M, F> Debug for Operation<'_, M, F, MemPhi>
1713where
1714 M: FunctionMutability,
1715 F: FunctionForm,
1716{
1717 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1718 f.debug_struct("MemPhi")
1719 .field("dest_memory_version", &self.dest_memory_version())
1720 .field("source_memory_versions", &self.source_memory_versions())
1721 .finish()
1722 }
1723}
1724
1725pub struct Const;
1727
1728impl<M, F> Operation<'_, M, F, Const>
1729where
1730 M: FunctionMutability,
1731 F: FunctionForm,
1732{
1733 pub fn size(&self) -> usize {
1734 self.op.size
1735 }
1736
1737 pub fn value(&self) -> u64 {
1738 #[cfg(debug_assertions)]
1739 {
1740 let raw = self.op.operands[0] as i64;
1741
1742 let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1743 (_, true) => true,
1744 (res, false) => [-1, 0].contains(&res),
1745 };
1746
1747 if !is_safe {
1748 log::error!(
1749 "il expr @ {:x} contains constant 0x{:x} as {} byte value (doesn't fit!)",
1750 self.op.address,
1751 self.op.operands[0],
1752 self.op.size
1753 );
1754 }
1755 }
1756
1757 let mask: u64 = if self.op.size == 0 {
1758 1
1759 } else if self.op.size < mem::size_of::<u64>() {
1760 let m = -1i64 << (self.op.size * 8);
1761 !m as u64
1762 } else {
1763 (-1i64) as u64
1764 };
1765
1766 self.op.operands[0] & mask
1767 }
1768}
1769
1770impl<M, F> Debug for Operation<'_, M, F, Const>
1771where
1772 M: FunctionMutability,
1773 F: FunctionForm,
1774{
1775 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1776 f.debug_struct("Const")
1777 .field("size", &self.size())
1778 .field("value", &self.value())
1779 .finish()
1780 }
1781}
1782
1783pub struct FloatConst;
1785
1786impl<M, F> Operation<'_, M, F, FloatConst>
1787where
1788 M: FunctionMutability,
1789 F: FunctionForm,
1790{
1791 pub fn size(&self) -> usize {
1792 self.op.size
1793 }
1794
1795 pub fn raw_value(&self) -> u64 {
1796 self.op.operands[0]
1797 }
1798
1799 pub fn float_value(&self) -> f64 {
1800 let raw_bits = self.raw_value();
1801 match self.op.size {
1802 4 => {
1803 let bits32 = (raw_bits & 0xFFFFFFFF) as u32;
1805 f32::from_bits(bits32) as f64
1806 }
1807 8 => {
1808 f64::from_bits(raw_bits)
1810 }
1811 _ => {
1812 log::error!(
1814 "il expr @ {:x} has invalid float size {} (expected 4 or 8 bytes)",
1815 self.op.address,
1816 self.op.size
1817 );
1818 f64::NAN
1819 }
1820 }
1821 }
1822}
1823
1824impl<M, F> Debug for Operation<'_, M, F, FloatConst>
1825where
1826 M: FunctionMutability,
1827 F: FunctionForm,
1828{
1829 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1830 f.debug_struct("FloatConst")
1831 .field("size", &self.size())
1832 .field("float_value", &self.float_value())
1833 .field("raw_value", &self.raw_value())
1834 .finish()
1835 }
1836}
1837
1838pub struct Extern;
1840
1841impl<M, F> Operation<'_, M, F, Extern>
1842where
1843 M: FunctionMutability,
1844 F: FunctionForm,
1845{
1846 pub fn size(&self) -> usize {
1847 self.op.size
1848 }
1849
1850 pub fn value(&self) -> u64 {
1851 #[cfg(debug_assertions)]
1852 {
1853 let raw = self.op.operands[0] as i64;
1854
1855 let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1856 (_, true) => true,
1857 (res, false) => [-1, 0].contains(&res),
1858 };
1859
1860 if !is_safe {
1861 log::error!(
1862 "il expr @ {:x} contains extern 0x{:x} as {} byte value (doesn't fit!)",
1863 self.op.address,
1864 self.op.operands[0],
1865 self.op.size
1866 );
1867 }
1868 }
1869
1870 let mut mask = -1i64 as u64;
1871
1872 if self.op.size < mem::size_of::<u64>() {
1873 mask <<= self.op.size * 8;
1874 mask = !mask;
1875 }
1876
1877 self.op.operands[0] & mask
1878 }
1879}
1880
1881impl<M, F> Debug for Operation<'_, M, F, Extern>
1882where
1883 M: FunctionMutability,
1884 F: FunctionForm,
1885{
1886 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1887 f.debug_struct("Extern")
1888 .field("size", &self.size())
1889 .field("value", &self.value())
1890 .finish()
1891 }
1892}
1893
1894pub struct BinaryOp;
1900
1901impl<'func, M, F> Operation<'func, M, F, BinaryOp>
1902where
1903 M: FunctionMutability,
1904 F: FunctionForm,
1905{
1906 pub fn size(&self) -> usize {
1907 self.op.size
1908 }
1909
1910 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1911 LowLevelILExpression::new(
1912 self.function,
1913 LowLevelExpressionIndex(self.op.operands[0] as usize),
1914 )
1915 }
1916
1917 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1918 LowLevelILExpression::new(
1919 self.function,
1920 LowLevelExpressionIndex(self.op.operands[1] as usize),
1921 )
1922 }
1923}
1924
1925impl<M, F> Debug for Operation<'_, M, F, BinaryOp>
1926where
1927 M: FunctionMutability,
1928 F: FunctionForm,
1929{
1930 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1931 f.debug_struct("BinaryOp")
1932 .field("size", &self.size())
1933 .field("left", &self.left())
1934 .field("right", &self.right())
1935 .finish()
1936 }
1937}
1938
1939pub struct BinaryOpCarry;
1941
1942impl<'func, M, F> Operation<'func, M, F, BinaryOpCarry>
1943where
1944 M: FunctionMutability,
1945 F: FunctionForm,
1946{
1947 pub fn size(&self) -> usize {
1948 self.op.size
1949 }
1950
1951 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1952 LowLevelILExpression::new(
1953 self.function,
1954 LowLevelExpressionIndex(self.op.operands[0] as usize),
1955 )
1956 }
1957
1958 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1959 LowLevelILExpression::new(
1960 self.function,
1961 LowLevelExpressionIndex(self.op.operands[1] as usize),
1962 )
1963 }
1964
1965 pub fn carry(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1966 LowLevelILExpression::new(
1967 self.function,
1968 LowLevelExpressionIndex(self.op.operands[2] as usize),
1969 )
1970 }
1971}
1972
1973impl<M, F> Debug for Operation<'_, M, F, BinaryOpCarry>
1974where
1975 M: FunctionMutability,
1976 F: FunctionForm,
1977{
1978 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1979 f.debug_struct("BinaryOpCarry")
1980 .field("size", &self.size())
1981 .field("left", &self.left())
1982 .field("right", &self.right())
1983 .field("carry", &self.carry())
1984 .finish()
1985 }
1986}
1987
1988pub struct UnaryOp;
1991
1992impl<'func, M, F> Operation<'func, M, F, UnaryOp>
1993where
1994 M: FunctionMutability,
1995 F: FunctionForm,
1996{
1997 pub fn size(&self) -> usize {
1998 self.op.size
1999 }
2000
2001 pub fn operand(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2002 LowLevelILExpression::new(
2003 self.function,
2004 LowLevelExpressionIndex(self.op.operands[0] as usize),
2005 )
2006 }
2007}
2008
2009impl<M, F> Debug for Operation<'_, M, F, UnaryOp>
2010where
2011 M: FunctionMutability,
2012 F: FunctionForm,
2013{
2014 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2015 f.debug_struct("UnaryOp")
2016 .field("size", &self.size())
2017 .field("operand", &self.operand())
2018 .finish()
2019 }
2020}
2021
2022pub struct Condition;
2024
2025impl<'func, M, F> Operation<'func, M, F, Condition>
2026where
2027 M: FunctionMutability,
2028 F: FunctionForm,
2029{
2030 pub fn size(&self) -> usize {
2031 self.op.size
2032 }
2033
2034 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2035 LowLevelILExpression::new(
2036 self.function,
2037 LowLevelExpressionIndex(self.op.operands[0] as usize),
2038 )
2039 }
2040
2041 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2042 LowLevelILExpression::new(
2043 self.function,
2044 LowLevelExpressionIndex(self.op.operands[1] as usize),
2045 )
2046 }
2047}
2048
2049impl<M, F> Debug for Operation<'_, M, F, Condition>
2050where
2051 M: FunctionMutability,
2052 F: FunctionForm,
2053{
2054 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2055 f.debug_struct("Condition")
2056 .field("size", &self.size())
2057 .field("left", &self.left())
2058 .field("right", &self.right())
2059 .finish()
2060 }
2061}
2062
2063pub struct UnimplMem;
2065
2066impl<'func, M, F> Operation<'func, M, F, UnimplMem>
2067where
2068 M: FunctionMutability,
2069 F: FunctionForm,
2070{
2071 pub fn size(&self) -> usize {
2072 self.op.size
2073 }
2074
2075 pub fn mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2076 LowLevelILExpression::new(
2077 self.function,
2078 LowLevelExpressionIndex(self.op.operands[0] as usize),
2079 )
2080 }
2081}
2082
2083impl<M, F> Debug for Operation<'_, M, F, UnimplMem>
2084where
2085 M: FunctionMutability,
2086 F: FunctionForm,
2087{
2088 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2089 f.debug_struct("UnimplMem")
2090 .field("size", &self.size())
2091 .field("mem_expr", &self.mem_expr())
2092 .finish()
2093 }
2094}
2095
2096pub struct Assert;
2098
2099impl<M, F> Operation<'_, M, F, Assert>
2100where
2101 M: FunctionMutability,
2102 F: FunctionForm,
2103{
2104 pub fn size(&self) -> usize {
2105 self.op.size
2106 }
2107
2108 pub fn source_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2109 let raw_id = RegisterId(self.op.operands[0] as u32);
2110 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2111 }
2112
2113 pub fn constraint(&self) -> PossibleValueSet {
2114 self.get_constraint(1)
2115 }
2116}
2117
2118impl<M, F> Debug for Operation<'_, M, F, Assert>
2119where
2120 M: FunctionMutability,
2121 F: FunctionForm,
2122{
2123 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2124 f.debug_struct("Assert")
2125 .field("size", &self.size())
2126 .field("source_reg", &self.source_reg())
2127 .field("constraint", &self.constraint())
2128 .finish()
2129 }
2130}
2131
2132pub struct AssertSsa;
2134
2135impl<M, F> Operation<'_, M, F, AssertSsa>
2136where
2137 M: FunctionMutability,
2138 F: FunctionForm,
2139{
2140 pub fn size(&self) -> usize {
2141 self.op.size
2142 }
2143
2144 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2145 let raw_id = RegisterId(self.op.operands[0] as u32);
2146 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2147 .expect("Bad register ID");
2148 let version = self.op.operands[1] as u32;
2149 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2150 }
2151
2152 pub fn constraint(&self) -> PossibleValueSet {
2153 self.get_constraint(2)
2154 }
2155}
2156
2157impl<M, F> Debug for Operation<'_, M, F, AssertSsa>
2158where
2159 M: FunctionMutability,
2160 F: FunctionForm,
2161{
2162 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2163 f.debug_struct("AssertSsa")
2164 .field("size", &self.size())
2165 .field("source_reg", &self.source_reg())
2166 .field("constraint", &self.constraint())
2167 .finish()
2168 }
2169}
2170
2171pub struct ForceVersion;
2173
2174impl<M, F> Operation<'_, M, F, ForceVersion>
2175where
2176 M: FunctionMutability,
2177 F: FunctionForm,
2178{
2179 pub fn size(&self) -> usize {
2180 self.op.size
2181 }
2182
2183 pub fn dest_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2184 let raw_id = RegisterId(self.op.operands[0] as u32);
2185 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2186 }
2187}
2188
2189impl<M, F> Debug for Operation<'_, M, F, ForceVersion>
2190where
2191 M: FunctionMutability,
2192 F: FunctionForm,
2193{
2194 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2195 f.debug_struct("ForceVersion")
2196 .field("size", &self.size())
2197 .field("dest_reg", &self.dest_reg())
2198 .finish()
2199 }
2200}
2201
2202pub struct ForceVersionSsa;
2204
2205impl<M, F> Operation<'_, M, F, ForceVersionSsa>
2206where
2207 M: FunctionMutability,
2208 F: FunctionForm,
2209{
2210 pub fn size(&self) -> usize {
2211 self.op.size
2212 }
2213
2214 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2215 let raw_id = RegisterId(self.op.operands[0] as u32);
2216 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2217 .expect("Bad register ID");
2218 let version = self.op.operands[1] as u32;
2219 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2220 }
2221
2222 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2223 let raw_id = RegisterId(self.op.operands[2] as u32);
2224 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2225 .expect("Bad register ID");
2226 let version = self.op.operands[3] as u32;
2227 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2228 }
2229}
2230
2231impl<M, F> Debug for Operation<'_, M, F, ForceVersionSsa>
2232where
2233 M: FunctionMutability,
2234 F: FunctionForm,
2235{
2236 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2237 f.debug_struct("ForceVersionSsa")
2238 .field("size", &self.size())
2239 .field("dest_reg", &self.dest_reg())
2240 .field("source_reg", &self.source_reg())
2241 .finish()
2242 }
2243}
2244
2245pub struct SeparateParamListSsa;
2247
2248impl<'func, M, F> Operation<'func, M, F, SeparateParamListSsa>
2249where
2250 M: FunctionMutability,
2251 F: FunctionForm,
2252{
2253 pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
2254 self.get_operand_list(0)
2255 .into_iter()
2256 .map(|val| LowLevelExpressionIndex(val as usize))
2257 .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
2258 .collect()
2259 }
2260}
2261
2262impl<M, F> Debug for Operation<'_, M, F, SeparateParamListSsa>
2263where
2264 M: FunctionMutability,
2265 F: FunctionForm,
2266{
2267 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2268 f.debug_struct("SeparateParamListSsa")
2269 .field("param_exprs", &self.param_exprs())
2270 .finish()
2271 }
2272}
2273
2274pub trait OperationArguments: 'static {}
2277
2278impl OperationArguments for NoArgs {}
2279impl OperationArguments for Pop {}
2280impl OperationArguments for Syscall {}
2281impl OperationArguments for SyscallSsa {}
2282impl OperationArguments for Intrinsic {}
2283impl OperationArguments for SetReg {}
2284impl OperationArguments for SetRegSsa {}
2285impl OperationArguments for SetRegPartialSsa {}
2286impl OperationArguments for SetRegSplit {}
2287impl OperationArguments for SetRegSplitSsa {}
2288impl OperationArguments for SetFlag {}
2289impl OperationArguments for SetFlagSsa {}
2290impl OperationArguments for Load {}
2291impl OperationArguments for LoadSsa {}
2292impl OperationArguments for Store {}
2293impl OperationArguments for StoreSsa {}
2294impl OperationArguments for Reg {}
2295impl OperationArguments for RegSsa {}
2296impl OperationArguments for RegPartialSsa {}
2297impl OperationArguments for RegSplit {}
2298impl OperationArguments for RegSplitSsa {}
2299impl OperationArguments for RegStackPush {}
2300impl OperationArguments for RegStackPop {}
2301impl OperationArguments for RegStackFreeReg {}
2302impl OperationArguments for Flag {}
2303impl OperationArguments for FlagBit {}
2304impl OperationArguments for Jump {}
2305impl OperationArguments for JumpTo {}
2306impl OperationArguments for Call {}
2307impl OperationArguments for CallSsa {}
2308impl OperationArguments for CallOutputSsa {}
2309impl OperationArguments for CallParamSsa {}
2310impl OperationArguments for CallStackSsa {}
2311impl OperationArguments for Ret {}
2312impl OperationArguments for If {}
2313impl OperationArguments for Goto {}
2314impl OperationArguments for FlagCond {}
2315impl OperationArguments for FlagGroup {}
2316impl OperationArguments for Trap {}
2317impl OperationArguments for RegPhi {}
2318impl OperationArguments for FlagPhi {}
2319impl OperationArguments for MemPhi {}
2320impl OperationArguments for Const {}
2321impl OperationArguments for FloatConst {}
2322impl OperationArguments for Extern {}
2323impl OperationArguments for BinaryOp {}
2324impl OperationArguments for BinaryOpCarry {}
2325impl OperationArguments for UnaryOp {}
2326impl OperationArguments for Condition {}
2327impl OperationArguments for UnimplMem {}
2328impl OperationArguments for Assert {}
2329impl OperationArguments for AssertSsa {}
2330impl OperationArguments for ForceVersion {}
2331impl OperationArguments for ForceVersionSsa {}
2332impl OperationArguments for SeparateParamListSsa {}