Skip to content

Commit

Permalink
Swaps parameters of "sub imm" and removes "neg".
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Jul 28, 2023
1 parent 5debf64 commit 57ece7c
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 22 deletions.
6 changes: 3 additions & 3 deletions benches/vm_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ static ADDRESS_TRANSLATION_STACK_CODE: &str = "
and r1, 4095
mov r3, r10
sub r3, r1
sub r3, 1
add r3, -1
ldxb r4, [r3]
add r2, 1
jlt r2, 0x10000, -8
Expand Down Expand Up @@ -234,7 +234,7 @@ fn bench_jit_vs_interpreter_call_depth_fixed(bencher: &mut Bencher) {
jgt r6, 0, +1
exit
mov r1, r6
sub r1, 1
add r1, -1
call function_foo
exit",
Config {
Expand Down Expand Up @@ -264,7 +264,7 @@ fn bench_jit_vs_interpreter_call_depth_dynamic(bencher: &mut Bencher) {
mov r6, r1
jeq r6, 0, +3
mov r1, r6
sub r1, 1
add r1, -1
call function_foo
add r11, 4
exit",
Expand Down
2 changes: 1 addition & 1 deletion src/ebpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ pub const ST_DW_XADD: u8 = BPF_STX | BPF_XADD | BPF_DW;
pub const ADD32_IMM: u8 = BPF_ALU | BPF_K | BPF_ADD;
/// BPF opcode: `add32 dst, src` /// `dst += src`.
pub const ADD32_REG: u8 = BPF_ALU | BPF_X | BPF_ADD;
/// BPF opcode: `sub32 dst, imm` /// `dst -= imm`.
/// BPF opcode: `sub32 dst, imm` /// `dst = imm - dst`.
pub const SUB32_IMM: u8 = BPF_ALU | BPF_K | BPF_SUB;
/// BPF opcode: `sub32 dst, src` /// `dst -= src`.
pub const SUB32_REG: u8 = BPF_ALU | BPF_X | BPF_SUB;
Expand Down
10 changes: 10 additions & 0 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ pub enum SBPFVersion {
}

impl SBPFVersion {
/// Enable the negation instruction
pub fn enable_neg(&self) -> bool {
self == &SBPFVersion::V1
}

/// Swaps the reg and imm operands of the subtraction instruction
pub fn swap_sub_reg_imm_operands(&self) -> bool {
self != &SBPFVersion::V1
}

/// Disable the only two slots long instruction: LD_DW_IMM
pub fn disable_lddw(&self) -> bool {
self != &SBPFVersion::V1
Expand Down
16 changes: 12 additions & 4 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,11 @@ impl<'a, 'b, V: Verifier, C: ContextObject> Interpreter<'a, 'b, V, C> {
// BPF_ALU class
ebpf::ADD32_IMM => self.reg[dst] = (self.reg[dst] as i32).wrapping_add(insn.imm as i32) as u64,
ebpf::ADD32_REG => self.reg[dst] = (self.reg[dst] as i32).wrapping_add(self.reg[src] as i32) as u64,
ebpf::SUB32_IMM => self.reg[dst] = (self.reg[dst] as i32).wrapping_sub(insn.imm as i32) as u64,
ebpf::SUB32_IMM => if self.executable.get_sbpf_version().swap_sub_reg_imm_operands() {
self.reg[dst] = (insn.imm as i32).wrapping_sub(self.reg[dst] as i32) as u64
} else {
self.reg[dst] = (self.reg[dst] as i32).wrapping_sub(insn.imm as i32) as u64
},
ebpf::SUB32_REG => self.reg[dst] = (self.reg[dst] as i32).wrapping_sub(self.reg[src] as i32) as u64,
ebpf::MUL32_IMM => self.reg[dst] = (self.reg[dst] as i32).wrapping_mul(insn.imm as i32) as u64,
ebpf::MUL32_REG => self.reg[dst] = (self.reg[dst] as i32).wrapping_mul(self.reg[src] as i32) as u64,
Expand Down Expand Up @@ -298,7 +302,7 @@ impl<'a, 'b, V: Verifier, C: ContextObject> Interpreter<'a, 'b, V, C> {
ebpf::LSH32_REG => self.reg[dst] = (self.reg[dst] as u32).wrapping_shl(self.reg[src] as u32) as u64,
ebpf::RSH32_IMM => self.reg[dst] = (self.reg[dst] as u32).wrapping_shr(insn.imm as u32) as u64,
ebpf::RSH32_REG => self.reg[dst] = (self.reg[dst] as u32).wrapping_shr(self.reg[src] as u32) as u64,
ebpf::NEG32 => self.reg[dst] = (self.reg[dst] as i32).wrapping_neg() as u64 & (u32::MAX as u64),
ebpf::NEG32 if self.executable.get_sbpf_version().enable_neg() => self.reg[dst] = (self.reg[dst] as i32).wrapping_neg() as u64 & (u32::MAX as u64),
ebpf::MOD32_IMM => self.reg[dst] = (self.reg[dst] as u32 % insn.imm as u32) as u64,
ebpf::MOD32_REG => {
if self.reg[src] as u32 == 0 {
Expand Down Expand Up @@ -336,7 +340,11 @@ impl<'a, 'b, V: Verifier, C: ContextObject> Interpreter<'a, 'b, V, C> {
// BPF_ALU64 class
ebpf::ADD64_IMM => self.reg[dst] = self.reg[dst].wrapping_add(insn.imm as u64),
ebpf::ADD64_REG => self.reg[dst] = self.reg[dst].wrapping_add(self.reg[src]),
ebpf::SUB64_IMM => self.reg[dst] = self.reg[dst].wrapping_sub(insn.imm as u64),
ebpf::SUB64_IMM => if self.executable.get_sbpf_version().swap_sub_reg_imm_operands() {
self.reg[dst] = (insn.imm as u64).wrapping_sub(self.reg[dst])
} else {
self.reg[dst] = self.reg[dst].wrapping_sub(insn.imm as u64)
},
ebpf::SUB64_REG => self.reg[dst] = self.reg[dst].wrapping_sub(self.reg[src]),
ebpf::MUL64_IMM => self.reg[dst] = self.reg[dst].wrapping_mul(insn.imm as u64),
ebpf::MUL64_REG => self.reg[dst] = self.reg[dst].wrapping_mul(self.reg[src]),
Expand Down Expand Up @@ -370,7 +378,7 @@ impl<'a, 'b, V: Verifier, C: ContextObject> Interpreter<'a, 'b, V, C> {
ebpf::LSH64_REG => self.reg[dst] = self.reg[dst].wrapping_shl(self.reg[src] as u32),
ebpf::RSH64_IMM => self.reg[dst] = self.reg[dst].wrapping_shr(insn.imm as u32),
ebpf::RSH64_REG => self.reg[dst] = self.reg[dst].wrapping_shr(self.reg[src] as u32),
ebpf::NEG64 => self.reg[dst] = (self.reg[dst] as i64).wrapping_neg() as u64,
ebpf::NEG64 if self.executable.get_sbpf_version().enable_neg() => self.reg[dst] = (self.reg[dst] as i64).wrapping_neg() as u64,
ebpf::MOD64_IMM => self.reg[dst] %= insn.imm as u64,
ebpf::MOD64_REG => {
if self.reg[src] == 0 {
Expand Down
24 changes: 20 additions & 4 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,14 @@ impl<'a, V: Verifier, C: ContextObject> JitCompiler<'a, V, C> {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x63, dst, dst, 0, None)); // sign extend i32 to i64
},
ebpf::SUB32_IMM => {
self.emit_sanitized_alu(OperandSize::S32, 0x29, 5, dst, insn.imm);
if self.executable.get_sbpf_version().swap_sub_reg_imm_operands() {
self.emit_ins(X86Instruction::alu(OperandSize::S32, 0xf7, 3, dst, 0, None));
if insn.imm != 0 {
self.emit_sanitized_alu(OperandSize::S32, 0x01, 0, dst, insn.imm);
}
} else {
self.emit_sanitized_alu(OperandSize::S32, 0x29, 5, dst, insn.imm);
}
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x63, dst, dst, 0, None)); // sign extend i32 to i64
},
ebpf::SUB32_REG => {
Expand All @@ -487,7 +494,7 @@ impl<'a, V: Verifier, C: ContextObject> JitCompiler<'a, V, C> {
ebpf::LSH32_REG => self.emit_shift(OperandSize::S32, 4, src, dst, None),
ebpf::RSH32_IMM => self.emit_shift(OperandSize::S32, 5, R11, dst, Some(insn.imm)),
ebpf::RSH32_REG => self.emit_shift(OperandSize::S32, 5, src, dst, None),
ebpf::NEG32 => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0xf7, 3, dst, 0, None)),
ebpf::NEG32 if self.executable.get_sbpf_version().enable_neg() => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0xf7, 3, dst, 0, None)),
ebpf::XOR32_IMM => self.emit_sanitized_alu(OperandSize::S32, 0x31, 6, dst, insn.imm),
ebpf::XOR32_REG => self.emit_ins(X86Instruction::alu(OperandSize::S32, 0x31, src, dst, 0, None)),
ebpf::MOV32_IMM => {
Expand Down Expand Up @@ -531,7 +538,16 @@ impl<'a, V: Verifier, C: ContextObject> JitCompiler<'a, V, C> {
// BPF_ALU64 class
ebpf::ADD64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x01, 0, dst, insn.imm),
ebpf::ADD64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x01, src, dst, 0, None)),
ebpf::SUB64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x29, 5, dst, insn.imm),
ebpf::SUB64_IMM => {
if self.executable.get_sbpf_version().swap_sub_reg_imm_operands() {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0xf7, 3, dst, 0, None));
if insn.imm != 0 {
self.emit_sanitized_alu(OperandSize::S64, 0x01, 0, dst, insn.imm);
}
} else {
self.emit_sanitized_alu(OperandSize::S64, 0x29, 5, dst, insn.imm);
}
}
ebpf::SUB64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, src, dst, 0, None)),
ebpf::MUL64_IMM | ebpf::DIV64_IMM | ebpf::SDIV64_IMM | ebpf::MOD64_IMM =>
self.emit_muldivmod(insn.opc, dst, dst, Some(insn.imm)),
Expand All @@ -545,7 +561,7 @@ impl<'a, V: Verifier, C: ContextObject> JitCompiler<'a, V, C> {
ebpf::LSH64_REG => self.emit_shift(OperandSize::S64, 4, src, dst, None),
ebpf::RSH64_IMM => self.emit_shift(OperandSize::S64, 5, R11, dst, Some(insn.imm)),
ebpf::RSH64_REG => self.emit_shift(OperandSize::S64, 5, src, dst, None),
ebpf::NEG64 => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0xf7, 3, dst, 0, None)),
ebpf::NEG64 if self.executable.get_sbpf_version().enable_neg() => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0xf7, 3, dst, 0, None)),
ebpf::XOR64_IMM => self.emit_sanitized_alu(OperandSize::S64, 0x31, 6, dst, insn.imm),
ebpf::XOR64_REG => self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x31, src, dst, 0, None)),
ebpf::MOV64_IMM => {
Expand Down
4 changes: 2 additions & 2 deletions src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ impl Verifier for RequisiteVerifier {
ebpf::LSH32_REG => {},
ebpf::RSH32_IMM => { check_imm_shift(&insn, insn_ptr, 32)?; },
ebpf::RSH32_REG => {},
ebpf::NEG32 => {},
ebpf::NEG32 if sbpf_version.enable_neg() => {},
ebpf::MOD32_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MOD32_REG => {},
ebpf::XOR32_IMM => {},
Expand Down Expand Up @@ -319,7 +319,7 @@ impl Verifier for RequisiteVerifier {
ebpf::LSH64_REG => {},
ebpf::RSH64_IMM => { check_imm_shift(&insn, insn_ptr, 64)?; },
ebpf::RSH64_REG => {},
ebpf::NEG64 => {},
ebpf::NEG64 if sbpf_version.enable_neg() => {},
ebpf::MOD64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MOD64_REG => {},
ebpf::XOR64_IMM => {},
Expand Down
26 changes: 18 additions & 8 deletions tests/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,16 @@ fn test_add32() {

#[test]
fn test_neg32() {
let config = Config {
enable_sbpf_v2: false,
..Config::default()
};
test_interpreter_and_jit_asm!(
"
mov32 r0, 2
neg32 r0
exit",
config,
[],
(),
TestContextObject::new(3),
Expand All @@ -267,11 +272,16 @@ fn test_neg32() {

#[test]
fn test_neg64() {
let config = Config {
enable_sbpf_v2: false,
..Config::default()
};
test_interpreter_and_jit_asm!(
"
mov32 r0, 2
neg r0
exit",
config,
[],
(),
TestContextObject::new(3),
Expand All @@ -293,10 +303,10 @@ fn test_alu32_arithmetic() {
mov32 r7, 7
mov32 r8, 8
mov32 r9, 9
add32 r0, 23
add32 r0, r7
sub32 r0, 13
sub32 r0, r1
add32 r0, 23
add32 r0, r7
mul32 r0, 7
mul32 r0, r3
div32 r0, 2
Expand All @@ -305,7 +315,7 @@ fn test_alu32_arithmetic() {
[],
(),
TestContextObject::new(19),
ProgramResult::Ok(0x2a),
ProgramResult::Ok(110),
);
}

Expand All @@ -323,10 +333,10 @@ fn test_alu64_arithmetic() {
mov r7, 7
mov r8, 8
mov r9, 9
add r0, 23
add r0, r7
sub r0, 13
sub r0, r1
add r0, 23
add r0, r7
mul r0, 7
mul r0, r3
div r0, 2
Expand All @@ -335,7 +345,7 @@ fn test_alu64_arithmetic() {
[],
(),
TestContextObject::new(19),
ProgramResult::Ok(0x2a),
ProgramResult::Ok(110),
);
}

Expand Down Expand Up @@ -542,7 +552,7 @@ fn test_rhs32_imm() {
test_interpreter_and_jit_asm!(
"
xor r0, r0
sub r0, 1
add r0, -1
rsh32 r0, 8
exit",
[],
Expand Down Expand Up @@ -3366,7 +3376,7 @@ fn test_symbol_relocation() {
test_interpreter_and_jit_asm!(
"
mov64 r1, r10
sub64 r1, 0x1
add64 r1, -0x1
mov64 r2, 0x1
syscall bpf_syscall_string
mov64 r0, 0x0
Expand Down

0 comments on commit 57ece7c

Please sign in to comment.