Skip to content

Commit

Permalink
Merge pull request #17 from qmonnet/master
Browse files Browse the repository at this point in the history
Add BPF_J{LT,LE,SLT,SLE} instructions
  • Loading branch information
rlane authored Nov 13, 2017
2 parents b8c87d2 + a0a78eb commit 2e06fd4
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 1 deletion.
12 changes: 12 additions & 0 deletions tests/jle-imm.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- asm
mov32 r0, 0
mov32 r1, 5
jle r1, 4, +1 # Not taken
jle r1, 6, +1 # Taken
exit
jle r1, 5, +1 # Taken
exit
mov32 r0, 1
exit
-- result
0x1
14 changes: 14 additions & 0 deletions tests/jle-reg.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- asm
mov r0, 0
mov r1, 5
mov r2, 4
mov r3, 6
jle r1, r2, +2 # Not taken
jle r1, r1, +1 # Taken
exit
jle r1, r3, +1 # Taken
exit
mov r0, 1
exit
-- result
0x1
11 changes: 11 additions & 0 deletions tests/jlt-imm.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- asm
mov32 r0, 0
mov32 r1, 5
jlt r1, 4, +2 # Not taken
jlt r1, 5, +1 # Not taken
jlt r1, 6, +1 # Taken
exit
mov32 r0, 1
exit
-- result
0x1
13 changes: 13 additions & 0 deletions tests/jlt-reg.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- asm
mov r0, 0
mov r1, 5
mov r2, 4
mov r3, 6
jlt r1, r2, +2 # Not taken
jlt r1, r1, +1 # Not taken
jlt r1, r3, +1 # Taken
exit
mov r0, 1
exit
-- result
0x1
12 changes: 12 additions & 0 deletions tests/jsle-imm.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- asm
mov32 r0, 0
mov r1, 0xfffffffe
jsle r1, 0xfffffffd, +1 # Not taken
jsle r1, 0xffffffff, +1 # Taken
exit
mov32 r0, 1
jsle r1, 0xfffffffe, +1 # Taken
mov32 r0, 2
exit
-- result
0x1
15 changes: 15 additions & 0 deletions tests/jsle-reg.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-- asm
mov32 r0, 0
mov r1, 0xffffffff
mov r2, 0xfffffffe
mov32 r3, 0
jsle r1, r2, +1 # Not taken
jsle r1, r3, +1 # Taken
exit
mov32 r0, 1
mov r1, r2
jsle r1, r2, +1 # Taken
mov32 r0, 2
exit
-- result
0x1
11 changes: 11 additions & 0 deletions tests/jslt-imm.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- asm
mov32 r0, 0
mov r1, 0xfffffffe
jslt r1, 0xfffffffd, +2 # Not taken
jslt r1, 0xfffffffe, +1 # Not taken
jslt r1, 0xffffffff, +1 # Taken
exit
mov32 r0, 1
exit
-- result
0x1
13 changes: 13 additions & 0 deletions tests/jslt-reg.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- asm
mov32 r0, 0
mov r1, 0xfffffffe
mov r2, 0xfffffffd
mov r3, 0xffffffff
jslt r1, r1, +2 # Not taken
jslt r1, r2, +1 # Not taken
jslt r1, r3, +1 # Taken
exit
mov32 r0, 1
exit
-- result
0x1
2 changes: 1 addition & 1 deletion ubpf/asm_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def keywords(vs):
(keywords(mem_load_ops) + reg + "," + memref) | \
(keywords(["lddw"]) + reg + "," + imm)

jmp_cmp_ops = ['jeq', 'jgt', 'jge', 'jset', 'jne', 'jsgt', 'jsge']
jmp_cmp_ops = ['jeq', 'jgt', 'jge', 'jlt', 'jle', 'jset', 'jne', 'jsgt', 'jsge', 'jslt', 'jsle']
jmp_instruction = \
(keywords(jmp_cmp_ops) + reg + "," + (reg | imm) + "," + offset) | \
(keywords(['ja']) + offset) | \
Expand Down
4 changes: 4 additions & 0 deletions ubpf/assembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
'jne': 5,
'jsgt': 6,
'jsge': 7,
'jlt': 10,
'jle': 11,
'jslt': 12,
'jsle': 13,
}

JMP_MISC_OPS = {
Expand Down
4 changes: 4 additions & 0 deletions ubpf/disassembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
7: 'jsge',
8: 'call',
9: 'exit',
10: 'jlt',
11: 'jle',
12: 'jslt',
13: 'jsle',
}

MODES = {
Expand Down
8 changes: 8 additions & 0 deletions vm/ebpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,13 @@ struct ebpf_inst {
#define EBPF_OP_JSGE_REG (EBPF_CLS_JMP|EBPF_SRC_REG|0x70)
#define EBPF_OP_CALL (EBPF_CLS_JMP|0x80)
#define EBPF_OP_EXIT (EBPF_CLS_JMP|0x90)
#define EBPF_OP_JLT_IMM (EBPF_CLS_JMP|EBPF_SRC_IMM|0xa0)
#define EBPF_OP_JLT_REG (EBPF_CLS_JMP|EBPF_SRC_REG|0xa0)
#define EBPF_OP_JLE_IMM (EBPF_CLS_JMP|EBPF_SRC_IMM|0xb0)
#define EBPF_OP_JLE_REG (EBPF_CLS_JMP|EBPF_SRC_REG|0xb0)
#define EBPF_OP_JSLT_IMM (EBPF_CLS_JMP|EBPF_SRC_IMM|0xc0)
#define EBPF_OP_JSLT_REG (EBPF_CLS_JMP|EBPF_SRC_REG|0xc0)
#define EBPF_OP_JSLE_IMM (EBPF_CLS_JMP|EBPF_SRC_IMM|0xd0)
#define EBPF_OP_JSLE_REG (EBPF_CLS_JMP|EBPF_SRC_REG|0xd0)

#endif
32 changes: 32 additions & 0 deletions vm/ubpf_jit_x86_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,22 @@ translate(struct ubpf_vm *vm, struct jit_state *state, char **errmsg)
emit_cmp(state, src, dst);
emit_jcc(state, 0x83, target_pc);
break;
case EBPF_OP_JLT_IMM:
emit_cmp_imm32(state, dst, inst.imm);
emit_jcc(state, 0x82, target_pc);
break;
case EBPF_OP_JLT_REG:
emit_cmp(state, src, dst);
emit_jcc(state, 0x82, target_pc);
break;
case EBPF_OP_JLE_IMM:
emit_cmp_imm32(state, dst, inst.imm);
emit_jcc(state, 0x86, target_pc);
break;
case EBPF_OP_JLE_REG:
emit_cmp(state, src, dst);
emit_jcc(state, 0x86, target_pc);
break;
case EBPF_OP_JSET_IMM:
emit_alu64_imm32(state, 0xf7, 0, dst, inst.imm);
emit_jcc(state, 0x85, target_pc);
Expand Down Expand Up @@ -325,6 +341,22 @@ translate(struct ubpf_vm *vm, struct jit_state *state, char **errmsg)
emit_cmp(state, src, dst);
emit_jcc(state, 0x8d, target_pc);
break;
case EBPF_OP_JSLT_IMM:
emit_cmp_imm32(state, dst, inst.imm);
emit_jcc(state, 0x8c, target_pc);
break;
case EBPF_OP_JSLT_REG:
emit_cmp(state, src, dst);
emit_jcc(state, 0x8c, target_pc);
break;
case EBPF_OP_JSLE_IMM:
emit_cmp_imm32(state, dst, inst.imm);
emit_jcc(state, 0x8e, target_pc);
break;
case EBPF_OP_JSLE_REG:
emit_cmp(state, src, dst);
emit_jcc(state, 0x8e, target_pc);
break;
case EBPF_OP_CALL:
/* We reserve RCX for shifts */
emit_mov(state, R9, RCX);
Expand Down
48 changes: 48 additions & 0 deletions vm/ubpf_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,26 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len)
pc += inst.offset;
}
break;
case EBPF_OP_JLT_IMM:
if (reg[inst.dst] < (uint32_t)inst.imm) {
pc += inst.offset;
}
break;
case EBPF_OP_JLT_REG:
if (reg[inst.dst] < reg[inst.src]) {
pc += inst.offset;
}
break;
case EBPF_OP_JLE_IMM:
if (reg[inst.dst] <= (uint32_t)inst.imm) {
pc += inst.offset;
}
break;
case EBPF_OP_JLE_REG:
if (reg[inst.dst] <= reg[inst.src]) {
pc += inst.offset;
}
break;
case EBPF_OP_JSET_IMM:
if (reg[inst.dst] & inst.imm) {
pc += inst.offset;
Expand Down Expand Up @@ -505,6 +525,26 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len)
pc += inst.offset;
}
break;
case EBPF_OP_JSLT_IMM:
if ((int64_t)reg[inst.dst] < inst.imm) {
pc += inst.offset;
}
break;
case EBPF_OP_JSLT_REG:
if ((int64_t)reg[inst.dst] < (int64_t)reg[inst.src]) {
pc += inst.offset;
}
break;
case EBPF_OP_JSLE_IMM:
if ((int64_t)reg[inst.dst] <= inst.imm) {
pc += inst.offset;
}
break;
case EBPF_OP_JSLE_REG:
if ((int64_t)reg[inst.dst] <= (int64_t)reg[inst.src]) {
pc += inst.offset;
}
break;
case EBPF_OP_EXIT:
return reg[0];
case EBPF_OP_CALL:
Expand Down Expand Up @@ -623,6 +663,10 @@ validate(const struct ubpf_vm *vm, const struct ebpf_inst *insts, uint32_t num_i
case EBPF_OP_JGT_IMM:
case EBPF_OP_JGE_REG:
case EBPF_OP_JGE_IMM:
case EBPF_OP_JLT_REG:
case EBPF_OP_JLT_IMM:
case EBPF_OP_JLE_REG:
case EBPF_OP_JLE_IMM:
case EBPF_OP_JSET_REG:
case EBPF_OP_JSET_IMM:
case EBPF_OP_JNE_REG:
Expand All @@ -631,6 +675,10 @@ validate(const struct ubpf_vm *vm, const struct ebpf_inst *insts, uint32_t num_i
case EBPF_OP_JSGT_REG:
case EBPF_OP_JSGE_IMM:
case EBPF_OP_JSGE_REG:
case EBPF_OP_JSLT_IMM:
case EBPF_OP_JSLT_REG:
case EBPF_OP_JSLE_IMM:
case EBPF_OP_JSLE_REG:
if (inst.offset == -1) {
*errmsg = ubpf_error("infinite loop at PC %d", i);
return false;
Expand Down

0 comments on commit 2e06fd4

Please sign in to comment.