From: Mathieu Desnoyers Date: Thu, 21 Sep 2017 23:43:10 +0000 (-0400) Subject: Filter: implement bitwise lshift, rshift, not X-Git-Tag: v2.11.0-rc1~11 X-Git-Url: http://git.liburcu.org/?p=lttng-ust.git;a=commitdiff_plain;h=0039e2d8d79c3260d29591fc10a07d57bcc535b3 Filter: implement bitwise lshift, rshift, not Signed-off-by: Mathieu Desnoyers --- diff --git a/liblttng-ust/filter-bytecode.h b/liblttng-ust/filter-bytecode.h index 1db8d14e..f937324d 100644 --- a/liblttng-ust/filter-bytecode.h +++ b/liblttng-ust/filter-bytecode.h @@ -74,8 +74,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, @@ -204,6 +204,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/liblttng-ust/lttng-filter-interpreter.c b/liblttng-ust/lttng-filter-interpreter.c index 5c0cea5a..1e7b12a5 100644 --- a/liblttng-ust/lttng-filter-interpreter.c +++ b/liblttng-ust/lttng-filter-interpreter.c @@ -622,8 +622,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, @@ -740,6 +740,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 */ @@ -778,8 +780,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): ERR("unsupported bytecode op %u", (unsigned int) *(filter_opcode_t *) pc); ret = -EINVAL; @@ -1548,6 +1548,40 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, next_pc += sizeof(struct binary_op); PO; } + OP(FILTER_OP_BIT_RSHIFT): + { + int64_t res; + + /* Dynamic typing. */ + if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) { + ret = -EINVAL; + goto end; + } + + res = (estack_bx_v >> estack_ax_v); + estack_pop(stack, top, ax, bx, ax_t, bx_t); + estack_ax_v = res; + estack_ax_t = REG_S64; + next_pc += sizeof(struct binary_op); + PO; + } + OP(FILTER_OP_BIT_LSHIFT): + { + int64_t res; + + /* Dynamic typing. */ + if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) { + ret = -EINVAL; + goto end; + } + + res = (estack_bx_v << estack_ax_v); + estack_pop(stack, top, ax, bx, ax_t, bx_t); + estack_ax_v = res; + estack_ax_t = REG_S64; + next_pc += sizeof(struct binary_op); + PO; + } OP(FILTER_OP_BIT_AND): { int64_t res; @@ -1661,6 +1695,19 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, PO; } + OP(FILTER_OP_UNARY_BIT_NOT): + { + /* Dynamic typing. */ + if (estack_ax_t != REG_S64) { + ret = -EINVAL; + goto end; + } + + estack_ax_v = ~estack_ax_v; + next_pc += sizeof(struct unary_op); + PO; + } + OP(FILTER_OP_UNARY_PLUS_S64): OP(FILTER_OP_UNARY_PLUS_DOUBLE): { diff --git a/liblttng-ust/lttng-filter-specialize.c b/liblttng-ust/lttng-filter-specialize.c index 7cbd8c59..6de25047 100644 --- a/liblttng-ust/lttng-filter-specialize.c +++ b/liblttng-ust/lttng-filter-specialize.c @@ -630,8 +630,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: ERR("unsupported bytecode op %u\n", (unsigned int) *(filter_opcode_t *) pc); ret = -EINVAL; @@ -959,6 +957,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: @@ -1046,6 +1046,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/liblttng-ust/lttng-filter-validator.c b/liblttng-ust/lttng-filter-validator.c index 6e52065c..4fe8e893 100644 --- a/liblttng-ust/lttng-filter-validator.c +++ b/liblttng-ust/lttng-filter-validator.c @@ -310,8 +310,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: { ERR("unsupported bytecode op %u\n", (unsigned int) *(filter_opcode_t *) pc); @@ -357,6 +355,8 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, 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: @@ -378,6 +378,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode, case FILTER_OP_UNARY_PLUS_DOUBLE: case FILTER_OP_UNARY_MINUS_DOUBLE: case FILTER_OP_UNARY_NOT_DOUBLE: + case FILTER_OP_UNARY_BIT_NOT: { if (unlikely(pc + sizeof(struct unary_op) > start_pc + bytecode->len)) { @@ -587,8 +588,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: { ERR("unsupported bytecode op %u\n", (unsigned int) opcode); @@ -758,6 +757,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) @@ -804,6 +813,32 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, } break; } + case FILTER_OP_UNARY_BIT_NOT: + { + if (!vstack_ax(stack)) { + ERR("Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + default: + ERR("unknown register type\n"); + ret = -EINVAL; + goto end; + + case REG_STRING: + case REG_STAR_GLOB_STRING: + case REG_DOUBLE: + ERR("Unary bitwise op can only be applied to numeric registers\n"); + ret = -EINVAL; + goto end; + case REG_S64: + break; + case REG_UNKNOWN: + break; + } + break; + } case FILTER_OP_UNARY_PLUS_S64: case FILTER_OP_UNARY_MINUS_S64: @@ -1227,8 +1262,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: { ERR("unsupported bytecode op %u\n", (unsigned int) *(filter_opcode_t *) pc); @@ -1274,6 +1307,8 @@ int exec_insn(struct bytecode_runtime *bytecode, 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: @@ -1383,6 +1418,31 @@ int exec_insn(struct bytecode_runtime *bytecode, break; } + case FILTER_OP_UNARY_BIT_NOT: + { + /* Pop 1, push 1 */ + if (!vstack_ax(stack)) { + ERR("Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + case REG_UNKNOWN: + case REG_S64: + break; + case REG_DOUBLE: + default: + ERR("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; + } + case FILTER_OP_UNARY_NOT_DOUBLE: { /* Pop 1, push 1 */ diff --git a/liblttng-ust/lttng-filter.c b/liblttng-ust/lttng-filter.c index 0508349f..b7f058a8 100644 --- a/liblttng-ust/lttng-filter.c +++ b/liblttng-ust/lttng-filter.c @@ -39,8 +39,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", @@ -168,6 +168,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 *print_op(enum filter_op op)