Filter: implement bitwise lshift, rshift, not
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 21 Sep 2017 23:43:10 +0000 (19:43 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 6 Jun 2018 20:40:15 +0000 (16:40 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
liblttng-ust/filter-bytecode.h
liblttng-ust/lttng-filter-interpreter.c
liblttng-ust/lttng-filter-specialize.c
liblttng-ust/lttng-filter-validator.c
liblttng-ust/lttng-filter.c

index 1db8d14e7444ef7487ce9e68942856574f99d968..f937324d1fd853e236807812d3500994da895293 100644 (file)
@@ -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,
 };
 
index 5c0cea5a4d2d99c05513b74f44be72bf04fdb7f9..1e7b12a5da4e0243ed1e00deb9b359b0569bb789 100644 (file)
@@ -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):
                {
index 7cbd8c592c4a782801ceae99b1d7ebd44921ee56..6de25047787d2b09954d1ce88815f53988463cea 100644 (file)
@@ -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:
index 6e52065c2d81b40dcc417cc754b9bdfa7e93f789..4fe8e8938d9ccd889d47a50f8d58910c62fdf68a 100644 (file)
@@ -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 */
index 0508349f39773534e8821b116a66f4c595806005..b7f058a8dac27d680d82786ef9f9337a7b5b6410 100644 (file)
@@ -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)
This page took 0.030569 seconds and 4 git commands to generate.