1#![allow(clippy::arithmetic_side_effects)]
2use crate::ebpf::*;
11
12pub trait Instruction: Sized {
14 fn opt_code_byte(&self) -> u8;
16
17 fn get_dst(&self) -> u8 {
19 self.get_insn().dst
20 }
21
22 fn get_src(&self) -> u8 {
24 self.get_insn().src
25 }
26
27 fn get_off(&self) -> i16 {
29 self.get_insn().off
30 }
31
32 fn get_imm(&self) -> i64 {
34 self.get_insn().imm
35 }
36
37 #[must_use]
39 fn set_dst(mut self, dst: u8) -> Self {
40 self.get_insn_mut().dst = dst;
41 self
42 }
43
44 #[must_use]
46 fn set_src(mut self, src: u8) -> Self {
47 self.get_insn_mut().src = src;
48 self
49 }
50
51 #[must_use]
53 fn set_off(mut self, offset: i16) -> Self {
54 self.get_insn_mut().off = offset;
55 self
56 }
57
58 #[must_use]
60 fn set_imm(mut self, imm: i64) -> Self {
61 self.get_insn_mut().imm = imm;
62 self
63 }
64
65 fn get_insn(&self) -> &Insn;
67
68 fn get_insn_mut(&mut self) -> &mut Insn;
70}
71
72pub trait IntoBytes {
75 type Bytes;
77
78 fn into_bytes(self) -> Self::Bytes;
80}
81
82impl<I: Instruction> IntoBytes for &I {
84 type Bytes = Vec<u8>;
85
86 fn into_bytes(self) -> Self::Bytes {
90 vec![
91 self.opt_code_byte(),
92 (self.get_src() << 4) | self.get_dst(),
93 self.get_off() as u8,
94 (self.get_off() >> 8) as u8,
95 self.get_imm() as u8,
96 (self.get_imm() >> 8) as u8,
97 (self.get_imm() >> 16) as u8,
98 (self.get_imm() >> 24) as u8,
99 ]
100 }
101}
102
103#[derive(Default)]
105pub struct BpfCode {
106 instructions: Vec<u8>,
107}
108
109impl BpfCode {
110 pub fn new() -> Self {
112 BpfCode {
113 instructions: vec![],
114 }
115 }
116
117 pub fn add(&mut self, source: Source, arch: Arch) -> Move {
119 self.mov_internal(source, arch, OpBits::Add)
120 }
121
122 pub fn sub(&mut self, source: Source, arch: Arch) -> Move {
124 self.mov_internal(source, arch, OpBits::Sub)
125 }
126
127 pub fn mul(&mut self, source: Source, arch: Arch) -> Move {
129 self.mov_internal(source, arch, OpBits::Mul)
130 }
131
132 pub fn div(&mut self, source: Source, arch: Arch) -> Move {
134 self.mov_internal(source, arch, OpBits::Div)
135 }
136
137 pub fn bit_or(&mut self, source: Source, arch: Arch) -> Move {
139 self.mov_internal(source, arch, OpBits::BitOr)
140 }
141
142 pub fn bit_and(&mut self, source: Source, arch: Arch) -> Move {
144 self.mov_internal(source, arch, OpBits::BitAnd)
145 }
146
147 pub fn left_shift(&mut self, source: Source, arch: Arch) -> Move {
149 self.mov_internal(source, arch, OpBits::LShift)
150 }
151
152 pub fn right_shift(&mut self, source: Source, arch: Arch) -> Move {
154 self.mov_internal(source, arch, OpBits::RShift)
155 }
156
157 pub fn negate(&mut self, arch: Arch) -> Move {
159 self.mov_internal(Source::Imm, arch, OpBits::Negate)
160 }
161
162 pub fn modulo(&mut self, source: Source, arch: Arch) -> Move {
164 self.mov_internal(source, arch, OpBits::Mod)
165 }
166
167 pub fn bit_xor(&mut self, source: Source, arch: Arch) -> Move {
169 self.mov_internal(source, arch, OpBits::BitXor)
170 }
171
172 pub fn mov(&mut self, source: Source, arch: Arch) -> Move {
174 self.mov_internal(source, arch, OpBits::Mov)
175 }
176
177 pub fn signed_right_shift(&mut self, source: Source, arch: Arch) -> Move {
179 self.mov_internal(source, arch, OpBits::SignRShift)
180 }
181
182 #[inline]
183 fn mov_internal(&mut self, source: Source, arch_bits: Arch, op_bits: OpBits) -> Move {
184 Move {
185 bpf_code: self,
186 src_bit: source,
187 op_bits,
188 arch_bits,
189 insn: Insn::default(),
190 }
191 }
192
193 pub fn swap_bytes(&mut self, endian: Endian) -> SwapBytes {
195 SwapBytes {
196 bpf_code: self,
197 endian,
198 insn: Insn::default(),
199 }
200 }
201
202 pub fn load(&mut self, mem_size: MemSize) -> Load {
204 self.load_internal(mem_size, Addressing::Imm, BPF_LD)
205 }
206
207 pub fn load_abs(&mut self, mem_size: MemSize) -> Load {
209 self.load_internal(mem_size, Addressing::Abs, BPF_LD)
210 }
211
212 pub fn load_ind(&mut self, mem_size: MemSize) -> Load {
214 self.load_internal(mem_size, Addressing::Ind, BPF_LD)
215 }
216
217 pub fn load_x(&mut self, mem_size: MemSize) -> Load {
219 self.load_internal(mem_size, Addressing::Mem, BPF_LDX)
220 }
221
222 #[inline]
223 fn load_internal(&mut self, mem_size: MemSize, addressing: Addressing, source: u8) -> Load {
224 Load {
225 bpf_code: self,
226 addressing,
227 mem_size,
228 source,
229 insn: Insn::default(),
230 }
231 }
232
233 pub fn store(&mut self, mem_size: MemSize) -> Store {
235 self.store_internal(mem_size, BPF_IMM)
236 }
237
238 pub fn store_x(&mut self, mem_size: MemSize) -> Store {
240 self.store_internal(mem_size, BPF_MEM | BPF_STX)
241 }
242
243 #[inline]
244 fn store_internal(&mut self, mem_size: MemSize, source: u8) -> Store {
245 Store {
246 bpf_code: self,
247 mem_size,
248 source,
249 insn: Insn::default(),
250 }
251 }
252
253 pub fn jump_unconditional(&mut self) -> Jump {
255 self.jump_conditional(Cond::Abs, Source::Imm)
256 }
257
258 pub fn jump_conditional(&mut self, cond: Cond, src_bit: Source) -> Jump {
260 Jump {
261 bpf_code: self,
262 cond,
263 src_bit,
264 insn: Insn::default(),
265 }
266 }
267
268 pub fn call(&mut self) -> FunctionCall {
270 FunctionCall {
271 bpf_code: self,
272 insn: Insn::default(),
273 }
274 }
275
276 pub fn exit(&mut self) -> Exit {
278 Exit {
279 bpf_code: self,
280 insn: Insn::default(),
281 }
282 }
283}
284
285impl<'a> IntoBytes for &'a BpfCode {
287 type Bytes = &'a [u8];
288
289 fn into_bytes(self) -> Self::Bytes {
291 self.instructions.as_slice()
292 }
293}
294
295pub struct Move<'i> {
297 bpf_code: &'i mut BpfCode,
298 src_bit: Source,
299 op_bits: OpBits,
300 arch_bits: Arch,
301 insn: Insn,
302}
303
304impl<'i> Move<'i> {
305 pub fn push(self) -> &'i mut BpfCode {
307 let mut asm = self.into_bytes();
308 self.bpf_code.instructions.append(&mut asm);
309 self.bpf_code
310 }
311}
312
313impl Instruction for Move<'_> {
314 fn opt_code_byte(&self) -> u8 {
315 let op_bits = self.op_bits as u8;
316 let src_bit = self.src_bit as u8;
317 let arch_bits = self.arch_bits as u8;
318 op_bits | src_bit | arch_bits
319 }
320
321 fn get_insn_mut(&mut self) -> &mut Insn {
322 &mut self.insn
323 }
324
325 fn get_insn(&self) -> &Insn {
326 &self.insn
327 }
328}
329
330#[derive(Copy, Clone, PartialEq, Eq)]
331#[cfg_attr(
332 feature = "fuzzer-not-safe-for-production",
333 derive(arbitrary::Arbitrary, Debug)
334)]
335pub enum Source {
337 Imm = BPF_IMM as isize,
339 Reg = BPF_X as isize,
341}
342
343#[derive(Copy, Clone)]
344enum OpBits {
345 Add = BPF_ADD as isize,
346 Sub = BPF_SUB as isize,
347 Mul = BPF_MUL as isize,
348 Div = BPF_DIV as isize,
349 BitOr = BPF_OR as isize,
350 BitAnd = BPF_AND as isize,
351 LShift = BPF_LSH as isize,
352 RShift = BPF_RSH as isize,
353 Negate = BPF_NEG as isize,
354 Mod = BPF_MOD as isize,
355 BitXor = BPF_XOR as isize,
356 Mov = BPF_MOV as isize,
357 SignRShift = BPF_ARSH as isize,
358}
359
360#[derive(Copy, Clone)]
361#[cfg_attr(
362 feature = "fuzzer-not-safe-for-production",
363 derive(arbitrary::Arbitrary, Debug, PartialEq, Eq)
364)]
365pub enum Arch {
367 X64 = BPF_ALU64_STORE as isize,
369 X32 = BPF_ALU32_LOAD as isize,
371}
372
373pub struct SwapBytes<'i> {
375 bpf_code: &'i mut BpfCode,
376 endian: Endian,
377 insn: Insn,
378}
379
380impl<'i> SwapBytes<'i> {
381 pub fn push(self) -> &'i mut BpfCode {
383 let mut asm = self.into_bytes();
384 self.bpf_code.instructions.append(&mut asm);
385 self.bpf_code
386 }
387}
388
389impl Instruction for SwapBytes<'_> {
390 fn opt_code_byte(&self) -> u8 {
391 self.endian as u8
392 }
393
394 fn get_insn_mut(&mut self) -> &mut Insn {
395 &mut self.insn
396 }
397
398 fn get_insn(&self) -> &Insn {
399 &self.insn
400 }
401}
402
403#[derive(Copy, Clone)]
404#[cfg_attr(
405 feature = "fuzzer-not-safe-for-production",
406 derive(arbitrary::Arbitrary, Debug, PartialEq, Eq)
407)]
408pub enum Endian {
410 Little = LE as isize,
412 Big = BE as isize,
414}
415
416pub struct Load<'i> {
418 bpf_code: &'i mut BpfCode,
419 addressing: Addressing,
420 mem_size: MemSize,
421 source: u8,
422 insn: Insn,
423}
424
425impl<'i> Load<'i> {
426 pub fn push(self) -> &'i mut BpfCode {
428 let mut asm = self.into_bytes();
429 self.bpf_code.instructions.append(&mut asm);
430 self.bpf_code
431 }
432}
433
434impl Instruction for Load<'_> {
435 fn opt_code_byte(&self) -> u8 {
436 let size = self.mem_size as u8;
437 let addressing = self.addressing as u8;
438 addressing | size | self.source
439 }
440
441 fn get_insn_mut(&mut self) -> &mut Insn {
442 &mut self.insn
443 }
444
445 fn get_insn(&self) -> &Insn {
446 &self.insn
447 }
448}
449
450pub struct Store<'i> {
452 bpf_code: &'i mut BpfCode,
453 mem_size: MemSize,
454 source: u8,
455 insn: Insn,
456}
457
458impl<'i> Store<'i> {
459 pub fn push(self) -> &'i mut BpfCode {
461 let mut asm = self.into_bytes();
462 self.bpf_code.instructions.append(&mut asm);
463 self.bpf_code
464 }
465}
466
467impl Instruction for Store<'_> {
468 fn opt_code_byte(&self) -> u8 {
469 let size = self.mem_size as u8;
470 BPF_MEM | BPF_ST | size | self.source
471 }
472
473 fn get_insn_mut(&mut self) -> &mut Insn {
474 &mut self.insn
475 }
476
477 fn get_insn(&self) -> &Insn {
478 &self.insn
479 }
480}
481
482#[derive(Copy, Clone)]
483#[cfg_attr(
484 feature = "fuzzer-not-safe-for-production",
485 derive(arbitrary::Arbitrary, Debug, PartialEq, Eq)
486)]
487pub enum MemSize {
489 Byte = BPF_B as isize,
491 HalfWord = BPF_H as isize,
493 Word = BPF_W as isize,
495 DoubleWord = BPF_DW as isize,
497}
498
499#[derive(Copy, Clone)]
500enum Addressing {
501 Imm = BPF_IMM as isize,
502 Abs = BPF_ABS as isize,
503 Ind = BPF_IND as isize,
504 Mem = BPF_MEM as isize,
505}
506
507pub struct Jump<'i> {
509 bpf_code: &'i mut BpfCode,
510 cond: Cond,
511 src_bit: Source,
512 insn: Insn,
513}
514
515impl<'i> Jump<'i> {
516 pub fn push(self) -> &'i mut BpfCode {
518 let mut asm = self.into_bytes();
519 self.bpf_code.instructions.append(&mut asm);
520 self.bpf_code
521 }
522}
523
524impl Instruction for Jump<'_> {
525 fn opt_code_byte(&self) -> u8 {
526 let cmp: u8 = self.cond as u8;
527 let src_bit = self.src_bit as u8;
528 cmp | src_bit | BPF_JMP
529 }
530
531 fn get_insn_mut(&mut self) -> &mut Insn {
532 &mut self.insn
533 }
534
535 fn get_insn(&self) -> &Insn {
536 &self.insn
537 }
538}
539
540#[derive(Copy, Clone, PartialEq, Eq)]
541#[cfg_attr(
542 feature = "fuzzer-not-safe-for-production",
543 derive(arbitrary::Arbitrary, Debug)
544)]
545pub enum Cond {
547 Abs = BPF_JA as isize,
549 Equals = BPF_JEQ as isize,
551 Greater = BPF_JGT as isize,
553 GreaterEquals = BPF_JGE as isize,
555 Lower = BPF_JLT as isize,
557 LowerEquals = BPF_JLE as isize,
559 BitAnd = BPF_JSET as isize,
561 NotEquals = BPF_JNE as isize,
563 GreaterSigned = BPF_JSGT as isize,
565 GreaterEqualsSigned = BPF_JSGE as isize,
567 LowerSigned = BPF_JSLT as isize,
569 LowerEqualsSigned = BPF_JSLE as isize,
571}
572
573pub struct FunctionCall<'i> {
575 bpf_code: &'i mut BpfCode,
576 insn: Insn,
577}
578
579impl<'i> FunctionCall<'i> {
580 pub fn push(self) -> &'i mut BpfCode {
582 let mut asm = self.into_bytes();
583 self.bpf_code.instructions.append(&mut asm);
584 self.bpf_code
585 }
586}
587
588impl Instruction for FunctionCall<'_> {
589 fn opt_code_byte(&self) -> u8 {
590 BPF_CALL | BPF_JMP
591 }
592
593 fn get_insn_mut(&mut self) -> &mut Insn {
594 &mut self.insn
595 }
596
597 fn get_insn(&self) -> &Insn {
598 &self.insn
599 }
600}
601
602pub struct Exit<'i> {
604 bpf_code: &'i mut BpfCode,
605 insn: Insn,
606}
607
608impl<'i> Exit<'i> {
609 pub fn push(self) -> &'i mut BpfCode {
611 let mut asm = self.into_bytes();
612 self.bpf_code.instructions.append(&mut asm);
613 self.bpf_code
614 }
615}
616
617impl Instruction for Exit<'_> {
618 fn opt_code_byte(&self) -> u8 {
619 BPF_EXIT | BPF_JMP
620 }
621
622 fn get_insn_mut(&mut self) -> &mut Insn {
623 &mut self.insn
624 }
625
626 fn get_insn(&self) -> &Insn {
627 &self.insn
628 }
629}
630
631#[cfg(test)]
632mod tests {
633 #[cfg(test)]
634 mod special {
635 use super::super::*;
636
637 #[test]
638 fn call_immediate() {
639 let mut program = BpfCode::new();
640 program.call().set_imm(0x11_22_33_44).push();
641
642 assert_eq!(
643 program.into_bytes(),
644 &[0x85, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
645 );
646 }
647
648 #[test]
649 fn exit_operation() {
650 let mut program = BpfCode::new();
651 program.exit().push();
652
653 assert_eq!(
654 program.into_bytes(),
655 &[0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
656 );
657 }
658 }
659
660 #[cfg(test)]
661 mod jump_instructions {
662 #[cfg(test)]
663 mod register {
664 use super::super::super::*;
665
666 #[test]
667 fn jump_on_dst_equals_src() {
668 let mut program = BpfCode::new();
669 program
670 .jump_conditional(Cond::Equals, Source::Reg)
671 .set_dst(0x01)
672 .set_src(0x02)
673 .push();
674
675 assert_eq!(
676 program.into_bytes(),
677 &[0x1d, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
678 );
679 }
680
681 #[test]
682 fn jump_on_dst_greater_than_src() {
683 let mut program = BpfCode::new();
684 program
685 .jump_conditional(Cond::Greater, Source::Reg)
686 .set_dst(0x03)
687 .set_src(0x02)
688 .push();
689
690 assert_eq!(
691 program.into_bytes(),
692 &[0x2d, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
693 );
694 }
695
696 #[test]
697 fn jump_on_dst_greater_or_equals_to_src() {
698 let mut program = BpfCode::new();
699 program
700 .jump_conditional(Cond::GreaterEquals, Source::Reg)
701 .set_dst(0x04)
702 .set_src(0x01)
703 .push();
704
705 assert_eq!(
706 program.into_bytes(),
707 &[0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
708 );
709 }
710
711 #[test]
712 fn jump_on_dst_lower_than_src() {
713 let mut program = BpfCode::new();
714 program
715 .jump_conditional(Cond::Lower, Source::Reg)
716 .set_dst(0x03)
717 .set_src(0x02)
718 .push();
719
720 assert_eq!(
721 program.into_bytes(),
722 &[0xad, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
723 );
724 }
725
726 #[test]
727 fn jump_on_dst_lower_or_equals_to_src() {
728 let mut program = BpfCode::new();
729 program
730 .jump_conditional(Cond::LowerEquals, Source::Reg)
731 .set_dst(0x04)
732 .set_src(0x01)
733 .push();
734
735 assert_eq!(
736 program.into_bytes(),
737 &[0xbd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
738 );
739 }
740
741 #[test]
742 fn jump_on_dst_bit_and_with_src_not_equal_zero() {
743 let mut program = BpfCode::new();
744 program
745 .jump_conditional(Cond::BitAnd, Source::Reg)
746 .set_dst(0x05)
747 .set_src(0x02)
748 .push();
749
750 assert_eq!(
751 program.into_bytes(),
752 &[0x4d, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
753 );
754 }
755
756 #[test]
757 fn jump_on_dst_not_equals_src() {
758 let mut program = BpfCode::new();
759 program
760 .jump_conditional(Cond::NotEquals, Source::Reg)
761 .set_dst(0x03)
762 .set_src(0x05)
763 .push();
764
765 assert_eq!(
766 program.into_bytes(),
767 &[0x5d, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
768 );
769 }
770
771 #[test]
772 fn jump_on_dst_greater_than_src_signed() {
773 let mut program = BpfCode::new();
774 program
775 .jump_conditional(Cond::GreaterSigned, Source::Reg)
776 .set_dst(0x04)
777 .set_src(0x01)
778 .push();
779
780 assert_eq!(
781 program.into_bytes(),
782 &[0x6d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
783 );
784 }
785
786 #[test]
787 fn jump_on_dst_greater_or_equals_src_signed() {
788 let mut program = BpfCode::new();
789 program
790 .jump_conditional(Cond::GreaterEqualsSigned, Source::Reg)
791 .set_dst(0x01)
792 .set_src(0x03)
793 .push();
794
795 assert_eq!(
796 program.into_bytes(),
797 &[0x7d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
798 );
799 }
800
801 #[test]
802 fn jump_on_dst_lower_than_src_signed() {
803 let mut program = BpfCode::new();
804 program
805 .jump_conditional(Cond::LowerSigned, Source::Reg)
806 .set_dst(0x04)
807 .set_src(0x01)
808 .push();
809
810 assert_eq!(
811 program.into_bytes(),
812 &[0xcd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
813 );
814 }
815
816 #[test]
817 fn jump_on_dst_lower_or_equals_src_signed() {
818 let mut program = BpfCode::new();
819 program
820 .jump_conditional(Cond::LowerEqualsSigned, Source::Reg)
821 .set_dst(0x01)
822 .set_src(0x03)
823 .push();
824
825 assert_eq!(
826 program.into_bytes(),
827 &[0xdd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
828 );
829 }
830 }
831
832 #[cfg(test)]
833 mod immediate {
834 use super::super::super::*;
835
836 #[test]
837 fn jump_to_label() {
838 let mut program = BpfCode::new();
839 program.jump_unconditional().set_off(0x00_11).push();
840
841 assert_eq!(
842 program.into_bytes(),
843 &[0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
844 );
845 }
846
847 #[test]
848 fn jump_on_dst_equals_const() {
849 let mut program = BpfCode::new();
850 program
851 .jump_conditional(Cond::Equals, Source::Imm)
852 .set_dst(0x01)
853 .set_imm(0x00_11_22_33)
854 .push();
855
856 assert_eq!(
857 program.into_bytes(),
858 &[0x15, 0x01, 0x00, 0x00, 0x33, 0x22, 0x11, 0x00]
859 );
860 }
861
862 #[test]
863 fn jump_on_dst_greater_than_const() {
864 let mut program = BpfCode::new();
865 program
866 .jump_conditional(Cond::Greater, Source::Imm)
867 .set_dst(0x02)
868 .set_imm(0x00_11_00_11)
869 .push();
870
871 assert_eq!(
872 program.into_bytes(),
873 &[0x25, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
874 );
875 }
876
877 #[test]
878 fn jump_on_dst_greater_or_equals_to_const() {
879 let mut program = BpfCode::new();
880 program
881 .jump_conditional(Cond::GreaterEquals, Source::Imm)
882 .set_dst(0x04)
883 .set_imm(0x00_22_11_00)
884 .push();
885
886 assert_eq!(
887 program.into_bytes(),
888 &[0x35, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
889 );
890 }
891
892 #[test]
893 fn jump_on_dst_lower_than_const() {
894 let mut program = BpfCode::new();
895 program
896 .jump_conditional(Cond::Lower, Source::Imm)
897 .set_dst(0x02)
898 .set_imm(0x00_11_00_11)
899 .push();
900
901 assert_eq!(
902 program.into_bytes(),
903 &[0xa5, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
904 );
905 }
906
907 #[test]
908 fn jump_on_dst_lower_or_equals_to_const() {
909 let mut program = BpfCode::new();
910 program
911 .jump_conditional(Cond::LowerEquals, Source::Imm)
912 .set_dst(0x04)
913 .set_imm(0x00_22_11_00)
914 .push();
915
916 assert_eq!(
917 program.into_bytes(),
918 &[0xb5, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
919 );
920 }
921
922 #[test]
923 fn jump_on_dst_bit_and_with_const_not_equal_zero() {
924 let mut program = BpfCode::new();
925 program
926 .jump_conditional(Cond::BitAnd, Source::Imm)
927 .set_dst(0x05)
928 .push();
929
930 assert_eq!(
931 program.into_bytes(),
932 &[0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
933 );
934 }
935
936 #[test]
937 fn jump_on_dst_not_equals_const() {
938 let mut program = BpfCode::new();
939 program
940 .jump_conditional(Cond::NotEquals, Source::Imm)
941 .set_dst(0x03)
942 .push();
943
944 assert_eq!(
945 program.into_bytes(),
946 &[0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
947 );
948 }
949
950 #[test]
951 fn jump_on_dst_greater_than_const_signed() {
952 let mut program = BpfCode::new();
953 program
954 .jump_conditional(Cond::GreaterSigned, Source::Imm)
955 .set_dst(0x04)
956 .push();
957
958 assert_eq!(
959 program.into_bytes(),
960 &[0x65, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
961 );
962 }
963
964 #[test]
965 fn jump_on_dst_greater_or_equals_src_signed() {
966 let mut program = BpfCode::new();
967 program
968 .jump_conditional(Cond::GreaterEqualsSigned, Source::Imm)
969 .set_dst(0x01)
970 .push();
971
972 assert_eq!(
973 program.into_bytes(),
974 &[0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
975 );
976 }
977
978 #[test]
979 fn jump_on_dst_lower_than_const_signed() {
980 let mut program = BpfCode::new();
981 program
982 .jump_conditional(Cond::LowerSigned, Source::Imm)
983 .set_dst(0x04)
984 .push();
985
986 assert_eq!(
987 program.into_bytes(),
988 &[0xc5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
989 );
990 }
991
992 #[test]
993 fn jump_on_dst_lower_or_equals_src_signed() {
994 let mut program = BpfCode::new();
995 program
996 .jump_conditional(Cond::LowerEqualsSigned, Source::Imm)
997 .set_dst(0x01)
998 .push();
999
1000 assert_eq!(
1001 program.into_bytes(),
1002 &[0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1003 );
1004 }
1005 }
1006 }
1007
1008 #[cfg(test)]
1009 mod store_instructions {
1010 use super::super::*;
1011
1012 #[test]
1013 fn store_word_from_dst_into_immediate_address() {
1014 let mut program = BpfCode::new();
1015 program
1016 .store(MemSize::Word)
1017 .set_dst(0x01)
1018 .set_off(0x00_11)
1019 .set_imm(0x11_22_33_44)
1020 .push();
1021
1022 assert_eq!(
1023 program.into_bytes(),
1024 &[0x62, 0x01, 0x11, 0x00, 0x44, 0x33, 0x22, 0x11]
1025 );
1026 }
1027
1028 #[test]
1029 fn store_half_word_from_dst_into_immediate_address() {
1030 let mut program = BpfCode::new();
1031 program
1032 .store(MemSize::HalfWord)
1033 .set_dst(0x02)
1034 .set_off(0x11_22)
1035 .push();
1036
1037 assert_eq!(
1038 program.into_bytes(),
1039 &[0x6a, 0x02, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
1040 );
1041 }
1042
1043 #[test]
1044 fn store_byte_from_dst_into_immediate_address() {
1045 let mut program = BpfCode::new();
1046 program.store(MemSize::Byte).push();
1047
1048 assert_eq!(
1049 program.into_bytes(),
1050 &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1051 );
1052 }
1053
1054 #[test]
1055 fn store_double_word_from_dst_into_immediate_address() {
1056 let mut program = BpfCode::new();
1057 program.store(MemSize::DoubleWord).push();
1058
1059 assert_eq!(
1060 program.into_bytes(),
1061 &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1062 );
1063 }
1064
1065 #[test]
1066 fn store_word_from_dst_into_src_address() {
1067 let mut program = BpfCode::new();
1068 program
1069 .store_x(MemSize::Word)
1070 .set_dst(0x01)
1071 .set_src(0x02)
1072 .push();
1073
1074 assert_eq!(
1075 program.into_bytes(),
1076 &[0x63, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1077 );
1078 }
1079
1080 #[test]
1081 fn store_half_word_from_dst_into_src_address() {
1082 let mut program = BpfCode::new();
1083 program.store_x(MemSize::HalfWord).push();
1084
1085 assert_eq!(
1086 program.into_bytes(),
1087 &[0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1088 );
1089 }
1090
1091 #[test]
1092 fn store_byte_from_dst_into_src_address() {
1093 let mut program = BpfCode::new();
1094 program.store_x(MemSize::Byte).push();
1095
1096 assert_eq!(
1097 program.into_bytes(),
1098 &[0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1099 );
1100 }
1101
1102 #[test]
1103 fn store_double_word_from_dst_into_src_address() {
1104 let mut program = BpfCode::new();
1105 program.store_x(MemSize::DoubleWord).push();
1106
1107 assert_eq!(
1108 program.into_bytes(),
1109 &[0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1110 );
1111 }
1112 }
1113
1114 #[cfg(test)]
1115 mod load_instructions {
1116 #[cfg(test)]
1117 mod register {
1118 use super::super::super::*;
1119
1120 #[test]
1121 fn load_word_from_set_src_with_offset() {
1122 let mut program = BpfCode::new();
1123 program
1124 .load_x(MemSize::Word)
1125 .set_dst(0x01)
1126 .set_src(0x02)
1127 .set_off(0x00_02)
1128 .push();
1129
1130 assert_eq!(
1131 program.into_bytes(),
1132 &[0x61, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]
1133 );
1134 }
1135
1136 #[test]
1137 fn load_half_word_from_set_src_with_offset() {
1138 let mut program = BpfCode::new();
1139 program
1140 .load_x(MemSize::HalfWord)
1141 .set_dst(0x02)
1142 .set_src(0x01)
1143 .set_off(0x11_22)
1144 .push();
1145
1146 assert_eq!(
1147 program.into_bytes(),
1148 &[0x69, 0x12, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
1149 );
1150 }
1151
1152 #[test]
1153 fn load_byte_from_set_src_with_offset() {
1154 let mut program = BpfCode::new();
1155 program
1156 .load_x(MemSize::Byte)
1157 .set_dst(0x01)
1158 .set_src(0x04)
1159 .set_off(0x00_11)
1160 .push();
1161
1162 assert_eq!(
1163 program.into_bytes(),
1164 &[0x71, 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
1165 );
1166 }
1167
1168 #[test]
1169 fn load_double_word_from_set_src_with_offset() {
1170 let mut program = BpfCode::new();
1171 program
1172 .load_x(MemSize::DoubleWord)
1173 .set_dst(0x04)
1174 .set_src(0x05)
1175 .set_off(0x44_55)
1176 .push();
1177
1178 assert_eq!(
1179 program.into_bytes(),
1180 &[0x79, 0x54, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00]
1181 );
1182 }
1183 }
1184
1185 #[cfg(test)]
1186 mod immediate {
1187 use super::super::super::*;
1188
1189 #[test]
1190 fn load_double_word() {
1191 let mut program = BpfCode::new();
1192 program
1193 .load(MemSize::DoubleWord)
1194 .set_dst(0x01)
1195 .set_imm(0x00_01_02_03)
1196 .push();
1197
1198 assert_eq!(
1199 program.into_bytes(),
1200 &[0x18, 0x01, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
1201 );
1202 }
1203
1204 #[test]
1205 fn load_abs_word() {
1206 let mut program = BpfCode::new();
1207 program.load_abs(MemSize::Word).push();
1208
1209 assert_eq!(
1210 program.into_bytes(),
1211 &[0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1212 );
1213 }
1214
1215 #[test]
1216 fn load_abs_half_word() {
1217 let mut program = BpfCode::new();
1218 program.load_abs(MemSize::HalfWord).set_dst(0x05).push();
1219
1220 assert_eq!(
1221 program.into_bytes(),
1222 &[0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1223 );
1224 }
1225
1226 #[test]
1227 fn load_abs_byte() {
1228 let mut program = BpfCode::new();
1229 program.load_abs(MemSize::Byte).set_dst(0x01).push();
1230
1231 assert_eq!(
1232 program.into_bytes(),
1233 &[0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1234 );
1235 }
1236
1237 #[test]
1238 fn load_abs_double_word() {
1239 let mut program = BpfCode::new();
1240 program
1241 .load_abs(MemSize::DoubleWord)
1242 .set_dst(0x01)
1243 .set_imm(0x01_02_03_04)
1244 .push();
1245
1246 assert_eq!(
1247 program.into_bytes(),
1248 &[0x38, 0x01, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
1249 );
1250 }
1251
1252 #[test]
1253 fn load_indirect_word() {
1254 let mut program = BpfCode::new();
1255 program.load_ind(MemSize::Word).push();
1256
1257 assert_eq!(
1258 program.into_bytes(),
1259 &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1260 );
1261 }
1262
1263 #[test]
1264 fn load_indirect_half_word() {
1265 let mut program = BpfCode::new();
1266 program.load_ind(MemSize::HalfWord).push();
1267
1268 assert_eq!(
1269 program.into_bytes(),
1270 &[0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1271 );
1272 }
1273
1274 #[test]
1275 fn load_indirect_byte() {
1276 let mut program = BpfCode::new();
1277 program.load_ind(MemSize::Byte).push();
1278
1279 assert_eq!(
1280 program.into_bytes(),
1281 &[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1282 );
1283 }
1284
1285 #[test]
1286 fn load_indirect_double_word() {
1287 let mut program = BpfCode::new();
1288 program.load_ind(MemSize::DoubleWord).push();
1289
1290 assert_eq!(
1291 program.into_bytes(),
1292 &[0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1293 );
1294 }
1295 }
1296 }
1297
1298 #[cfg(test)]
1299 mod byte_swap_instructions {
1300 use super::super::*;
1301
1302 #[test]
1303 fn convert_host_to_little_endian_16bits() {
1304 let mut program = BpfCode::new();
1305 program
1306 .swap_bytes(Endian::Little)
1307 .set_dst(0x01)
1308 .set_imm(0x00_00_00_10)
1309 .push();
1310
1311 assert_eq!(
1312 program.into_bytes(),
1313 &[0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
1314 );
1315 }
1316
1317 #[test]
1318 fn convert_host_to_little_endian_32bits() {
1319 let mut program = BpfCode::new();
1320 program
1321 .swap_bytes(Endian::Little)
1322 .set_dst(0x02)
1323 .set_imm(0x00_00_00_20)
1324 .push();
1325
1326 assert_eq!(
1327 program.into_bytes(),
1328 &[0xd4, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
1329 );
1330 }
1331
1332 #[test]
1333 fn convert_host_to_little_endian_64bit() {
1334 let mut program = BpfCode::new();
1335 program
1336 .swap_bytes(Endian::Little)
1337 .set_dst(0x03)
1338 .set_imm(0x00_00_00_40)
1339 .push();
1340
1341 assert_eq!(
1342 program.into_bytes(),
1343 &[0xd4, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
1344 );
1345 }
1346
1347 #[test]
1348 fn convert_host_to_big_endian_16bits() {
1349 let mut program = BpfCode::new();
1350 program
1351 .swap_bytes(Endian::Big)
1352 .set_dst(0x01)
1353 .set_imm(0x00_00_00_10)
1354 .push();
1355
1356 assert_eq!(
1357 program.into_bytes(),
1358 &[0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
1359 );
1360 }
1361
1362 #[test]
1363 fn convert_host_to_big_endian_32bits() {
1364 let mut program = BpfCode::new();
1365 program
1366 .swap_bytes(Endian::Big)
1367 .set_dst(0x02)
1368 .set_imm(0x00_00_00_20)
1369 .push();
1370
1371 assert_eq!(
1372 program.into_bytes(),
1373 &[0xdc, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
1374 );
1375 }
1376
1377 #[test]
1378 fn convert_host_to_big_endian_64bit() {
1379 let mut program = BpfCode::new();
1380 program
1381 .swap_bytes(Endian::Big)
1382 .set_dst(0x03)
1383 .set_imm(0x00_00_00_40)
1384 .push();
1385
1386 assert_eq!(
1387 program.into_bytes(),
1388 &[0xdc, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
1389 );
1390 }
1391 }
1392
1393 #[cfg(test)]
1394 mod moves_instructions {
1395 #[cfg(test)]
1396 mod arch_x64 {
1397 #[cfg(test)]
1398 mod immediate {
1399 use super::super::super::super::*;
1400
1401 #[test]
1402 fn move_and_add_const_to_register() {
1403 let mut program = BpfCode::new();
1404 program
1405 .add(Source::Imm, Arch::X64)
1406 .set_dst(0x02)
1407 .set_imm(0x01_02_03_04)
1408 .push();
1409
1410 assert_eq!(
1411 program.into_bytes(),
1412 &[0x07, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
1413 );
1414 }
1415
1416 #[test]
1417 fn move_sub_const_to_register() {
1418 let mut program = BpfCode::new();
1419 program
1420 .sub(Source::Imm, Arch::X64)
1421 .set_dst(0x04)
1422 .set_imm(0x00_01_02_03)
1423 .push();
1424
1425 assert_eq!(
1426 program.into_bytes(),
1427 &[0x17, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
1428 );
1429 }
1430
1431 #[test]
1432 fn move_mul_const_to_register() {
1433 let mut program = BpfCode::new();
1434 program
1435 .mul(Source::Imm, Arch::X64)
1436 .set_dst(0x05)
1437 .set_imm(0x04_03_02_01)
1438 .push();
1439
1440 assert_eq!(
1441 program.into_bytes(),
1442 &[0x27, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
1443 );
1444 }
1445
1446 #[test]
1447 fn move_div_constant_to_register() {
1448 let mut program = BpfCode::new();
1449 program
1450 .div(Source::Imm, Arch::X64)
1451 .set_dst(0x02)
1452 .set_imm(0x00_ff_00_ff)
1453 .push();
1454
1455 assert_eq!(
1456 program.into_bytes(),
1457 &[0x37, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
1458 );
1459 }
1460
1461 #[test]
1462 fn move_bit_or_const_to_register() {
1463 let mut program = BpfCode::new();
1464 program
1465 .bit_or(Source::Imm, Arch::X64)
1466 .set_dst(0x02)
1467 .set_imm(0x00_11_00_22)
1468 .push();
1469
1470 assert_eq!(
1471 program.into_bytes(),
1472 &[0x47, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
1473 );
1474 }
1475
1476 #[test]
1477 fn move_bit_and_const_to_register() {
1478 let mut program = BpfCode::new();
1479 program
1480 .bit_and(Source::Imm, Arch::X64)
1481 .set_dst(0x02)
1482 .set_imm(0x11_22_33_44)
1483 .push();
1484
1485 assert_eq!(
1486 program.into_bytes(),
1487 &[0x57, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
1488 );
1489 }
1490
1491 #[test]
1492 fn move_left_shift_const_to_register() {
1493 let mut program = BpfCode::new();
1494 program
1495 .left_shift(Source::Imm, Arch::X64)
1496 .set_dst(0x01)
1497 .push();
1498
1499 assert_eq!(
1500 program.into_bytes(),
1501 &[0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1502 );
1503 }
1504
1505 #[test]
1506 fn move_logical_right_shift_const_to_register() {
1507 let mut program = BpfCode::new();
1508 program
1509 .right_shift(Source::Imm, Arch::X64)
1510 .set_dst(0x01)
1511 .push();
1512
1513 assert_eq!(
1514 program.into_bytes(),
1515 &[0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1516 );
1517 }
1518
1519 #[test]
1520 fn move_negate_register() {
1521 let mut program = BpfCode::new();
1522 program.negate(Arch::X64).set_dst(0x02).push();
1523
1524 assert_eq!(
1525 program.into_bytes(),
1526 &[0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1527 );
1528 }
1529
1530 #[test]
1531 fn move_mod_const_to_register() {
1532 let mut program = BpfCode::new();
1533 program.modulo(Source::Imm, Arch::X64).set_dst(0x02).push();
1534
1535 assert_eq!(
1536 program.into_bytes(),
1537 &[0x97, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1538 );
1539 }
1540
1541 #[test]
1542 fn move_bit_xor_const_to_register() {
1543 let mut program = BpfCode::new();
1544 program.bit_xor(Source::Imm, Arch::X64).set_dst(0x03).push();
1545
1546 assert_eq!(
1547 program.into_bytes(),
1548 &[0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1549 );
1550 }
1551
1552 #[test]
1553 fn move_const_to_register() {
1554 let mut program = BpfCode::new();
1555 program
1556 .mov(Source::Imm, Arch::X64)
1557 .set_dst(0x01)
1558 .set_imm(0x00_00_00_FF)
1559 .push();
1560
1561 assert_eq!(
1562 program.into_bytes(),
1563 &[0xb7, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
1564 );
1565 }
1566
1567 #[test]
1568 fn move_signed_right_shift_const_to_register() {
1569 let mut program = BpfCode::new();
1570 program
1571 .signed_right_shift(Source::Imm, Arch::X64)
1572 .set_dst(0x05)
1573 .push();
1574
1575 assert_eq!(
1576 program.into_bytes(),
1577 &[0xc7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1578 );
1579 }
1580 }
1581
1582 #[cfg(test)]
1583 mod register {
1584 use super::super::super::super::*;
1585
1586 #[test]
1587 fn move_and_add_from_register() {
1588 let mut program = BpfCode::new();
1589 program
1590 .add(Source::Reg, Arch::X64)
1591 .set_dst(0x03)
1592 .set_src(0x02)
1593 .push();
1594
1595 assert_eq!(
1596 program.into_bytes(),
1597 &[0x0f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1598 );
1599 }
1600
1601 #[test]
1602 fn move_sub_from_register_to_register() {
1603 let mut program = BpfCode::new();
1604 program
1605 .sub(Source::Reg, Arch::X64)
1606 .set_dst(0x03)
1607 .set_src(0x04)
1608 .push();
1609
1610 assert_eq!(
1611 program.into_bytes(),
1612 &[0x1f, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1613 );
1614 }
1615
1616 #[test]
1617 fn move_mul_from_register_to_register() {
1618 let mut program = BpfCode::new();
1619 program
1620 .mul(Source::Reg, Arch::X64)
1621 .set_dst(0x04)
1622 .set_src(0x03)
1623 .push();
1624
1625 assert_eq!(
1626 program.into_bytes(),
1627 &[0x2f, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1628 );
1629 }
1630
1631 #[test]
1632 fn move_div_from_register_to_register() {
1633 let mut program = BpfCode::new();
1634 program
1635 .div(Source::Reg, Arch::X64)
1636 .set_dst(0x01)
1637 .set_src(0x00)
1638 .push();
1639
1640 assert_eq!(
1641 program.into_bytes(),
1642 &[0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1643 );
1644 }
1645
1646 #[test]
1647 fn move_bit_or_from_register_to_register() {
1648 let mut program = BpfCode::new();
1649 program
1650 .bit_or(Source::Reg, Arch::X64)
1651 .set_dst(0x03)
1652 .set_src(0x01)
1653 .push();
1654
1655 assert_eq!(
1656 program.into_bytes(),
1657 &[0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1658 );
1659 }
1660
1661 #[test]
1662 fn move_bit_and_from_register_to_register() {
1663 let mut program = BpfCode::new();
1664 program
1665 .bit_and(Source::Reg, Arch::X64)
1666 .set_dst(0x03)
1667 .set_src(0x02)
1668 .push();
1669
1670 assert_eq!(
1671 program.into_bytes(),
1672 &[0x5f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1673 );
1674 }
1675
1676 #[test]
1677 fn move_left_shift_from_register_to_register() {
1678 let mut program = BpfCode::new();
1679 program
1680 .left_shift(Source::Reg, Arch::X64)
1681 .set_dst(0x02)
1682 .set_src(0x03)
1683 .push();
1684
1685 assert_eq!(
1686 program.into_bytes(),
1687 &[0x6f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1688 );
1689 }
1690
1691 #[test]
1692 fn move_logical_right_shift_from_register_to_register() {
1693 let mut program = BpfCode::new();
1694 program
1695 .right_shift(Source::Reg, Arch::X64)
1696 .set_dst(0x02)
1697 .set_src(0x04)
1698 .push();
1699
1700 assert_eq!(
1701 program.into_bytes(),
1702 &[0x7f, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1703 );
1704 }
1705
1706 #[test]
1707 fn move_mod_from_register_to_register() {
1708 let mut program = BpfCode::new();
1709 program
1710 .modulo(Source::Reg, Arch::X64)
1711 .set_dst(0x01)
1712 .set_src(0x02)
1713 .push();
1714
1715 assert_eq!(
1716 program.into_bytes(),
1717 &[0x9f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1718 );
1719 }
1720
1721 #[test]
1722 fn move_bit_xor_from_register_to_register() {
1723 let mut program = BpfCode::new();
1724 program
1725 .bit_xor(Source::Reg, Arch::X64)
1726 .set_dst(0x02)
1727 .set_src(0x04)
1728 .push();
1729
1730 assert_eq!(
1731 program.into_bytes(),
1732 &[0xaf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1733 );
1734 }
1735
1736 #[test]
1737 fn move_from_register_to_another_register() {
1738 let mut program = BpfCode::new();
1739 program.mov(Source::Reg, Arch::X64).set_src(0x01).push();
1740
1741 assert_eq!(
1742 program.into_bytes(),
1743 &[0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1744 );
1745 }
1746
1747 #[test]
1748 fn move_signed_right_shift_from_register_to_register() {
1749 let mut program = BpfCode::new();
1750 program
1751 .signed_right_shift(Source::Reg, Arch::X64)
1752 .set_dst(0x02)
1753 .set_src(0x03)
1754 .push();
1755
1756 assert_eq!(
1757 program.into_bytes(),
1758 &[0xcf, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1759 );
1760 }
1761 }
1762 }
1763
1764 #[cfg(test)]
1765 mod arch_x32 {
1766 #[cfg(test)]
1767 mod immediate {
1768 use super::super::super::super::*;
1769
1770 #[test]
1771 fn move_and_add_const_to_register() {
1772 let mut program = BpfCode::new();
1773 program
1774 .add(Source::Imm, Arch::X32)
1775 .set_dst(0x02)
1776 .set_imm(0x01_02_03_04)
1777 .push();
1778
1779 assert_eq!(
1780 program.into_bytes(),
1781 &[0x04, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
1782 );
1783 }
1784
1785 #[test]
1786 fn move_sub_const_to_register() {
1787 let mut program = BpfCode::new();
1788 program
1789 .sub(Source::Imm, Arch::X32)
1790 .set_dst(0x04)
1791 .set_imm(0x00_01_02_03)
1792 .push();
1793
1794 assert_eq!(
1795 program.into_bytes(),
1796 &[0x14, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
1797 );
1798 }
1799
1800 #[test]
1801 fn move_mul_const_to_register() {
1802 let mut program = BpfCode::new();
1803 program
1804 .mul(Source::Imm, Arch::X32)
1805 .set_dst(0x05)
1806 .set_imm(0x04_03_02_01)
1807 .push();
1808
1809 assert_eq!(
1810 program.into_bytes(),
1811 &[0x24, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
1812 );
1813 }
1814
1815 #[test]
1816 fn move_div_constant_to_register() {
1817 let mut program = BpfCode::new();
1818 program
1819 .div(Source::Imm, Arch::X32)
1820 .set_dst(0x02)
1821 .set_imm(0x00_ff_00_ff)
1822 .push();
1823
1824 assert_eq!(
1825 program.into_bytes(),
1826 &[0x34, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
1827 );
1828 }
1829
1830 #[test]
1831 fn move_bit_or_const_to_register() {
1832 let mut program = BpfCode::new();
1833 program
1834 .bit_or(Source::Imm, Arch::X32)
1835 .set_dst(0x02)
1836 .set_imm(0x00_11_00_22)
1837 .push();
1838
1839 assert_eq!(
1840 program.into_bytes(),
1841 &[0x44, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
1842 );
1843 }
1844
1845 #[test]
1846 fn move_bit_and_const_to_register() {
1847 let mut program = BpfCode::new();
1848 program
1849 .bit_and(Source::Imm, Arch::X32)
1850 .set_dst(0x02)
1851 .set_imm(0x11_22_33_44)
1852 .push();
1853
1854 assert_eq!(
1855 program.into_bytes(),
1856 &[0x54, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
1857 );
1858 }
1859
1860 #[test]
1861 fn move_left_shift_const_to_register() {
1862 let mut program = BpfCode::new();
1863 program
1864 .left_shift(Source::Imm, Arch::X32)
1865 .set_dst(0x01)
1866 .push();
1867
1868 assert_eq!(
1869 program.into_bytes(),
1870 &[0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1871 );
1872 }
1873
1874 #[test]
1875 fn move_logical_right_shift_const_to_register() {
1876 let mut program = BpfCode::new();
1877 program
1878 .right_shift(Source::Imm, Arch::X32)
1879 .set_dst(0x01)
1880 .push();
1881
1882 assert_eq!(
1883 program.into_bytes(),
1884 &[0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1885 );
1886 }
1887
1888 #[test]
1889 fn move_negate_register() {
1890 let mut program = BpfCode::new();
1891 program.negate(Arch::X32).set_dst(0x02).push();
1892
1893 assert_eq!(
1894 program.into_bytes(),
1895 &[0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1896 );
1897 }
1898
1899 #[test]
1900 fn move_mod_const_to_register() {
1901 let mut program = BpfCode::new();
1902 program.modulo(Source::Imm, Arch::X32).set_dst(0x02).push();
1903
1904 assert_eq!(
1905 program.into_bytes(),
1906 &[0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1907 );
1908 }
1909
1910 #[test]
1911 fn move_bit_xor_const_to_register() {
1912 let mut program = BpfCode::new();
1913 program.bit_xor(Source::Imm, Arch::X32).set_dst(0x03).push();
1914
1915 assert_eq!(
1916 program.into_bytes(),
1917 &[0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1918 );
1919 }
1920
1921 #[test]
1922 fn move_const_to_register() {
1923 let mut program = BpfCode::new();
1924 program
1925 .mov(Source::Imm, Arch::X32)
1926 .set_dst(0x01)
1927 .set_imm(0x00_00_00_FF)
1928 .push();
1929
1930 assert_eq!(
1931 program.into_bytes(),
1932 &[0xb4, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
1933 );
1934 }
1935
1936 #[test]
1937 fn move_signed_right_shift_const_to_register() {
1938 let mut program = BpfCode::new();
1939 program
1940 .signed_right_shift(Source::Imm, Arch::X32)
1941 .set_dst(0x05)
1942 .push();
1943
1944 assert_eq!(
1945 program.into_bytes(),
1946 &[0xc4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1947 );
1948 }
1949 }
1950
1951 #[cfg(test)]
1952 mod register {
1953 use super::super::super::super::*;
1954
1955 #[test]
1956 fn move_and_add_from_register() {
1957 let mut program = BpfCode::new();
1958 program
1959 .add(Source::Reg, Arch::X32)
1960 .set_dst(0x03)
1961 .set_src(0x02)
1962 .push();
1963
1964 assert_eq!(
1965 program.into_bytes(),
1966 &[0x0c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1967 );
1968 }
1969
1970 #[test]
1971 fn move_sub_from_register_to_register() {
1972 let mut program = BpfCode::new();
1973 program
1974 .sub(Source::Reg, Arch::X32)
1975 .set_dst(0x03)
1976 .set_src(0x04)
1977 .push();
1978
1979 assert_eq!(
1980 program.into_bytes(),
1981 &[0x1c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1982 );
1983 }
1984
1985 #[test]
1986 fn move_mul_from_register_to_register() {
1987 let mut program = BpfCode::new();
1988 program
1989 .mul(Source::Reg, Arch::X32)
1990 .set_dst(0x04)
1991 .set_src(0x03)
1992 .push();
1993
1994 assert_eq!(
1995 program.into_bytes(),
1996 &[0x2c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
1997 );
1998 }
1999
2000 #[test]
2001 fn move_div_from_register_to_register() {
2002 let mut program = BpfCode::new();
2003 program
2004 .div(Source::Reg, Arch::X32)
2005 .set_dst(0x01)
2006 .set_src(0x00)
2007 .push();
2008
2009 assert_eq!(
2010 program.into_bytes(),
2011 &[0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2012 );
2013 }
2014
2015 #[test]
2016 fn move_bit_or_from_register_to_register() {
2017 let mut program = BpfCode::new();
2018 program
2019 .bit_or(Source::Reg, Arch::X32)
2020 .set_dst(0x03)
2021 .set_src(0x01)
2022 .push();
2023
2024 assert_eq!(
2025 program.into_bytes(),
2026 &[0x4c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2027 );
2028 }
2029
2030 #[test]
2031 fn move_bit_and_from_register_to_register() {
2032 let mut program = BpfCode::new();
2033 program
2034 .bit_and(Source::Reg, Arch::X32)
2035 .set_dst(0x03)
2036 .set_src(0x02)
2037 .push();
2038
2039 assert_eq!(
2040 program.into_bytes(),
2041 &[0x5c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2042 );
2043 }
2044
2045 #[test]
2046 fn move_left_shift_from_register_to_register() {
2047 let mut program = BpfCode::new();
2048 program
2049 .left_shift(Source::Reg, Arch::X32)
2050 .set_dst(0x02)
2051 .set_src(0x03)
2052 .push();
2053
2054 assert_eq!(
2055 program.into_bytes(),
2056 &[0x6c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2057 );
2058 }
2059
2060 #[test]
2061 fn move_logical_right_shift_from_register_to_register() {
2062 let mut program = BpfCode::new();
2063 program
2064 .right_shift(Source::Reg, Arch::X32)
2065 .set_dst(0x02)
2066 .set_src(0x04)
2067 .push();
2068
2069 assert_eq!(
2070 program.into_bytes(),
2071 &[0x7c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2072 );
2073 }
2074
2075 #[test]
2076 fn move_mod_from_register_to_register() {
2077 let mut program = BpfCode::new();
2078 program
2079 .modulo(Source::Reg, Arch::X32)
2080 .set_dst(0x01)
2081 .set_src(0x02)
2082 .push();
2083
2084 assert_eq!(
2085 program.into_bytes(),
2086 &[0x9c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2087 );
2088 }
2089
2090 #[test]
2091 fn move_bit_xor_from_register_to_register() {
2092 let mut program = BpfCode::new();
2093 program
2094 .bit_xor(Source::Reg, Arch::X32)
2095 .set_dst(0x02)
2096 .set_src(0x04)
2097 .push();
2098
2099 assert_eq!(
2100 program.into_bytes(),
2101 &[0xac, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2102 );
2103 }
2104
2105 #[test]
2106 fn move_from_register_to_another_register() {
2107 let mut program = BpfCode::new();
2108 program
2109 .mov(Source::Reg, Arch::X32)
2110 .set_dst(0x00)
2111 .set_src(0x01)
2112 .push();
2113
2114 assert_eq!(
2115 program.into_bytes(),
2116 &[0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2117 );
2118 }
2119
2120 #[test]
2121 fn move_signed_right_shift_from_register_to_register() {
2122 let mut program = BpfCode::new();
2123 program
2124 .signed_right_shift(Source::Reg, Arch::X32)
2125 .set_dst(0x02)
2126 .set_src(0x03)
2127 .push();
2128
2129 assert_eq!(
2130 program.into_bytes(),
2131 &[0xcc, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
2132 );
2133 }
2134 }
2135 }
2136 }
2137
2138 #[cfg(test)]
2139 mod programs {
2140 use super::super::*;
2141
2142 #[test]
2143 fn example_from_assembler() {
2144 let mut program = BpfCode::new();
2145 program
2146 .add(Source::Imm, Arch::X64)
2147 .set_dst(1)
2148 .set_imm(0x605)
2149 .push()
2150 .mov(Source::Imm, Arch::X64)
2151 .set_dst(2)
2152 .set_imm(0x32)
2153 .push()
2154 .mov(Source::Reg, Arch::X64)
2155 .set_src(0)
2156 .set_dst(1)
2157 .push()
2158 .swap_bytes(Endian::Big)
2159 .set_dst(0)
2160 .set_imm(0x10)
2161 .push()
2162 .negate(Arch::X64)
2163 .set_dst(2)
2164 .push()
2165 .exit()
2166 .push();
2167
2168 let bytecode = program.into_bytes();
2169 let ref_prog = &[
2170 0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xb7, 0x02, 0x00, 0x00, 0x32, 0x00,
2171 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
2172 0x10, 0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00,
2173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2174 ];
2175 assert_eq!(bytecode[..32], ref_prog[..32]);
2179 assert_eq!(bytecode[33..], ref_prog[33..]);
2180 }
2181 }
2182}