1use binaryninjacore_sys::{
16 BNGetCachedLowLevelILPossibleValueSet, BNLowLevelILFreeOperandList, BNLowLevelILGetOperandList,
17 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<'func, M, F> Operation<'func, 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<'func, 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_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), full_raw_id)
417 .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_kind, version, partial_reg)
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_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), full_raw_id)
872 .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_kind, version, partial_reg)
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 high_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 low_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("high_reg", &self.high_reg())
926 .field("low_reg", &self.low_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 high_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 low_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("high_reg", &self.high_reg())
970 .field("low_reg", &self.low_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
1160impl<'func, M, F> Operation<'func, M, F, JumpTo>
1161where
1162 M: FunctionMutability,
1163 F: FunctionForm,
1164{
1165 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1166 LowLevelILExpression::new(
1167 self.function,
1168 LowLevelExpressionIndex(self.op.operands[0] as usize),
1169 )
1170 }
1171
1172 pub fn target_list(&self) -> BTreeMap<u64, LowLevelInstructionIndex> {
1173 self.get_operand_list(1)
1174 .as_chunks::<2>()
1175 .0
1176 .iter()
1177 .map(|pair| (pair[0], LowLevelInstructionIndex(pair[1] as usize)))
1178 .collect()
1179 }
1180}
1181
1182impl<M, F> Debug for Operation<'_, M, F, JumpTo>
1183where
1184 M: FunctionMutability,
1185 F: FunctionForm,
1186{
1187 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1188 f.debug_struct("JumpTo")
1189 .field("target", &self.target())
1190 .field("target_list", &self.target_list())
1191 .finish()
1192 }
1193}
1194
1195pub struct Call;
1197
1198impl<'func, M, F> Operation<'func, M, F, Call>
1199where
1200 M: FunctionMutability,
1201 F: FunctionForm,
1202{
1203 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1204 LowLevelILExpression::new(
1205 self.function,
1206 LowLevelExpressionIndex(self.op.operands[0] as usize),
1207 )
1208 }
1209
1210 pub fn stack_adjust(&self) -> Option<u64> {
1211 use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CALL_STACK_ADJUST;
1212
1213 if self.op.operation == LLIL_CALL_STACK_ADJUST {
1214 Some(self.op.operands[1])
1215 } else {
1216 None
1217 }
1218 }
1219}
1220
1221impl<M, F> Debug for Operation<'_, M, F, Call>
1222where
1223 M: FunctionMutability,
1224 F: FunctionForm,
1225{
1226 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1227 f.debug_struct("Call")
1228 .field("target", &self.target())
1229 .field("stack_adjust", &self.stack_adjust())
1230 .finish()
1231 }
1232}
1233
1234pub struct CallSsa;
1236
1237impl<'func, M, F> Operation<'func, M, F, CallSsa>
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[1] as usize),
1246 )
1247 }
1248
1249 pub fn output_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1253 LowLevelILExpression::new(
1254 self.function,
1255 LowLevelExpressionIndex(self.op.operands[0] as usize),
1256 )
1257 }
1258
1259 pub fn param_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1263 LowLevelILExpression::new(
1264 self.function,
1265 LowLevelExpressionIndex(self.op.operands[3] as usize),
1266 )
1267 }
1268
1269 pub fn stack_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1273 LowLevelILExpression::new(
1274 self.function,
1275 LowLevelExpressionIndex(self.op.operands[2] as usize),
1276 )
1277 }
1278}
1279
1280impl<M, F> Debug for Operation<'_, M, F, CallSsa>
1281where
1282 M: FunctionMutability,
1283 F: FunctionForm,
1284{
1285 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1286 f.debug_struct("CallSsa")
1287 .field("target", &self.target())
1288 .field("output_expr", &self.output_expr())
1289 .field("param_expr", &self.param_expr())
1290 .field("stack_expr", &self.stack_expr())
1291 .finish()
1292 }
1293}
1294
1295pub struct CallOutputSsa;
1297
1298impl<M, F> Operation<'_, M, F, CallOutputSsa>
1299where
1300 M: FunctionMutability,
1301 F: FunctionForm,
1302{
1303 pub fn dest_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1304 let operand_list = self.get_operand_list(1);
1305
1306 let paired_ssa_reg = |paired: &[u64; 2]| {
1308 let raw_id = RegisterId(paired[0] as u32);
1309 let version = paired[1] as u32;
1310 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1311 .expect("Bad register ID");
1312 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1313 };
1314
1315 operand_list
1316 .as_chunks::<2>()
1317 .0
1318 .iter()
1319 .map(paired_ssa_reg)
1320 .collect()
1321 }
1322
1323 pub fn dest_memory_version(&self) -> u64 {
1324 self.op.operands[0]
1325 }
1326}
1327
1328impl<M, F> Debug for Operation<'_, M, F, CallOutputSsa>
1329where
1330 M: FunctionMutability,
1331 F: FunctionForm,
1332{
1333 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1334 f.debug_struct("CallOutputSsa")
1335 .field("dest_regs", &self.dest_regs())
1336 .finish()
1337 }
1338}
1339
1340pub struct CallParamSsa;
1342
1343impl<'func, M, F> Operation<'func, M, F, CallParamSsa>
1344where
1345 M: FunctionMutability,
1346 F: FunctionForm,
1347{
1348 pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
1349 self.get_operand_list(0)
1350 .into_iter()
1351 .map(|val| LowLevelExpressionIndex(val as usize))
1352 .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
1353 .collect()
1354 }
1355}
1356
1357impl<M, F> Debug for Operation<'_, M, F, CallParamSsa>
1358where
1359 M: FunctionMutability,
1360 F: FunctionForm,
1361{
1362 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1363 f.debug_struct("CallParamSsa")
1364 .field("param_exprs", &self.param_exprs())
1365 .finish()
1366 }
1367}
1368
1369pub struct CallStackSsa;
1371
1372impl<M, F> Operation<'_, M, F, CallStackSsa>
1373where
1374 M: FunctionMutability,
1375 F: FunctionForm,
1376{
1377 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1378 let raw_id = RegisterId(self.op.operands[0] as u32);
1379 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1380 .expect("Bad register ID");
1381 let version = self.op.operands[1] as u32;
1382 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1383 }
1384}
1385
1386impl<M, F> Debug for Operation<'_, M, F, CallStackSsa>
1387where
1388 M: FunctionMutability,
1389 F: FunctionForm,
1390{
1391 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1392 f.debug_struct("CallStackSsa")
1393 .field("source_reg", &self.source_reg())
1394 .finish()
1395 }
1396}
1397
1398pub struct Ret;
1400
1401impl<'func, M, F> Operation<'func, M, F, Ret>
1402where
1403 M: FunctionMutability,
1404 F: FunctionForm,
1405{
1406 pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1407 LowLevelILExpression::new(
1408 self.function,
1409 LowLevelExpressionIndex(self.op.operands[0] as usize),
1410 )
1411 }
1412}
1413
1414impl<M, F> Debug for Operation<'_, M, F, Ret>
1415where
1416 M: FunctionMutability,
1417 F: FunctionForm,
1418{
1419 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1420 f.debug_struct("Ret")
1421 .field("target", &self.target())
1422 .finish()
1423 }
1424}
1425
1426pub struct If;
1428
1429impl<'func, M, F> Operation<'func, M, F, If>
1430where
1431 M: FunctionMutability,
1432 F: FunctionForm,
1433{
1434 pub fn condition(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1435 LowLevelILExpression::new(
1436 self.function,
1437 LowLevelExpressionIndex(self.op.operands[0] as usize),
1438 )
1439 }
1440
1441 pub fn true_target(&self) -> LowLevelILInstruction<'func, M, F> {
1442 LowLevelILInstruction::new(
1443 self.function,
1444 LowLevelInstructionIndex(self.op.operands[1] as usize),
1445 )
1446 }
1447
1448 pub fn false_target(&self) -> LowLevelILInstruction<'func, M, F> {
1449 LowLevelILInstruction::new(
1450 self.function,
1451 LowLevelInstructionIndex(self.op.operands[2] as usize),
1452 )
1453 }
1454}
1455
1456impl<M, F> Debug for Operation<'_, M, F, If>
1457where
1458 M: FunctionMutability,
1459 F: FunctionForm,
1460{
1461 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1462 f.debug_struct("If")
1463 .field("condition", &self.condition())
1464 .field("true_target", &self.true_target())
1465 .field("false_target", &self.false_target())
1466 .finish()
1467 }
1468}
1469
1470pub struct Goto;
1472
1473impl<'func, M, F> Operation<'func, M, F, Goto>
1474where
1475 M: FunctionMutability,
1476 F: FunctionForm,
1477{
1478 pub fn target(&self) -> LowLevelILInstruction<'func, M, F> {
1479 LowLevelILInstruction::new(
1480 self.function,
1481 LowLevelInstructionIndex(self.op.operands[0] as usize),
1482 )
1483 }
1484}
1485
1486impl<M, F> Debug for Operation<'_, M, F, Goto>
1487where
1488 M: FunctionMutability,
1489 F: FunctionForm,
1490{
1491 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1492 f.debug_struct("Goto")
1493 .field("target", &self.target())
1494 .finish()
1495 }
1496}
1497
1498pub struct FlagCond;
1501
1502impl<M, F> Debug for Operation<'_, M, F, FlagCond>
1503where
1504 M: FunctionMutability,
1505 F: FunctionForm,
1506{
1507 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1508 f.debug_struct("FlagCond").finish()
1509 }
1510}
1511
1512pub struct FlagGroup;
1515
1516impl<M, F> Operation<'_, M, F, FlagGroup>
1517where
1518 M: FunctionMutability,
1519 F: FunctionForm,
1520{
1521 pub fn flag_group(&self) -> CoreFlagGroup {
1522 let id = self.op.operands[0] as u32;
1523 self.function
1524 .arch()
1525 .flag_group_from_id(FlagGroupId(id))
1526 .unwrap()
1527 }
1528}
1529
1530impl<M, F> Debug for Operation<'_, M, F, FlagGroup>
1531where
1532 M: FunctionMutability,
1533 F: FunctionForm,
1534{
1535 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1536 f.debug_struct("FlagGroup")
1537 .field("flag_group", &self.flag_group())
1538 .finish()
1539 }
1540}
1541
1542pub struct Trap;
1544
1545impl<M, F> Operation<'_, M, F, Trap>
1546where
1547 M: FunctionMutability,
1548 F: FunctionForm,
1549{
1550 pub fn vector(&self) -> u64 {
1551 self.op.operands[0]
1552 }
1553}
1554
1555impl<M, F> Debug for Operation<'_, M, F, Trap>
1556where
1557 M: FunctionMutability,
1558 F: FunctionForm,
1559{
1560 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1561 f.debug_struct("Trap")
1562 .field("vector", &self.vector())
1563 .finish()
1564 }
1565}
1566
1567pub struct RegPhi;
1569impl<M, F> Operation<'_, M, F, RegPhi>
1570where
1571 M: FunctionMutability,
1572 F: FunctionForm,
1573{
1574 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1575 let raw_id = RegisterId(self.op.operands[0] as u32);
1576 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1577 .expect("Bad register ID");
1578 let version = self.op.operands[1] as u32;
1579 LowLevelILSSARegisterKind::new_full(reg_kind, version)
1580 }
1581
1582 pub fn source_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1583 let operand_list = self.get_operand_list(2);
1584 let arch = self.function.arch();
1585 operand_list
1586 .as_chunks::<2>()
1587 .0
1588 .iter()
1589 .map(|chunk| {
1590 let (register, version) = (chunk[0], chunk[1]);
1591 LowLevelILSSARegisterKind::new_full(
1592 LowLevelILRegisterKind::from_raw(&arch, RegisterId(register as u32))
1593 .expect("Bad register ID"),
1594 version as u32,
1595 )
1596 })
1597 .collect()
1598 }
1599}
1600
1601impl<M, F> Debug for Operation<'_, M, F, RegPhi>
1602where
1603 M: FunctionMutability,
1604 F: FunctionForm,
1605{
1606 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1607 f.debug_struct("RegPhi")
1608 .field("dest_reg", &self.dest_reg())
1609 .field("source_regs", &self.source_regs())
1610 .finish()
1611 }
1612}
1613
1614pub struct FlagPhi;
1616
1617impl<M, F> Operation<'_, M, F, FlagPhi>
1618where
1619 M: FunctionMutability,
1620 F: FunctionForm,
1621{
1622 pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
1623 let flag = self
1624 .function
1625 .arch()
1626 .flag_from_id(FlagId(self.op.operands[0] as u32))
1627 .expect("Bad flag ID");
1628 let version = self.op.operands[1] as u32;
1629 LowLevelILSSAFlag::new(flag, version)
1630 }
1631
1632 pub fn source_flags(&self) -> Vec<LowLevelILSSAFlag<CoreFlag>> {
1633 let operand_list = self.get_operand_list(2);
1634 operand_list
1635 .as_chunks::<2>()
1636 .0
1637 .iter()
1638 .map(|chunk| {
1639 let (flag, version) = (chunk[0], chunk[1]);
1640 let flag = self
1641 .function
1642 .arch()
1643 .flag_from_id(FlagId(flag as u32))
1644 .expect("Bad flag ID");
1645 LowLevelILSSAFlag::new(flag, version as u32)
1646 })
1647 .collect()
1648 }
1649}
1650
1651impl<M, F> Debug for Operation<'_, M, F, FlagPhi>
1652where
1653 M: FunctionMutability,
1654 F: FunctionForm,
1655{
1656 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1657 f.debug_struct("FlagPhi")
1658 .field("dest_flag", &self.dest_flag())
1659 .field("source_flags", &self.source_flags())
1660 .finish()
1661 }
1662}
1663
1664pub struct MemPhi;
1666
1667impl<M, F> Operation<'_, M, F, MemPhi>
1668where
1669 M: FunctionMutability,
1670 F: FunctionForm,
1671{
1672 pub fn dest_memory_version(&self) -> usize {
1673 self.op.operands[0] as usize
1674 }
1675
1676 pub fn source_memory_versions(&self) -> Vec<usize> {
1677 let operand_list = self.get_operand_list(1);
1678 operand_list.into_iter().map(|op| op as usize).collect()
1679 }
1680}
1681
1682impl<M, F> Debug for Operation<'_, M, F, MemPhi>
1683where
1684 M: FunctionMutability,
1685 F: FunctionForm,
1686{
1687 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1688 f.debug_struct("MemPhi")
1689 .field("dest_memory_version", &self.dest_memory_version())
1690 .field("source_memory_versions", &self.source_memory_versions())
1691 .finish()
1692 }
1693}
1694
1695pub struct Const;
1697
1698impl<M, F> Operation<'_, M, F, Const>
1699where
1700 M: FunctionMutability,
1701 F: FunctionForm,
1702{
1703 pub fn size(&self) -> usize {
1704 self.op.size
1705 }
1706
1707 pub fn value(&self) -> u64 {
1708 #[cfg(debug_assertions)]
1709 {
1710 let raw = self.op.operands[0] as i64;
1711
1712 let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1713 (_, true) => true,
1714 (res, false) => [-1, 0].contains(&res),
1715 };
1716
1717 if !is_safe {
1718 tracing::error!(
1719 "il expr @ {:x} contains constant 0x{:x} as {} byte value (doesn't fit!)",
1720 self.op.address,
1721 self.op.operands[0],
1722 self.op.size
1723 );
1724 }
1725 }
1726
1727 let mask: u64 = if self.op.size == 0 {
1728 1
1729 } else if self.op.size < mem::size_of::<u64>() {
1730 let m = -1i64 << (self.op.size * 8);
1731 !m as u64
1732 } else {
1733 (-1i64) as u64
1734 };
1735
1736 self.op.operands[0] & mask
1737 }
1738}
1739
1740impl<M, F> Debug for Operation<'_, M, F, Const>
1741where
1742 M: FunctionMutability,
1743 F: FunctionForm,
1744{
1745 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1746 f.debug_struct("Const")
1747 .field("size", &self.size())
1748 .field("value", &self.value())
1749 .finish()
1750 }
1751}
1752
1753pub struct FloatConst;
1755
1756impl<M, F> Operation<'_, M, F, FloatConst>
1757where
1758 M: FunctionMutability,
1759 F: FunctionForm,
1760{
1761 pub fn size(&self) -> usize {
1762 self.op.size
1763 }
1764
1765 pub fn raw_value(&self) -> u64 {
1766 self.op.operands[0]
1767 }
1768
1769 pub fn float_value(&self) -> f64 {
1770 let raw_bits = self.raw_value();
1771 match self.op.size {
1772 4 => {
1773 let bits32 = (raw_bits & 0xFFFFFFFF) as u32;
1775 f32::from_bits(bits32) as f64
1776 }
1777 8 => {
1778 f64::from_bits(raw_bits)
1780 }
1781 _ => {
1782 tracing::error!(
1784 "il expr @ {:x} has invalid float size {} (expected 4 or 8 bytes)",
1785 self.op.address,
1786 self.op.size
1787 );
1788 f64::NAN
1789 }
1790 }
1791 }
1792}
1793
1794impl<M, F> Debug for Operation<'_, M, F, FloatConst>
1795where
1796 M: FunctionMutability,
1797 F: FunctionForm,
1798{
1799 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1800 f.debug_struct("FloatConst")
1801 .field("size", &self.size())
1802 .field("float_value", &self.float_value())
1803 .field("raw_value", &self.raw_value())
1804 .finish()
1805 }
1806}
1807
1808pub struct Extern;
1810
1811impl<M, F> Operation<'_, M, F, Extern>
1812where
1813 M: FunctionMutability,
1814 F: FunctionForm,
1815{
1816 pub fn size(&self) -> usize {
1817 self.op.size
1818 }
1819
1820 pub fn value(&self) -> u64 {
1821 #[cfg(debug_assertions)]
1822 {
1823 let raw = self.op.operands[0] as i64;
1824
1825 let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1826 (_, true) => true,
1827 (res, false) => [-1, 0].contains(&res),
1828 };
1829
1830 if !is_safe {
1831 tracing::error!(
1832 "il expr @ {:x} contains extern 0x{:x} as {} byte value (doesn't fit!)",
1833 self.op.address,
1834 self.op.operands[0],
1835 self.op.size
1836 );
1837 }
1838 }
1839
1840 let mut mask = -1i64 as u64;
1841
1842 if self.op.size < mem::size_of::<u64>() {
1843 mask <<= self.op.size * 8;
1844 mask = !mask;
1845 }
1846
1847 self.op.operands[0] & mask
1848 }
1849}
1850
1851impl<M, F> Debug for Operation<'_, M, F, Extern>
1852where
1853 M: FunctionMutability,
1854 F: FunctionForm,
1855{
1856 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1857 f.debug_struct("Extern")
1858 .field("size", &self.size())
1859 .field("value", &self.value())
1860 .finish()
1861 }
1862}
1863
1864pub struct BinaryOp;
1870
1871impl<'func, M, F> Operation<'func, M, F, BinaryOp>
1872where
1873 M: FunctionMutability,
1874 F: FunctionForm,
1875{
1876 pub fn size(&self) -> usize {
1877 self.op.size
1878 }
1879
1880 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1881 LowLevelILExpression::new(
1882 self.function,
1883 LowLevelExpressionIndex(self.op.operands[0] as usize),
1884 )
1885 }
1886
1887 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1888 LowLevelILExpression::new(
1889 self.function,
1890 LowLevelExpressionIndex(self.op.operands[1] as usize),
1891 )
1892 }
1893}
1894
1895impl<M, F> Debug for Operation<'_, M, F, BinaryOp>
1896where
1897 M: FunctionMutability,
1898 F: FunctionForm,
1899{
1900 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1901 f.debug_struct("BinaryOp")
1902 .field("size", &self.size())
1903 .field("left", &self.left())
1904 .field("right", &self.right())
1905 .finish()
1906 }
1907}
1908
1909pub struct BinaryOpCarry;
1911
1912impl<'func, M, F> Operation<'func, M, F, BinaryOpCarry>
1913where
1914 M: FunctionMutability,
1915 F: FunctionForm,
1916{
1917 pub fn size(&self) -> usize {
1918 self.op.size
1919 }
1920
1921 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1922 LowLevelILExpression::new(
1923 self.function,
1924 LowLevelExpressionIndex(self.op.operands[0] as usize),
1925 )
1926 }
1927
1928 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1929 LowLevelILExpression::new(
1930 self.function,
1931 LowLevelExpressionIndex(self.op.operands[1] as usize),
1932 )
1933 }
1934
1935 pub fn carry(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1936 LowLevelILExpression::new(
1937 self.function,
1938 LowLevelExpressionIndex(self.op.operands[2] as usize),
1939 )
1940 }
1941}
1942
1943impl<M, F> Debug for Operation<'_, M, F, BinaryOpCarry>
1944where
1945 M: FunctionMutability,
1946 F: FunctionForm,
1947{
1948 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1949 f.debug_struct("BinaryOpCarry")
1950 .field("size", &self.size())
1951 .field("left", &self.left())
1952 .field("right", &self.right())
1953 .field("carry", &self.carry())
1954 .finish()
1955 }
1956}
1957
1958pub struct UnaryOp;
1961
1962impl<'func, M, F> Operation<'func, M, F, UnaryOp>
1963where
1964 M: FunctionMutability,
1965 F: FunctionForm,
1966{
1967 pub fn size(&self) -> usize {
1968 self.op.size
1969 }
1970
1971 pub fn operand(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1972 LowLevelILExpression::new(
1973 self.function,
1974 LowLevelExpressionIndex(self.op.operands[0] as usize),
1975 )
1976 }
1977}
1978
1979impl<M, F> Debug for Operation<'_, M, F, UnaryOp>
1980where
1981 M: FunctionMutability,
1982 F: FunctionForm,
1983{
1984 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1985 f.debug_struct("UnaryOp")
1986 .field("size", &self.size())
1987 .field("operand", &self.operand())
1988 .finish()
1989 }
1990}
1991
1992pub struct Condition;
1994
1995impl<'func, M, F> Operation<'func, M, F, Condition>
1996where
1997 M: FunctionMutability,
1998 F: FunctionForm,
1999{
2000 pub fn size(&self) -> usize {
2001 self.op.size
2002 }
2003
2004 pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2005 LowLevelILExpression::new(
2006 self.function,
2007 LowLevelExpressionIndex(self.op.operands[0] as usize),
2008 )
2009 }
2010
2011 pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2012 LowLevelILExpression::new(
2013 self.function,
2014 LowLevelExpressionIndex(self.op.operands[1] as usize),
2015 )
2016 }
2017}
2018
2019impl<M, F> Debug for Operation<'_, M, F, Condition>
2020where
2021 M: FunctionMutability,
2022 F: FunctionForm,
2023{
2024 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2025 f.debug_struct("Condition")
2026 .field("size", &self.size())
2027 .field("left", &self.left())
2028 .field("right", &self.right())
2029 .finish()
2030 }
2031}
2032
2033pub struct UnimplMem;
2035
2036impl<'func, M, F> Operation<'func, M, F, UnimplMem>
2037where
2038 M: FunctionMutability,
2039 F: FunctionForm,
2040{
2041 pub fn size(&self) -> usize {
2042 self.op.size
2043 }
2044
2045 pub fn mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2046 LowLevelILExpression::new(
2047 self.function,
2048 LowLevelExpressionIndex(self.op.operands[0] as usize),
2049 )
2050 }
2051}
2052
2053impl<M, F> Debug for Operation<'_, M, F, UnimplMem>
2054where
2055 M: FunctionMutability,
2056 F: FunctionForm,
2057{
2058 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2059 f.debug_struct("UnimplMem")
2060 .field("size", &self.size())
2061 .field("mem_expr", &self.mem_expr())
2062 .finish()
2063 }
2064}
2065
2066pub struct Assert;
2068
2069impl<M, F> Operation<'_, M, F, Assert>
2070where
2071 M: FunctionMutability,
2072 F: FunctionForm,
2073{
2074 pub fn size(&self) -> usize {
2075 self.op.size
2076 }
2077
2078 pub fn source_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2079 let raw_id = RegisterId(self.op.operands[0] as u32);
2080 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2081 }
2082
2083 pub fn constraint(&self) -> PossibleValueSet {
2084 self.get_constraint(1)
2085 }
2086}
2087
2088impl<M, F> Debug for Operation<'_, M, F, Assert>
2089where
2090 M: FunctionMutability,
2091 F: FunctionForm,
2092{
2093 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2094 f.debug_struct("Assert")
2095 .field("size", &self.size())
2096 .field("source_reg", &self.source_reg())
2097 .field("constraint", &self.constraint())
2098 .finish()
2099 }
2100}
2101
2102pub struct AssertSsa;
2104
2105impl<M, F> Operation<'_, M, F, AssertSsa>
2106where
2107 M: FunctionMutability,
2108 F: FunctionForm,
2109{
2110 pub fn size(&self) -> usize {
2111 self.op.size
2112 }
2113
2114 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2115 let raw_id = RegisterId(self.op.operands[0] as u32);
2116 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2117 .expect("Bad register ID");
2118 let version = self.op.operands[1] as u32;
2119 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2120 }
2121
2122 pub fn constraint(&self) -> PossibleValueSet {
2123 self.get_constraint(2)
2124 }
2125}
2126
2127impl<M, F> Debug for Operation<'_, M, F, AssertSsa>
2128where
2129 M: FunctionMutability,
2130 F: FunctionForm,
2131{
2132 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2133 f.debug_struct("AssertSsa")
2134 .field("size", &self.size())
2135 .field("source_reg", &self.source_reg())
2136 .field("constraint", &self.constraint())
2137 .finish()
2138 }
2139}
2140
2141pub struct ForceVersion;
2143
2144impl<M, F> Operation<'_, M, F, ForceVersion>
2145where
2146 M: FunctionMutability,
2147 F: FunctionForm,
2148{
2149 pub fn size(&self) -> usize {
2150 self.op.size
2151 }
2152
2153 pub fn dest_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2154 let raw_id = RegisterId(self.op.operands[0] as u32);
2155 LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2156 }
2157}
2158
2159impl<M, F> Debug for Operation<'_, M, F, ForceVersion>
2160where
2161 M: FunctionMutability,
2162 F: FunctionForm,
2163{
2164 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2165 f.debug_struct("ForceVersion")
2166 .field("size", &self.size())
2167 .field("dest_reg", &self.dest_reg())
2168 .finish()
2169 }
2170}
2171
2172pub struct ForceVersionSsa;
2174
2175impl<M, F> Operation<'_, M, F, ForceVersionSsa>
2176where
2177 M: FunctionMutability,
2178 F: FunctionForm,
2179{
2180 pub fn size(&self) -> usize {
2181 self.op.size
2182 }
2183
2184 pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2185 let raw_id = RegisterId(self.op.operands[0] as u32);
2186 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2187 .expect("Bad register ID");
2188 let version = self.op.operands[1] as u32;
2189 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2190 }
2191
2192 pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2193 let raw_id = RegisterId(self.op.operands[2] as u32);
2194 let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2195 .expect("Bad register ID");
2196 let version = self.op.operands[3] as u32;
2197 LowLevelILSSARegisterKind::new_full(reg_kind, version)
2198 }
2199}
2200
2201impl<M, F> Debug for Operation<'_, M, F, ForceVersionSsa>
2202where
2203 M: FunctionMutability,
2204 F: FunctionForm,
2205{
2206 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2207 f.debug_struct("ForceVersionSsa")
2208 .field("size", &self.size())
2209 .field("dest_reg", &self.dest_reg())
2210 .field("source_reg", &self.source_reg())
2211 .finish()
2212 }
2213}
2214
2215pub struct SeparateParamListSsa;
2217
2218impl<'func, M, F> Operation<'func, M, F, SeparateParamListSsa>
2219where
2220 M: FunctionMutability,
2221 F: FunctionForm,
2222{
2223 pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
2224 self.get_operand_list(0)
2225 .into_iter()
2226 .map(|val| LowLevelExpressionIndex(val as usize))
2227 .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
2228 .collect()
2229 }
2230}
2231
2232impl<M, F> Debug for Operation<'_, M, F, SeparateParamListSsa>
2233where
2234 M: FunctionMutability,
2235 F: FunctionForm,
2236{
2237 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2238 f.debug_struct("SeparateParamListSsa")
2239 .field("param_exprs", &self.param_exprs())
2240 .finish()
2241 }
2242}
2243
2244pub trait OperationArguments: 'static {}
2247
2248impl OperationArguments for NoArgs {}
2249impl OperationArguments for Pop {}
2250impl OperationArguments for Syscall {}
2251impl OperationArguments for SyscallSsa {}
2252impl OperationArguments for Intrinsic {}
2253impl OperationArguments for SetReg {}
2254impl OperationArguments for SetRegSsa {}
2255impl OperationArguments for SetRegPartialSsa {}
2256impl OperationArguments for SetRegSplit {}
2257impl OperationArguments for SetRegSplitSsa {}
2258impl OperationArguments for SetFlag {}
2259impl OperationArguments for SetFlagSsa {}
2260impl OperationArguments for Load {}
2261impl OperationArguments for LoadSsa {}
2262impl OperationArguments for Store {}
2263impl OperationArguments for StoreSsa {}
2264impl OperationArguments for Reg {}
2265impl OperationArguments for RegSsa {}
2266impl OperationArguments for RegPartialSsa {}
2267impl OperationArguments for RegSplit {}
2268impl OperationArguments for RegSplitSsa {}
2269impl OperationArguments for RegStackPush {}
2270impl OperationArguments for RegStackPop {}
2271impl OperationArguments for RegStackFreeReg {}
2272impl OperationArguments for Flag {}
2273impl OperationArguments for FlagBit {}
2274impl OperationArguments for Jump {}
2275impl OperationArguments for JumpTo {}
2276impl OperationArguments for Call {}
2277impl OperationArguments for CallSsa {}
2278impl OperationArguments for CallOutputSsa {}
2279impl OperationArguments for CallParamSsa {}
2280impl OperationArguments for CallStackSsa {}
2281impl OperationArguments for Ret {}
2282impl OperationArguments for If {}
2283impl OperationArguments for Goto {}
2284impl OperationArguments for FlagCond {}
2285impl OperationArguments for FlagGroup {}
2286impl OperationArguments for Trap {}
2287impl OperationArguments for RegPhi {}
2288impl OperationArguments for FlagPhi {}
2289impl OperationArguments for MemPhi {}
2290impl OperationArguments for Const {}
2291impl OperationArguments for FloatConst {}
2292impl OperationArguments for Extern {}
2293impl OperationArguments for BinaryOp {}
2294impl OperationArguments for BinaryOpCarry {}
2295impl OperationArguments for UnaryOp {}
2296impl OperationArguments for Condition {}
2297impl OperationArguments for UnimplMem {}
2298impl OperationArguments for Assert {}
2299impl OperationArguments for AssertSsa {}
2300impl OperationArguments for ForceVersion {}
2301impl OperationArguments for ForceVersionSsa {}
2302impl OperationArguments for SeparateParamListSsa {}