Преглед на файлове

src/lib.rs: Use clojure for implementing jumps

Avoid writing the same instructions many times for performing the jumps
in the interpreter. Use a mutable clojure to update the instruction
pointer instead, to improve readability.

Signed-off-by: Quentin Monnet <quentin@isovalent.com>
Quentin Monnet преди 2 години
родител
ревизия
4169726916
променени са 1 файла, в които са добавени 28 реда и са изтрити 24 реда
  1. 28 24
      src/lib.rs

+ 28 - 24
src/lib.rs

@@ -44,7 +44,7 @@ mod verifier;
 ///   - Unknown instructions.
 ///   - Bad formed instruction.
 ///   - Unknown eBPF helper index.
-pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
+pub type Verifier = fn (prog: &[u8]) -> Result<(), Error>;
 
 /// eBPF helper function.
 pub type Helper = fn (u64, u64, u64, u64, u64) -> u64;
@@ -308,6 +308,10 @@ impl<'a> EbpfVmMbuff<'a> {
             let _dst = insn.dst as usize;
             let _src = insn.src as usize;
 
+            let mut do_jump = || {
+                insn_ptr = (insn_ptr as i16 + insn.off) as usize;
+            };
+
             match insn.opc {
 
                 // BPF_LD class
@@ -522,29 +526,29 @@ impl<'a> EbpfVmMbuff<'a> {
 
                 // BPF_JMP class
                 // TODO: check this actually works as expected for signed / unsigned ops
-                ebpf::JA         =>                                             insn_ptr = (insn_ptr as i16 + insn.off) as usize,
-                ebpf::JEQ_IMM    => if  reg[_dst] == insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JEQ_REG    => if  reg[_dst] == reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JGT_IMM    => if  reg[_dst] >  insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JGT_REG    => if  reg[_dst] >  reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JGE_IMM    => if  reg[_dst] >= insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JGE_REG    => if  reg[_dst] >= reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JLT_IMM    => if  reg[_dst] <  insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JLT_REG    => if  reg[_dst] <  reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JLE_IMM    => if  reg[_dst] <= insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JLE_REG    => if  reg[_dst] <= reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSET_IMM   => if  reg[_dst] &  insn.imm as u64 != 0     { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSET_REG   => if  reg[_dst] &  reg[_src]       != 0     { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JNE_IMM    => if  reg[_dst] != insn.imm as u64          { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JNE_REG    => if  reg[_dst] != reg[_src]                { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSGT_IMM   => if  reg[_dst] as i64 >  insn.imm  as i64  { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSGT_REG   => if  reg[_dst] as i64 >  reg[_src] as i64  { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSGE_IMM   => if  reg[_dst] as i64 >= insn.imm  as i64  { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSGE_REG   => if  reg[_dst] as i64 >= reg[_src] as i64  { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSLT_IMM   => if (reg[_dst] as i64) <  insn.imm  as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSLT_REG   => if (reg[_dst] as i64) <  reg[_src] as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSLE_IMM   => if (reg[_dst] as i64) <= insn.imm  as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
-                ebpf::JSLE_REG   => if (reg[_dst] as i64) <= reg[_src] as i64 { insn_ptr = (insn_ptr as i16 + insn.off) as usize; },
+                ebpf::JA         =>                                             do_jump(),
+                ebpf::JEQ_IMM    => if  reg[_dst] == insn.imm as u64          { do_jump(); },
+                ebpf::JEQ_REG    => if  reg[_dst] == reg[_src]                { do_jump(); },
+                ebpf::JGT_IMM    => if  reg[_dst] >  insn.imm as u64          { do_jump(); },
+                ebpf::JGT_REG    => if  reg[_dst] >  reg[_src]                { do_jump(); },
+                ebpf::JGE_IMM    => if  reg[_dst] >= insn.imm as u64          { do_jump(); },
+                ebpf::JGE_REG    => if  reg[_dst] >= reg[_src]                { do_jump(); },
+                ebpf::JLT_IMM    => if  reg[_dst] <  insn.imm as u64          { do_jump(); },
+                ebpf::JLT_REG    => if  reg[_dst] <  reg[_src]                { do_jump(); },
+                ebpf::JLE_IMM    => if  reg[_dst] <= insn.imm as u64          { do_jump(); },
+                ebpf::JLE_REG    => if  reg[_dst] <= reg[_src]                { do_jump(); },
+                ebpf::JSET_IMM   => if  reg[_dst] &  insn.imm as u64 != 0     { do_jump(); },
+                ebpf::JSET_REG   => if  reg[_dst] &  reg[_src]       != 0     { do_jump(); },
+                ebpf::JNE_IMM    => if  reg[_dst] != insn.imm as u64          { do_jump(); },
+                ebpf::JNE_REG    => if  reg[_dst] != reg[_src]                { do_jump(); },
+                ebpf::JSGT_IMM   => if  reg[_dst] as i64  >  insn.imm  as i64 { do_jump(); },
+                ebpf::JSGT_REG   => if  reg[_dst] as i64  >  reg[_src] as i64 { do_jump(); },
+                ebpf::JSGE_IMM   => if  reg[_dst] as i64  >= insn.imm  as i64 { do_jump(); },
+                ebpf::JSGE_REG   => if  reg[_dst] as i64  >= reg[_src] as i64 { do_jump(); },
+                ebpf::JSLT_IMM   => if (reg[_dst] as i64) <  insn.imm  as i64 { do_jump(); },
+                ebpf::JSLT_REG   => if (reg[_dst] as i64) <  reg[_src] as i64 { do_jump(); },
+                ebpf::JSLE_IMM   => if  reg[_dst] as i64  <= insn.imm  as i64 { do_jump(); },
+                ebpf::JSLE_REG   => if  reg[_dst] as i64  <= reg[_src] as i64 { do_jump(); },
                 // Do not delegate the check to the verifier, since registered functions can be
                 // changed after the program has been verified.
                 ebpf::CALL       => if let Some(function) = self.helpers.get(&(insn.imm as u32)) {