1use ebpf::*;
7use crate::lib::*;
8
9pub trait Instruction: Sized {
11 fn opt_code_byte(&self) -> u8;
13
14 fn get_dst(&self) -> u8 {
16 self.get_insn().dst
17 }
18
19 fn get_src(&self) -> u8 {
21 self.get_insn().src
22 }
23
24 fn get_off(&self) -> i16 {
26 self.get_insn().off
27 }
28
29 fn get_imm(&self) -> i32 {
31 self.get_insn().imm
32 }
33
34 fn set_dst(mut self, dst: u8) -> Self {
36 self.get_insn_mut().dst = dst;
37 self
38 }
39
40 fn set_src(mut self, src: u8) -> Self {
42 self.get_insn_mut().src = src;
43 self
44 }
45
46 fn set_off(mut self, offset: i16) -> Self {
48 self.get_insn_mut().off = offset;
49 self
50 }
51
52 fn set_imm(mut self, imm: i32) -> Self {
54 self.get_insn_mut().imm = imm;
55 self
56 }
57
58 fn get_insn(&self) -> &Insn;
60
61 fn get_insn_mut(&mut self) -> &mut Insn;
63}
64
65pub trait IntoBytes {
68 type Bytes;
70
71 fn into_bytes(self) -> Self::Bytes;
73}
74
75impl<'i, I: Instruction> IntoBytes for &'i I {
77 type Bytes = Vec<u8>;
78
79 fn into_bytes(self) -> Self::Bytes {
83 let buffer = vec![
84 self.opt_code_byte(),
85 self.get_src() << 4 | self.get_dst(),
86 self.get_off() as u8,
87 (self.get_off() >> 8) as u8,
88 self.get_imm() as u8,
89 (self.get_imm() >> 8) as u8,
90 (self.get_imm() >> 16) as u8,
91 (self.get_imm() >> 24) as u8,
92 ];
93 buffer
94 }
95}
96
97#[derive(Default)]
99pub struct BpfCode {
100 instructions: Vec<u8>
101}
102
103impl BpfCode {
104 pub fn new() -> Self {
106 BpfCode { instructions: vec![] }
107 }
108
109 pub fn add(&mut self, source: Source, arch: Arch) -> Move {
111 self.mov_internal(source, arch, OpBits::Add)
112 }
113
114 pub fn sub(&mut self, source: Source, arch: Arch) -> Move {
116 self.mov_internal(source, arch, OpBits::Sub)
117 }
118
119 pub fn mul(&mut self, source: Source, arch: Arch) -> Move {
121 self.mov_internal(source, arch, OpBits::Mul)
122 }
123
124 pub fn div(&mut self, source: Source, arch: Arch) -> Move {
126 self.mov_internal(source, arch, OpBits::Div)
127 }
128
129 pub fn bit_or(&mut self, source: Source, arch: Arch) -> Move {
131 self.mov_internal(source, arch, OpBits::BitOr)
132 }
133
134 pub fn bit_and(&mut self, source: Source, arch: Arch) -> Move {
136 self.mov_internal(source, arch, OpBits::BitAnd)
137 }
138
139 pub fn left_shift(&mut self, source: Source, arch: Arch) -> Move {
141 self.mov_internal(source, arch, OpBits::LShift)
142 }
143
144 pub fn right_shift(&mut self, source: Source, arch: Arch) -> Move {
146 self.mov_internal(source, arch, OpBits::RShift)
147 }
148
149 pub fn negate(&mut self, arch: Arch) -> Move {
151 self.mov_internal(Source::Imm, arch, OpBits::Negate)
152 }
153
154 pub fn modulo(&mut self, source: Source, arch: Arch) -> Move {
156 self.mov_internal(source, arch, OpBits::Mod)
157 }
158
159 pub fn bit_xor(&mut self, source: Source, arch: Arch) -> Move {
161 self.mov_internal(source, arch, OpBits::BitXor)
162 }
163
164 pub fn mov(&mut self, source: Source, arch: Arch) -> Move {
166 self.mov_internal(source, arch, OpBits::Mov)
167 }
168
169 pub fn signed_right_shift(&mut self, source: Source, arch: Arch) -> Move {
171 self.mov_internal(source, arch, OpBits::SignRShift)
172 }
173
174 #[inline]
175 fn mov_internal(&mut self, source: Source, arch_bits: Arch, op_bits: OpBits) -> Move {
176 Move {
177 bpf_code: self,
178 src_bit: source,
179 op_bits,
180 arch_bits,
181 insn: Insn {
182 opc: 0x00,
183 dst: 0x00,
184 src: 0x00,
185 off: 0x00_00,
186 imm: 0x00_00_00_00
187 }
188 }
189 }
190
191 pub fn swap_bytes(&mut self, endian: Endian) -> SwapBytes {
193 SwapBytes {
194 bpf_code: self,
195 endian,
196 insn: Insn {
197 opc: 0x00,
198 dst: 0x00,
199 src: 0x00,
200 off: 0x00_00,
201 imm: 0x00_00_00_00
202 }
203 }
204 }
205
206 pub fn load(&mut self, mem_size: MemSize) -> Load {
208 self.load_internal(mem_size, Addressing::Imm, BPF_LD)
209 }
210
211 pub fn load_abs(&mut self, mem_size: MemSize) -> Load {
213 self.load_internal(mem_size, Addressing::Abs, BPF_LD)
214 }
215
216 pub fn load_ind(&mut self, mem_size: MemSize) -> Load {
218 self.load_internal(mem_size, Addressing::Ind, BPF_LD)
219 }
220
221 pub fn load_x(&mut self, mem_size: MemSize) -> Load {
223 self.load_internal(mem_size, Addressing::Mem, BPF_LDX)
224 }
225
226 #[inline]
227 fn load_internal(&mut self, mem_size: MemSize, addressing: Addressing, source: u8) -> Load {
228 Load {
229 bpf_code: self,
230 addressing,
231 mem_size,
232 source,
233 insn: Insn {
234 opc: 0x00,
235 dst: 0x00,
236 src: 0x00,
237 off: 0x00_00,
238 imm: 0x00_00_00_00
239 }
240 }
241 }
242
243 pub fn store(&mut self, mem_size: MemSize) -> Store {
245 self.store_internal(mem_size, BPF_IMM)
246 }
247
248 pub fn store_x(&mut self, mem_size: MemSize) -> Store {
250 self.store_internal(mem_size, BPF_MEM | BPF_STX)
251 }
252
253 #[inline]
254 fn store_internal(&mut self, mem_size: MemSize, source: u8) -> Store {
255 Store {
256 bpf_code: self,
257 mem_size,
258 source,
259 insn: Insn {
260 opc: 0x00,
261 dst: 0x00,
262 src: 0x00,
263 off: 0x00_00,
264 imm: 0x00_00_00_00
265 }
266 }
267 }
268
269 pub fn jump_unconditional(&mut self) -> Jump {
271 self.jump_conditional(Cond::Abs, Source::Imm)
272 }
273
274 pub fn jump_conditional(&mut self, cond: Cond, src_bit: Source) -> Jump {
276 Jump {
277 bpf_code: self,
278 cond,
279 src_bit,
280 insn: Insn {
281 opc: 0x00,
282 dst: 0x00,
283 src: 0x00,
284 off: 0x00_00,
285 imm: 0x00_00_00_00
286 }
287 }
288 }
289
290 pub fn call(&mut self) -> FunctionCall {
292 FunctionCall {
293 bpf_code: self,
294 insn: Insn {
295 opc: 0x00,
296 dst: 0x00,
297 src: 0x00,
298 off: 0x00_00,
299 imm: 0x00_00_00_00
300 }
301 }
302 }
303
304 pub fn exit(&mut self) -> Exit {
306 Exit {
307 bpf_code: self,
308 insn: Insn {
309 opc: 0x00,
310 dst: 0x00,
311 src: 0x00,
312 off: 0x00_00,
313 imm: 0x00_00_00_00
314 }
315 }
316 }
317}
318
319impl<'a> IntoBytes for &'a BpfCode {
321 type Bytes = &'a [u8];
322
323 fn into_bytes(self) -> Self::Bytes {
325 self.instructions.as_slice()
326 }
327}
328
329pub struct Move<'i> {
331 bpf_code: &'i mut BpfCode,
332 src_bit: Source,
333 op_bits: OpBits,
334 arch_bits: Arch,
335 insn: Insn
336}
337
338impl<'i> Move<'i> {
339 pub fn push(self) -> &'i mut BpfCode {
341 let mut asm = self.into_bytes();
342 self.bpf_code.instructions.append(&mut asm);
343 self.bpf_code
344 }
345}
346
347impl<'i> Instruction for Move<'i> {
348 fn opt_code_byte(&self) -> u8 {
349 let op_bits = self.op_bits as u8;
350 let src_bit = self.src_bit as u8;
351 let arch_bits = self.arch_bits as u8;
352 op_bits | src_bit | arch_bits
353 }
354
355 fn get_insn_mut(&mut self) -> &mut Insn {
356 &mut self.insn
357 }
358
359 fn get_insn(&self) -> &Insn {
360 &self.insn
361 }
362}
363
364#[derive(Copy, Clone, PartialEq, Eq)]
365pub enum Source {
367 Imm = BPF_IMM as isize,
369 Reg = BPF_X as isize
371}
372
373#[derive(Copy, Clone)]
374enum OpBits {
375 Add = BPF_ADD as isize,
376 Sub = BPF_SUB as isize,
377 Mul = BPF_MUL as isize,
378 Div = BPF_DIV as isize,
379 BitOr = BPF_OR as isize,
380 BitAnd = BPF_AND as isize,
381 LShift = BPF_LSH as isize,
382 RShift = BPF_RSH as isize,
383 Negate = BPF_NEG as isize,
384 Mod = BPF_MOD as isize,
385 BitXor = BPF_XOR as isize,
386 Mov = BPF_MOV as isize,
387 SignRShift = BPF_ARSH as isize
388}
389
390#[derive(Copy, Clone)]
391pub enum Arch {
393 X64 = BPF_ALU64 as isize,
395 X32 = BPF_ALU as isize
397}
398
399pub struct SwapBytes<'i> {
401 bpf_code: &'i mut BpfCode,
402 endian: Endian,
403 insn: Insn
404}
405
406impl<'i> SwapBytes<'i> {
407 pub fn push(self) -> &'i mut BpfCode {
409 let mut asm = self.into_bytes();
410 self.bpf_code.instructions.append(&mut asm);
411 self.bpf_code
412 }
413}
414
415impl<'i> Instruction for SwapBytes<'i> {
416 fn opt_code_byte(&self) -> u8 {
417 self.endian as u8
418 }
419
420 fn get_insn_mut(&mut self) -> &mut Insn {
421 &mut self.insn
422 }
423
424 fn get_insn(&self) -> &Insn {
425 &self.insn
426 }
427}
428
429#[derive(Copy, Clone)]
430pub enum Endian {
432 Little = LE as isize,
434 Big = BE as isize
436}
437
438pub struct Load<'i> {
440 bpf_code: &'i mut BpfCode,
441 addressing: Addressing,
442 mem_size: MemSize,
443 source: u8,
444 insn: Insn
445}
446
447impl<'i> Load<'i> {
448 pub fn push(self) -> &'i mut BpfCode {
450 let mut asm = self.into_bytes();
451 self.bpf_code.instructions.append(&mut asm);
452 self.bpf_code
453 }
454}
455
456impl<'i> Instruction for Load<'i> {
457 fn opt_code_byte(&self) -> u8 {
458 let size = self.mem_size as u8;
459 let addressing = self.addressing as u8;
460 addressing | size | self.source
461 }
462
463 fn get_insn_mut(&mut self) -> &mut Insn {
464 &mut self.insn
465 }
466
467 fn get_insn(&self) -> &Insn {
468 &self.insn
469 }
470}
471
472pub struct Store<'i> {
474 bpf_code: &'i mut BpfCode,
475 mem_size: MemSize,
476 source: u8,
477 insn: Insn
478}
479
480impl<'i> Store<'i> {
481 pub fn push(self) -> &'i mut BpfCode {
483 let mut asm = self.into_bytes();
484 self.bpf_code.instructions.append(&mut asm);
485 self.bpf_code
486 }
487}
488
489impl<'i> Instruction for Store<'i> {
490 fn opt_code_byte(&self) -> u8 {
491 let size = self.mem_size as u8;
492 BPF_MEM | BPF_ST | size | self.source
493 }
494
495 fn get_insn_mut(&mut self) -> &mut Insn {
496 &mut self.insn
497 }
498
499 fn get_insn(&self) -> &Insn {
500 &self.insn
501 }
502}
503
504#[derive(Copy, Clone)]
505pub enum MemSize {
507 Byte = BPF_B as isize,
509 HalfWord = BPF_H as isize,
511 Word = BPF_W as isize,
513 DoubleWord = BPF_DW as isize
515}
516
517#[derive(Copy, Clone)]
518enum Addressing {
519 Imm = BPF_IMM as isize,
520 Abs = BPF_ABS as isize,
521 Ind = BPF_IND as isize,
522 Mem = BPF_MEM as isize
523}
524
525pub struct Jump<'i> {
527 bpf_code: &'i mut BpfCode,
528 cond: Cond,
529 src_bit: Source,
530 insn: Insn
531}
532
533impl<'i> Jump<'i> {
534 pub fn push(self) -> &'i mut BpfCode {
536 let mut asm = self.into_bytes();
537 self.bpf_code.instructions.append(&mut asm);
538 self.bpf_code
539 }
540}
541
542impl<'i> Instruction for Jump<'i> {
543 fn opt_code_byte(&self) -> u8 {
544 let cmp: u8 = self.cond as u8;
545 let src_bit = self.src_bit as u8;
546 cmp | src_bit | BPF_JMP
547 }
548
549 fn get_insn_mut(&mut self) -> &mut Insn {
550 &mut self.insn
551 }
552
553 fn get_insn(&self) -> &Insn {
554 &self.insn
555 }
556}
557
558#[derive(Copy, Clone, PartialEq, Eq)]
559pub enum Cond {
561 Abs = BPF_JA as isize,
563 Equals = BPF_JEQ as isize,
565 Greater = BPF_JGT as isize,
567 GreaterEquals = BPF_JGE as isize,
569 Lower = BPF_JLT as isize,
571 LowerEquals = BPF_JLE as isize,
573 BitAnd = BPF_JSET as isize,
575 NotEquals = BPF_JNE as isize,
577 GreaterSigned = BPF_JSGT as isize,
579 GreaterEqualsSigned = BPF_JSGE as isize,
581 LowerSigned = BPF_JSLT as isize,
583 LowerEqualsSigned = BPF_JSLE as isize
585}
586
587pub struct FunctionCall<'i> {
589 bpf_code: &'i mut BpfCode,
590 insn: Insn
591}
592
593impl<'i> FunctionCall<'i> {
594 pub fn push(self) -> &'i mut BpfCode {
596 let mut asm = self.into_bytes();
597 self.bpf_code.instructions.append(&mut asm);
598 self.bpf_code
599 }
600}
601
602impl<'i> Instruction for FunctionCall<'i> {
603 fn opt_code_byte(&self) -> u8 {
604 BPF_CALL | BPF_JMP
605 }
606
607 fn get_insn_mut(&mut self) -> &mut Insn {
608 &mut self.insn
609 }
610
611 fn get_insn(&self) -> &Insn {
612 &self.insn
613 }
614}
615
616pub struct Exit<'i> {
618 bpf_code: &'i mut BpfCode,
619 insn: Insn
620}
621
622impl<'i> Exit<'i> {
623 pub fn push(self) -> &'i mut BpfCode {
625 let mut asm = self.into_bytes();
626 self.bpf_code.instructions.append(&mut asm);
627 self.bpf_code
628 }
629}
630
631impl<'i> Instruction for Exit<'i> {
632 fn opt_code_byte(&self) -> u8 {
633 BPF_EXIT | BPF_JMP
634 }
635
636 fn get_insn_mut(&mut self) -> &mut Insn {
637 &mut self.insn
638 }
639
640 fn get_insn(&self) -> &Insn {
641 &self.insn
642 }
643}
644
645#[cfg(test)]
646mod tests {
647 #[cfg(test)]
648 mod special {
649 use super::super::*;
650
651 #[test]
652 fn call_immediate() {
653 let mut program = BpfCode::new();
654 program.call().set_imm(0x11_22_33_44).push();
655
656 assert_eq!(program.into_bytes(), &[0x85, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
657 }
658
659 #[test]
660 fn exit_operation() {
661 let mut program = BpfCode::new();
662 program.exit().push();
663
664 assert_eq!(program.into_bytes(), &[0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
665 }
666 }
667
668 #[cfg(test)]
669 mod jump_instructions {
670 #[cfg(test)]
671 mod register {
672 use super::super::super::*;
673
674 #[test]
675 fn jump_on_dst_equals_src() {
676 let mut program = BpfCode::new();
677 program.jump_conditional(Cond::Equals, Source::Reg).set_dst(0x01).set_src(0x02).push();
678
679 assert_eq!(program.into_bytes(), &[0x1d, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
680 }
681
682 #[test]
683 fn jump_on_dst_greater_than_src() {
684 let mut program = BpfCode::new();
685 program.jump_conditional(Cond::Greater, Source::Reg).set_dst(0x03).set_src(0x02).push();
686
687 assert_eq!(program.into_bytes(), &[0x2d, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
688 }
689
690 #[test]
691 fn jump_on_dst_greater_or_equals_to_src() {
692 let mut program = BpfCode::new();
693 program.jump_conditional(Cond::GreaterEquals, Source::Reg).set_dst(0x04).set_src(0x01).push();
694
695 assert_eq!(program.into_bytes(), &[0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
696 }
697
698 #[test]
699 fn jump_on_dst_lower_than_src() {
700 let mut program = BpfCode::new();
701 program.jump_conditional(Cond::Lower, Source::Reg).set_dst(0x03).set_src(0x02).push();
702
703 assert_eq!(program.into_bytes(), &[0xad, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
704 }
705
706 #[test]
707 fn jump_on_dst_lower_or_equals_to_src() {
708 let mut program = BpfCode::new();
709 program.jump_conditional(Cond::LowerEquals, Source::Reg).set_dst(0x04).set_src(0x01).push();
710
711 assert_eq!(program.into_bytes(), &[0xbd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
712 }
713
714 #[test]
715 fn jump_on_dst_bit_and_with_src_not_equal_zero() {
716 let mut program = BpfCode::new();
717 program.jump_conditional(Cond::BitAnd, Source::Reg).set_dst(0x05).set_src(0x02).push();
718
719 assert_eq!(program.into_bytes(), &[0x4d, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
720 }
721
722 #[test]
723 fn jump_on_dst_not_equals_src() {
724 let mut program = BpfCode::new();
725 program.jump_conditional(Cond::NotEquals, Source::Reg).set_dst(0x03).set_src(0x05).push();
726
727 assert_eq!(program.into_bytes(), &[0x5d, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
728 }
729
730 #[test]
731 fn jump_on_dst_greater_than_src_signed() {
732 let mut program = BpfCode::new();
733 program.jump_conditional(Cond::GreaterSigned, Source::Reg).set_dst(0x04).set_src(0x01).push();
734
735 assert_eq!(program.into_bytes(), &[0x6d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
736 }
737
738 #[test]
739 fn jump_on_dst_greater_or_equals_src_signed() {
740 let mut program = BpfCode::new();
741 program.jump_conditional(Cond::GreaterEqualsSigned, Source::Reg).set_dst(0x01).set_src(0x03).push();
742
743 assert_eq!(program.into_bytes(), &[0x7d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
744 }
745
746 #[test]
747 fn jump_on_dst_lower_than_src_signed() {
748 let mut program = BpfCode::new();
749 program.jump_conditional(Cond::LowerSigned, Source::Reg).set_dst(0x04).set_src(0x01).push();
750
751 assert_eq!(program.into_bytes(), &[0xcd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
752 }
753
754 #[test]
755 fn jump_on_dst_lower_or_equals_src_signed() {
756 let mut program = BpfCode::new();
757 program.jump_conditional(Cond::LowerEqualsSigned, Source::Reg).set_dst(0x01).set_src(0x03).push();
758
759 assert_eq!(program.into_bytes(), &[0xdd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
760 }
761 }
762
763 #[cfg(test)]
764 mod immediate {
765 use super::super::super::*;
766
767 #[test]
768 fn jump_to_label() {
769 let mut program = BpfCode::new();
770 program.jump_unconditional().set_off(0x00_11).push();
771
772 assert_eq!(program.into_bytes(), &[0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
773 }
774
775 #[test]
776 fn jump_on_dst_equals_const() {
777 let mut program = BpfCode::new();
778 program.jump_conditional(Cond::Equals, Source::Imm).set_dst(0x01).set_imm(0x00_11_22_33).push();
779
780 assert_eq!(program.into_bytes(), &[0x15, 0x01, 0x00, 0x00, 0x33, 0x22, 0x11, 0x00]);
781 }
782
783 #[test]
784 fn jump_on_dst_greater_than_const() {
785 let mut program = BpfCode::new();
786 program.jump_conditional(Cond::Greater, Source::Imm).set_dst(0x02).set_imm(0x00_11_00_11).push();
787
788 assert_eq!(program.into_bytes(), &[0x25, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]);
789 }
790
791 #[test]
792 fn jump_on_dst_greater_or_equals_to_const() {
793 let mut program = BpfCode::new();
794 program.jump_conditional(Cond::GreaterEquals, Source::Imm).set_dst(0x04).set_imm(0x00_22_11_00).push();
795
796 assert_eq!(program.into_bytes(), &[0x35, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]);
797 }
798
799 #[test]
800 fn jump_on_dst_lower_than_const() {
801 let mut program = BpfCode::new();
802 program.jump_conditional(Cond::Lower, Source::Imm).set_dst(0x02).set_imm(0x00_11_00_11).push();
803
804 assert_eq!(program.into_bytes(), &[0xa5, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]);
805 }
806
807 #[test]
808 fn jump_on_dst_lower_or_equals_to_const() {
809 let mut program = BpfCode::new();
810 program.jump_conditional(Cond::LowerEquals, Source::Imm).set_dst(0x04).set_imm(0x00_22_11_00).push();
811
812 assert_eq!(program.into_bytes(), &[0xb5, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]);
813 }
814
815 #[test]
816 fn jump_on_dst_bit_and_with_const_not_equal_zero() {
817 let mut program = BpfCode::new();
818 program.jump_conditional(Cond::BitAnd, Source::Imm).set_dst(0x05).push();
819
820 assert_eq!(program.into_bytes(), &[0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
821 }
822
823 #[test]
824 fn jump_on_dst_not_equals_const() {
825 let mut program = BpfCode::new();
826 program.jump_conditional(Cond::NotEquals, Source::Imm).set_dst(0x03).push();
827
828 assert_eq!(program.into_bytes(), &[0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
829 }
830
831 #[test]
832 fn jump_on_dst_greater_than_const_signed() {
833 let mut program = BpfCode::new();
834 program.jump_conditional(Cond::GreaterSigned, Source::Imm).set_dst(0x04).push();
835
836 assert_eq!(program.into_bytes(), &[0x65, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
837 }
838
839 #[test]
840 fn jump_on_dst_greater_or_equals_src_signed() {
841 let mut program = BpfCode::new();
842 program.jump_conditional(Cond::GreaterEqualsSigned, Source::Imm).set_dst(0x01).push();
843
844 assert_eq!(program.into_bytes(), &[0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
845 }
846
847 #[test]
848 fn jump_on_dst_lower_than_const_signed() {
849 let mut program = BpfCode::new();
850 program.jump_conditional(Cond::LowerSigned, Source::Imm).set_dst(0x04).push();
851
852 assert_eq!(program.into_bytes(), &[0xc5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
853 }
854
855 #[test]
856 fn jump_on_dst_lower_or_equals_src_signed() {
857 let mut program = BpfCode::new();
858 program.jump_conditional(Cond::LowerEqualsSigned, Source::Imm).set_dst(0x01).push();
859
860 assert_eq!(program.into_bytes(), &[0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
861 }
862 }
863 }
864
865 #[cfg(test)]
866 mod store_instructions {
867 use super::super::*;
868
869 #[test]
870 fn store_word_from_dst_into_immediate_address() {
871 let mut program = BpfCode::new();
872 program.store(MemSize::Word).set_dst(0x01).set_off(0x00_11).set_imm(0x11_22_33_44).push();
873
874 assert_eq!(program.into_bytes(), &[0x62, 0x01, 0x11, 0x00, 0x44, 0x33, 0x22, 0x11]);
875 }
876
877 #[test]
878 fn store_half_word_from_dst_into_immediate_address() {
879 let mut program = BpfCode::new();
880 program.store(MemSize::HalfWord).set_dst(0x02).set_off(0x11_22).push();
881
882 assert_eq!(program.into_bytes(), &[0x6a, 0x02, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]);
883 }
884
885 #[test]
886 fn store_byte_from_dst_into_immediate_address() {
887 let mut program = BpfCode::new();
888 program.store(MemSize::Byte).push();
889
890 assert_eq!(program.into_bytes(), &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
891 }
892
893 #[test]
894 fn store_double_word_from_dst_into_immediate_address() {
895 let mut program = BpfCode::new();
896 program.store(MemSize::DoubleWord).push();
897
898 assert_eq!(program.into_bytes(), &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
899 }
900
901 #[test]
902 fn store_word_from_dst_into_src_address() {
903 let mut program = BpfCode::new();
904 program.store_x(MemSize::Word).set_dst(0x01).set_src(0x02).push();
905
906 assert_eq!(program.into_bytes(), &[0x63, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
907 }
908
909 #[test]
910 fn store_half_word_from_dst_into_src_address() {
911 let mut program = BpfCode::new();
912 program.store_x(MemSize::HalfWord).push();
913
914 assert_eq!(program.into_bytes(), &[0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
915 }
916
917 #[test]
918 fn store_byte_from_dst_into_src_address() {
919 let mut program = BpfCode::new();
920 program.store_x(MemSize::Byte).push();
921
922 assert_eq!(program.into_bytes(), &[0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
923 }
924
925 #[test]
926 fn store_double_word_from_dst_into_src_address() {
927 let mut program = BpfCode::new();
928 program.store_x(MemSize::DoubleWord).push();
929
930 assert_eq!(program.into_bytes(), &[0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
931 }
932 }
933
934 #[cfg(test)]
935 mod load_instructions {
936 #[cfg(test)]
937 mod register {
938 use super::super::super::*;
939
940 #[test]
941 fn load_word_from_set_src_with_offset() {
942 let mut program = BpfCode::new();
943 program.load_x(MemSize::Word).set_dst(0x01).set_src(0x02).set_off(0x00_02).push();
944
945 assert_eq!(program.into_bytes(), &[0x61, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]);
946 }
947
948 #[test]
949 fn load_half_word_from_set_src_with_offset() {
950 let mut program = BpfCode::new();
951 program.load_x(MemSize::HalfWord).set_dst(0x02).set_src(0x01).set_off(0x11_22).push();
952
953 assert_eq!(program.into_bytes(), &[0x69, 0x12, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]);
954 }
955
956 #[test]
957 fn load_byte_from_set_src_with_offset() {
958 let mut program = BpfCode::new();
959 program.load_x(MemSize::Byte).set_dst(0x01).set_src(0x04).set_off(0x00_11).push();
960
961 assert_eq!(program.into_bytes(), &[0x71, 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
962 }
963
964 #[test]
965 fn load_double_word_from_set_src_with_offset() {
966 let mut program = BpfCode::new();
967 program.load_x(MemSize::DoubleWord).set_dst(0x04).set_src(0x05).set_off(0x44_55).push();
968
969 assert_eq!(program.into_bytes(), &[0x79, 0x54, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00]);
970 }
971 }
972
973 #[cfg(test)]
974 mod immediate {
975 use super::super::super::*;
976
977 #[test]
978 fn load_double_word() {
979 let mut program = BpfCode::new();
980 program.load(MemSize::DoubleWord).set_dst(0x01).set_imm(0x00_01_02_03).push();
981
982 assert_eq!(program.into_bytes(), &[0x18, 0x01, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
983 }
984
985 #[test]
986 fn load_abs_word() {
987 let mut program = BpfCode::new();
988 program.load_abs(MemSize::Word).push();
989
990 assert_eq!(program.into_bytes(), &[0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
991 }
992
993 #[test]
994 fn load_abs_half_word() {
995 let mut program = BpfCode::new();
996 program.load_abs(MemSize::HalfWord).set_dst(0x05).push();
997
998 assert_eq!(program.into_bytes(), &[0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
999 }
1000
1001 #[test]
1002 fn load_abs_byte() {
1003 let mut program = BpfCode::new();
1004 program.load_abs(MemSize::Byte).set_dst(0x01).push();
1005
1006 assert_eq!(program.into_bytes(), &[0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1007 }
1008
1009 #[test]
1010 fn load_abs_double_word() {
1011 let mut program = BpfCode::new();
1012 program.load_abs(MemSize::DoubleWord).set_dst(0x01).set_imm(0x01_02_03_04).push();
1013
1014 assert_eq!(program.into_bytes(), &[0x38, 0x01, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
1015 }
1016
1017 #[test]
1018 fn load_indirect_word() {
1019 let mut program = BpfCode::new();
1020 program.load_ind(MemSize::Word).push();
1021
1022 assert_eq!(program.into_bytes(), &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1023 }
1024
1025 #[test]
1026 fn load_indirect_half_word() {
1027 let mut program = BpfCode::new();
1028 program.load_ind(MemSize::HalfWord).push();
1029
1030 assert_eq!(program.into_bytes(), &[0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1031 }
1032
1033 #[test]
1034 fn load_indirect_byte() {
1035 let mut program = BpfCode::new();
1036 program.load_ind(MemSize::Byte).push();
1037
1038 assert_eq!(program.into_bytes(), &[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1039 }
1040
1041 #[test]
1042 fn load_indirect_double_word() {
1043 let mut program = BpfCode::new();
1044 program.load_ind(MemSize::DoubleWord).push();
1045
1046 assert_eq!(program.into_bytes(), &[0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1047 }
1048 }
1049 }
1050
1051 #[cfg(test)]
1052 mod byte_swap_instructions {
1053 use super::super::*;
1054
1055 #[test]
1056 fn convert_host_to_little_endian_16bits() {
1057 let mut program = BpfCode::new();
1058 program.swap_bytes(Endian::Little).set_dst(0x01).set_imm(0x00_00_00_10).push();
1059
1060 assert_eq!(program.into_bytes(), &[0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]);
1061 }
1062
1063 #[test]
1064 fn convert_host_to_little_endian_32bits() {
1065 let mut program = BpfCode::new();
1066 program.swap_bytes(Endian::Little).set_dst(0x02).set_imm(0x00_00_00_20).push();
1067
1068 assert_eq!(program.into_bytes(), &[0xd4, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]);
1069 }
1070
1071 #[test]
1072 fn convert_host_to_little_endian_64bit() {
1073 let mut program = BpfCode::new();
1074 program.swap_bytes(Endian::Little).set_dst(0x03).set_imm(0x00_00_00_40).push();
1075
1076 assert_eq!(program.into_bytes(), &[0xd4, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]);
1077 }
1078
1079 #[test]
1080 fn convert_host_to_big_endian_16bits() {
1081 let mut program = BpfCode::new();
1082 program.swap_bytes(Endian::Big).set_dst(0x01).set_imm(0x00_00_00_10).push();
1083
1084 assert_eq!(program.into_bytes(), &[0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]);
1085 }
1086
1087 #[test]
1088 fn convert_host_to_big_endian_32bits() {
1089 let mut program = BpfCode::new();
1090 program.swap_bytes(Endian::Big).set_dst(0x02).set_imm(0x00_00_00_20).push();
1091
1092 assert_eq!(program.into_bytes(), &[0xdc, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]);
1093 }
1094
1095 #[test]
1096 fn convert_host_to_big_endian_64bit() {
1097 let mut program = BpfCode::new();
1098 program.swap_bytes(Endian::Big).set_dst(0x03).set_imm(0x00_00_00_40).push();
1099
1100 assert_eq!(program.into_bytes(), &[0xdc, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]);
1101 }
1102 }
1103
1104 #[cfg(test)]
1105 mod moves_instructions {
1106 #[cfg(test)]
1107 mod arch_x64 {
1108 #[cfg(test)]
1109 mod immediate {
1110 use super::super::super::super::*;
1111
1112 #[test]
1113 fn move_and_add_const_to_register() {
1114 let mut program = BpfCode::new();
1115 program.add(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x01_02_03_04).push();
1116
1117 assert_eq!(program.into_bytes(), &[0x07, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
1118 }
1119
1120 #[test]
1121 fn move_sub_const_to_register() {
1122 let mut program = BpfCode::new();
1123 program.sub(Source::Imm, Arch::X64).set_dst(0x04).set_imm(0x00_01_02_03).push();
1124
1125 assert_eq!(program.into_bytes(), &[0x17, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
1126 }
1127
1128 #[test]
1129 fn move_mul_const_to_register() {
1130 let mut program = BpfCode::new();
1131 program.mul(Source::Imm, Arch::X64).set_dst(0x05).set_imm(0x04_03_02_01).push();
1132
1133 assert_eq!(program.into_bytes(), &[0x27, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]);
1134 }
1135
1136 #[test]
1137 fn move_div_constant_to_register() {
1138 let mut program = BpfCode::new();
1139 program.div(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x00_ff_00_ff).push();
1140
1141 assert_eq!(program.into_bytes(), &[0x37, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]);
1142 }
1143
1144 #[test]
1145 fn move_bit_or_const_to_register() {
1146 let mut program = BpfCode::new();
1147 program.bit_or(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x00_11_00_22).push();
1148
1149 assert_eq!(program.into_bytes(), &[0x47, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]);
1150 }
1151
1152 #[test]
1153 fn move_bit_and_const_to_register() {
1154 let mut program = BpfCode::new();
1155 program.bit_and(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x11_22_33_44).push();
1156
1157 assert_eq!(program.into_bytes(), &[0x57, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
1158 }
1159
1160 #[test]
1161 fn move_left_shift_const_to_register() {
1162 let mut program = BpfCode::new();
1163 program.left_shift(Source::Imm, Arch::X64).set_dst(0x01).push();
1164
1165 assert_eq!(program.into_bytes(), &[0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1166 }
1167
1168 #[test]
1169 fn move_logical_right_shift_const_to_register() {
1170 let mut program = BpfCode::new();
1171 program.right_shift(Source::Imm, Arch::X64).set_dst(0x01).push();
1172
1173 assert_eq!(program.into_bytes(), &[0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1174 }
1175
1176 #[test]
1177 fn move_negate_register() {
1178 let mut program = BpfCode::new();
1179 program.negate(Arch::X64).set_dst(0x02).push();
1180
1181 assert_eq!(program.into_bytes(), &[0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1182 }
1183
1184 #[test]
1185 fn move_mod_const_to_register() {
1186 let mut program = BpfCode::new();
1187 program.modulo(Source::Imm, Arch::X64).set_dst(0x02).push();
1188
1189 assert_eq!(program.into_bytes(), &[0x97, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1190 }
1191
1192 #[test]
1193 fn move_bit_xor_const_to_register() {
1194 let mut program = BpfCode::new();
1195 program.bit_xor(Source::Imm, Arch::X64).set_dst(0x03).push();
1196
1197 assert_eq!(program.into_bytes(), &[0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1198 }
1199
1200 #[test]
1201 fn move_const_to_register() {
1202 let mut program = BpfCode::new();
1203 program.mov(Source::Imm, Arch::X64).set_dst(0x01).set_imm(0x00_00_00_FF).push();
1204
1205 assert_eq!(program.into_bytes(), &[0xb7, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]);
1206 }
1207
1208 #[test]
1209 fn move_signed_right_shift_const_to_register() {
1210 let mut program = BpfCode::new();
1211 program.signed_right_shift(Source::Imm, Arch::X64).set_dst(0x05).push();
1212
1213 assert_eq!(program.into_bytes(), &[0xc7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1214 }
1215 }
1216
1217 #[cfg(test)]
1218 mod register {
1219 use super::super::super::super::*;
1220
1221 #[test]
1222 fn move_and_add_from_register() {
1223 let mut program = BpfCode::new();
1224 program.add(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x02).push();
1225
1226 assert_eq!(program.into_bytes(), &[0x0f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1227 }
1228
1229 #[test]
1230 fn move_sub_from_register_to_register() {
1231 let mut program = BpfCode::new();
1232 program.sub(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x04).push();
1233
1234 assert_eq!(program.into_bytes(), &[0x1f, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1235 }
1236
1237 #[test]
1238 fn move_mul_from_register_to_register() {
1239 let mut program = BpfCode::new();
1240 program.mul(Source::Reg, Arch::X64).set_dst(0x04).set_src(0x03).push();
1241
1242 assert_eq!(program.into_bytes(), &[0x2f, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1243 }
1244
1245 #[test]
1246 fn move_div_from_register_to_register() {
1247 let mut program = BpfCode::new();
1248 program.div(Source::Reg, Arch::X64).set_dst(0x01).set_src(0x00).push();
1249
1250 assert_eq!(program.into_bytes(), &[0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1251 }
1252
1253 #[test]
1254 fn move_bit_or_from_register_to_register() {
1255 let mut program = BpfCode::new();
1256 program.bit_or(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x01).push();
1257
1258 assert_eq!(program.into_bytes(), &[0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1259 }
1260
1261 #[test]
1262 fn move_bit_and_from_register_to_register() {
1263 let mut program = BpfCode::new();
1264 program.bit_and(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x02).push();
1265
1266 assert_eq!(program.into_bytes(), &[0x5f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1267 }
1268
1269 #[test]
1270 fn move_left_shift_from_register_to_register() {
1271 let mut program = BpfCode::new();
1272 program.left_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x03).push();
1273
1274 assert_eq!(program.into_bytes(), &[0x6f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1275 }
1276
1277 #[test]
1278 fn move_logical_right_shift_from_register_to_register() {
1279 let mut program = BpfCode::new();
1280 program.right_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x04).push();
1281
1282 assert_eq!(program.into_bytes(), &[0x7f, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1283 }
1284
1285 #[test]
1286 fn move_mod_from_register_to_register() {
1287 let mut program = BpfCode::new();
1288 program.modulo(Source::Reg, Arch::X64).set_dst(0x01).set_src(0x02).push();
1289
1290 assert_eq!(program.into_bytes(), &[0x9f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1291 }
1292
1293 #[test]
1294 fn move_bit_xor_from_register_to_register() {
1295 let mut program = BpfCode::new();
1296 program.bit_xor(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x04).push();
1297
1298 assert_eq!(program.into_bytes(), &[0xaf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1299 }
1300
1301 #[test]
1302 fn move_from_register_to_another_register() {
1303 let mut program = BpfCode::new();
1304 program.mov(Source::Reg, Arch::X64).set_src(0x01).push();
1305
1306 assert_eq!(program.into_bytes(), &[0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1307 }
1308
1309 #[test]
1310 fn move_signed_right_shift_from_register_to_register() {
1311 let mut program = BpfCode::new();
1312 program.signed_right_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x03).push();
1313
1314 assert_eq!(program.into_bytes(), &[0xcf, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1315 }
1316 }
1317 }
1318
1319 #[cfg(test)]
1320 mod arch_x32 {
1321 #[cfg(test)]
1322 mod immediate {
1323 use super::super::super::super::*;
1324
1325 #[test]
1326 fn move_and_add_const_to_register() {
1327 let mut program = BpfCode::new();
1328 program.add(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x01_02_03_04).push();
1329
1330 assert_eq!(program.into_bytes(), &[0x04, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
1331 }
1332
1333 #[test]
1334 fn move_sub_const_to_register() {
1335 let mut program = BpfCode::new();
1336 program.sub(Source::Imm, Arch::X32).set_dst(0x04).set_imm(0x00_01_02_03).push();
1337
1338 assert_eq!(program.into_bytes(), &[0x14, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
1339 }
1340
1341 #[test]
1342 fn move_mul_const_to_register() {
1343 let mut program = BpfCode::new();
1344 program.mul(Source::Imm, Arch::X32).set_dst(0x05).set_imm(0x04_03_02_01).push();
1345
1346 assert_eq!(program.into_bytes(), &[0x24, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]);
1347 }
1348
1349 #[test]
1350 fn move_div_constant_to_register() {
1351 let mut program = BpfCode::new();
1352 program.div(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x00_ff_00_ff).push();
1353
1354 assert_eq!(program.into_bytes(), &[0x34, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]);
1355 }
1356
1357 #[test]
1358 fn move_bit_or_const_to_register() {
1359 let mut program = BpfCode::new();
1360 program.bit_or(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x00_11_00_22).push();
1361
1362 assert_eq!(program.into_bytes(), &[0x44, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]);
1363 }
1364
1365 #[test]
1366 fn move_bit_and_const_to_register() {
1367 let mut program = BpfCode::new();
1368 program.bit_and(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x11_22_33_44).push();
1369
1370 assert_eq!(program.into_bytes(), &[0x54, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
1371 }
1372
1373 #[test]
1374 fn move_left_shift_const_to_register() {
1375 let mut program = BpfCode::new();
1376 program.left_shift(Source::Imm, Arch::X32).set_dst(0x01).push();
1377
1378 assert_eq!(program.into_bytes(), &[0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1379 }
1380
1381 #[test]
1382 fn move_logical_right_shift_const_to_register() {
1383 let mut program = BpfCode::new();
1384 program.right_shift(Source::Imm, Arch::X32).set_dst(0x01).push();
1385
1386 assert_eq!(program.into_bytes(), &[0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1387 }
1388
1389 #[test]
1390 fn move_negate_register() {
1391 let mut program = BpfCode::new();
1392 program.negate(Arch::X32).set_dst(0x02).push();
1393
1394 assert_eq!(program.into_bytes(), &[0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1395 }
1396
1397 #[test]
1398 fn move_mod_const_to_register() {
1399 let mut program = BpfCode::new();
1400 program.modulo(Source::Imm, Arch::X32).set_dst(0x02).push();
1401
1402 assert_eq!(program.into_bytes(), &[0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1403 }
1404
1405 #[test]
1406 fn move_bit_xor_const_to_register() {
1407 let mut program = BpfCode::new();
1408 program.bit_xor(Source::Imm, Arch::X32).set_dst(0x03).push();
1409
1410 assert_eq!(program.into_bytes(), &[0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1411 }
1412
1413 #[test]
1414 fn move_const_to_register() {
1415 let mut program = BpfCode::new();
1416 program.mov(Source::Imm, Arch::X32).set_dst(0x01).set_imm(0x00_00_00_FF).push();
1417
1418 assert_eq!(program.into_bytes(), &[0xb4, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]);
1419 }
1420
1421 #[test]
1422 fn move_signed_right_shift_const_to_register() {
1423 let mut program = BpfCode::new();
1424 program.signed_right_shift(Source::Imm, Arch::X32).set_dst(0x05).push();
1425
1426 assert_eq!(program.into_bytes(), &[0xc4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1427 }
1428 }
1429
1430 #[cfg(test)]
1431 mod register {
1432 use super::super::super::super::*;
1433
1434 #[test]
1435 fn move_and_add_from_register() {
1436 let mut program = BpfCode::new();
1437 program.add(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x02).push();
1438
1439 assert_eq!(program.into_bytes(), &[0x0c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1440 }
1441
1442 #[test]
1443 fn move_sub_from_register_to_register() {
1444 let mut program = BpfCode::new();
1445 program.sub(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x04).push();
1446
1447 assert_eq!(program.into_bytes(), &[0x1c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1448 }
1449
1450 #[test]
1451 fn move_mul_from_register_to_register() {
1452 let mut program = BpfCode::new();
1453 program.mul(Source::Reg, Arch::X32).set_dst(0x04).set_src(0x03).push();
1454
1455 assert_eq!(program.into_bytes(), &[0x2c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1456 }
1457
1458 #[test]
1459 fn move_div_from_register_to_register() {
1460 let mut program = BpfCode::new();
1461 program.div(Source::Reg, Arch::X32).set_dst(0x01).set_src(0x00).push();
1462
1463 assert_eq!(program.into_bytes(), &[0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1464 }
1465
1466 #[test]
1467 fn move_bit_or_from_register_to_register() {
1468 let mut program = BpfCode::new();
1469 program.bit_or(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x01).push();
1470
1471 assert_eq!(program.into_bytes(), &[0x4c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1472 }
1473
1474 #[test]
1475 fn move_bit_and_from_register_to_register() {
1476 let mut program = BpfCode::new();
1477 program.bit_and(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x02).push();
1478
1479 assert_eq!(program.into_bytes(), &[0x5c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1480 }
1481
1482 #[test]
1483 fn move_left_shift_from_register_to_register() {
1484 let mut program = BpfCode::new();
1485 program.left_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x03).push();
1486
1487 assert_eq!(program.into_bytes(), &[0x6c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1488 }
1489
1490 #[test]
1491 fn move_logical_right_shift_from_register_to_register() {
1492 let mut program = BpfCode::new();
1493 program.right_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x04).push();
1494
1495 assert_eq!(program.into_bytes(), &[0x7c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1496 }
1497
1498 #[test]
1499 fn move_mod_from_register_to_register() {
1500 let mut program = BpfCode::new();
1501 program.modulo(Source::Reg, Arch::X32).set_dst(0x01).set_src(0x02).push();
1502
1503 assert_eq!(program.into_bytes(), &[0x9c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1504 }
1505
1506 #[test]
1507 fn move_bit_xor_from_register_to_register() {
1508 let mut program = BpfCode::new();
1509 program.bit_xor(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x04).push();
1510
1511 assert_eq!(program.into_bytes(), &[0xac, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1512 }
1513
1514 #[test]
1515 fn move_from_register_to_another_register() {
1516 let mut program = BpfCode::new();
1517 program.mov(Source::Reg, Arch::X32).set_dst(0x00).set_src(0x01).push();
1518
1519 assert_eq!(program.into_bytes(), &[0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1520 }
1521
1522 #[test]
1523 fn move_signed_right_shift_from_register_to_register() {
1524 let mut program = BpfCode::new();
1525 program.signed_right_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x03).push();
1526
1527 assert_eq!(program.into_bytes(), &[0xcc, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
1528 }
1529 }
1530 }
1531 }
1532
1533 #[cfg(test)]
1534 mod programs {
1535 use super::super::*;
1536
1537 #[test]
1538 fn example_from_assembler() {
1539 let mut program = BpfCode::new();
1540 program.add(Source::Imm, Arch::X64).set_dst(1).set_imm(0x605).push()
1541 .mov(Source::Imm, Arch::X64).set_dst(2).set_imm(0x32).push()
1542 .mov(Source::Reg, Arch::X64).set_src(0).set_dst(1).push()
1543 .swap_bytes(Endian::Big).set_dst(0).set_imm(0x10).push()
1544 .negate(Arch::X64).set_dst(2).push()
1545 .exit().push();
1546
1547 let bytecode = program.into_bytes();
1548 let ref_prog = &[
1549 0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
1550 0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
1551 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1552 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1553 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1554 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1555 ];
1556 assert_eq!(bytecode[..32], ref_prog[..32]);
1560 assert_eq!(bytecode[33..], ref_prog[33..]);
1561 }
1562 }
1563}