From e16c054bb621df50a1710dcd9d1d613f13ef52d2 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 21 Sep 2017 20:42:34 -0400 Subject: [PATCH] Filter: add lshift, rshift, bit not ops Signed-off-by: Mathieu Desnoyers --- filter-bytecode.h | 6 ++-- lttng-filter-interpreter.c | 35 +++++++++++++++--- lttng-filter-specialize.c | 11 ++++-- lttng-filter-validator.c | 72 ++++++++++++++++++++++++++++++++++---- lttng-filter.c | 6 ++-- 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/filter-bytecode.h b/filter-bytecode.h index 931daa97..2aa5c2d0 100644 --- a/filter-bytecode.h +++ b/filter-bytecode.h @@ -72,8 +72,8 @@ enum filter_op { FILTER_OP_MOD = 4, FILTER_OP_PLUS = 5, FILTER_OP_MINUS = 6, - FILTER_OP_RSHIFT = 7, - FILTER_OP_LSHIFT = 8, + FILTER_OP_BIT_RSHIFT = 7, + FILTER_OP_BIT_LSHIFT = 8, FILTER_OP_BIT_AND = 9, FILTER_OP_BIT_OR = 10, FILTER_OP_BIT_XOR = 11, @@ -202,6 +202,8 @@ enum filter_op { FILTER_OP_LOAD_FIELD_SEQUENCE = 96, FILTER_OP_LOAD_FIELD_DOUBLE = 97, + FILTER_OP_UNARY_BIT_NOT = 98, + NR_FILTER_OPS, }; diff --git a/lttng-filter-interpreter.c b/lttng-filter-interpreter.c index 0bede9c5..5bf0bd60 100644 --- a/lttng-filter-interpreter.c +++ b/lttng-filter-interpreter.c @@ -647,8 +647,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD, [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS, [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS, - [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT, - [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT, + [ FILTER_OP_BIT_RSHIFT ] = &&LABEL_FILTER_OP_BIT_RSHIFT, + [ FILTER_OP_BIT_LSHIFT ] = &&LABEL_FILTER_OP_BIT_LSHIFT, [ FILTER_OP_BIT_AND ] = &&LABEL_FILTER_OP_BIT_AND, [ FILTER_OP_BIT_OR ] = &&LABEL_FILTER_OP_BIT_OR, [ FILTER_OP_BIT_XOR ] = &&LABEL_FILTER_OP_BIT_XOR, @@ -769,6 +769,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, [ FILTER_OP_LOAD_FIELD_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_STRING, [ FILTER_OP_LOAD_FIELD_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_SEQUENCE, [ FILTER_OP_LOAD_FIELD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_DOUBLE, + + [ FILTER_OP_UNARY_BIT_NOT ] = &&LABEL_FILTER_OP_UNARY_BIT_NOT, }; #endif /* #ifndef INTERPRETER_USE_SWITCH */ @@ -797,8 +799,6 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, OP(FILTER_OP_MOD): OP(FILTER_OP_PLUS): OP(FILTER_OP_MINUS): - OP(FILTER_OP_RSHIFT): - OP(FILTER_OP_LSHIFT): printk(KERN_WARNING "unsupported bytecode op %u\n", (unsigned int) *(filter_opcode_t *) pc); ret = -EINVAL; @@ -986,6 +986,26 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, BUG_ON(1); PO; } + OP(FILTER_OP_BIT_RSHIFT): + { + int64_t res; + + res = (estack_bx_v >> estack_ax_v); + estack_pop(stack, top, ax, bx); + estack_ax_v = res; + next_pc += sizeof(struct binary_op); + PO; + } + OP(FILTER_OP_BIT_LSHIFT): + { + int64_t res; + + res = (estack_bx_v << estack_ax_v); + estack_pop(stack, top, ax, bx); + estack_ax_v = res; + next_pc += sizeof(struct binary_op); + PO; + } OP(FILTER_OP_BIT_AND): { int64_t res; @@ -1027,6 +1047,13 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, goto end; + OP(FILTER_OP_UNARY_BIT_NOT): + { + estack_ax_v = ~estack_ax_v; + next_pc += sizeof(struct unary_op); + PO; + } + OP(FILTER_OP_UNARY_PLUS_S64): { next_pc += sizeof(struct unary_op); diff --git a/lttng-filter-specialize.c b/lttng-filter-specialize.c index 7112b0ae..b9ddfb10 100644 --- a/lttng-filter-specialize.c +++ b/lttng-filter-specialize.c @@ -527,8 +527,6 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: printk(KERN_WARNING "unsupported bytecode op %u\n", (unsigned int) *(filter_opcode_t *) pc); ret = -EINVAL; @@ -804,6 +802,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case FILTER_OP_LT_S64_DOUBLE: case FILTER_OP_GE_S64_DOUBLE: case FILTER_OP_LE_S64_DOUBLE: + case FILTER_OP_BIT_RSHIFT: + case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: case FILTER_OP_BIT_OR: case FILTER_OP_BIT_XOR: @@ -885,6 +885,13 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, break; } + case FILTER_OP_UNARY_BIT_NOT: + { + /* Pop 1, push 1 */ + next_pc += sizeof(struct unary_op); + break; + } + case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: case FILTER_OP_UNARY_NOT_S64: diff --git a/lttng-filter-validator.c b/lttng-filter-validator.c index cc8f4596..c7b81bb6 100644 --- a/lttng-filter-validator.c +++ b/lttng-filter-validator.c @@ -317,8 +317,6 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: case FILTER_OP_GT_DOUBLE: @@ -372,6 +370,8 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_LT_S64: case FILTER_OP_GE_S64: case FILTER_OP_LE_S64: + case FILTER_OP_BIT_RSHIFT: + case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: case FILTER_OP_BIT_OR: case FILTER_OP_BIT_XOR: @@ -390,6 +390,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: case FILTER_OP_UNARY_NOT_S64: + case FILTER_OP_UNARY_BIT_NOT: { if (unlikely(pc + sizeof(struct unary_op) > start_pc + bytecode->len)) { @@ -595,8 +596,6 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: /* Floating point */ case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: @@ -733,6 +732,16 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, break; } + case FILTER_OP_BIT_RSHIFT: + ret = bin_op_bitwise_check(stack, opcode, ">>"); + if (ret < 0) + goto end; + break; + case FILTER_OP_BIT_LSHIFT: + ret = bin_op_bitwise_check(stack, opcode, "<<"); + if (ret < 0) + goto end; + break; case FILTER_OP_BIT_AND: ret = bin_op_bitwise_check(stack, opcode, "&"); if (ret < 0) @@ -777,6 +786,32 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, } break; } + case FILTER_OP_UNARY_BIT_NOT: + { + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + default: + printk(KERN_WARNING "unknown register type\n"); + ret = -EINVAL; + goto end; + + case REG_STRING: + case REG_STAR_GLOB_STRING: + case REG_DOUBLE: + printk(KERN_WARNING "Unary bitwise op can only be applied to numeric registers\n"); + ret = -EINVAL; + goto end; + case REG_S64: + break; + case REG_TYPE_UNKNOWN: + break; + } + break; + } case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: @@ -1154,8 +1189,6 @@ int exec_insn(struct bytecode_runtime *bytecode, case FILTER_OP_MOD: case FILTER_OP_PLUS: case FILTER_OP_MINUS: - case FILTER_OP_RSHIFT: - case FILTER_OP_LSHIFT: /* Floating point */ case FILTER_OP_EQ_DOUBLE: case FILTER_OP_NE_DOUBLE: @@ -1209,6 +1242,8 @@ int exec_insn(struct bytecode_runtime *bytecode, case FILTER_OP_LT_S64: case FILTER_OP_GE_S64: case FILTER_OP_LE_S64: + case FILTER_OP_BIT_RSHIFT: + case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: case FILTER_OP_BIT_OR: case FILTER_OP_BIT_XOR: @@ -1317,6 +1352,31 @@ int exec_insn(struct bytecode_runtime *bytecode, break; } + case FILTER_OP_UNARY_BIT_NOT: + { + /* Pop 1, push 1 */ + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + case REG_S64: + case REG_TYPE_UNKNOWN: + break; + case REG_DOUBLE: + default: + printk(KERN_WARNING "Unexpected register type %d for operation\n", + (int) vstack_ax(stack)->type); + ret = -EINVAL; + goto end; + } + + vstack_ax(stack)->type = REG_S64; + next_pc += sizeof(struct unary_op); + break; + } + /* logical */ case FILTER_OP_AND: case FILTER_OP_OR: diff --git a/lttng-filter.c b/lttng-filter.c index d7fcceae..ff976743 100644 --- a/lttng-filter.c +++ b/lttng-filter.c @@ -40,8 +40,8 @@ static const char *opnames[] = { [ FILTER_OP_MOD ] = "MOD", [ FILTER_OP_PLUS ] = "PLUS", [ FILTER_OP_MINUS ] = "MINUS", - [ FILTER_OP_RSHIFT ] = "RSHIFT", - [ FILTER_OP_LSHIFT ] = "LSHIFT", + [ FILTER_OP_BIT_RSHIFT ] = "BIT_RSHIFT", + [ FILTER_OP_BIT_LSHIFT ] = "BIT_LSHIFT", [ FILTER_OP_BIT_AND ] = "BIT_AND", [ FILTER_OP_BIT_OR ] = "BIT_OR", [ FILTER_OP_BIT_XOR ] = "BIT_XOR", @@ -169,6 +169,8 @@ static const char *opnames[] = { [ FILTER_OP_LOAD_FIELD_STRING ] = "LOAD_FIELD_STRING", [ FILTER_OP_LOAD_FIELD_SEQUENCE ] = "LOAD_FIELD_SEQUENCE", [ FILTER_OP_LOAD_FIELD_DOUBLE ] = "LOAD_FIELD_DOUBLE", + + [ FILTER_OP_UNARY_BIT_NOT ] = "UNARY_BIT_NOT", }; const char *lttng_filter_print_op(enum filter_op op) -- 2.34.1