bytecode: propagate `rev_bo` of element
[deliverable/lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
index 1e7b12a5da4e0243ed1e00deb9b359b0569bb789..d00179cdd7ff234de83390267a3e9a3de2767fd2 100644 (file)
  */
 
 #define _LGPL_SOURCE
-#include <urcu-pointer.h>
+#include <stddef.h>
 #include <stdint.h>
+#include <urcu-pointer.h>
 #include <byteswap.h>
+
+#include <lttng/ust-endian.h>
+#include <lttng/ust-events.h>
+
 #include "lttng-filter.h"
 #include "string-utils.h"
 
+
 /*
  * -1: wildcard found.
  * -2: unknown escape char.
@@ -160,10 +166,10 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
        return diff;
 }
 
-uint64_t lttng_filter_false(void *filter_data,
+uint64_t lttng_filter_interpret_bytecode_false(void *filter_data,
                const char *filter_stack_data)
 {
-       return 0;
+       return LTTNG_FILTER_DISCARD;
 }
 
 #ifdef INTERPRETER_USE_SWITCH
@@ -219,6 +225,9 @@ LABEL_##name
 
 #endif
 
+#define IS_INTEGER_REGISTER(reg_type) \
+               (reg_type == REG_U64 || reg_type == REG_S64)
+
 static int context_get_index(struct lttng_ctx *ctx,
                struct load_ptr *ptr,
                uint32_t idx)
@@ -231,13 +240,12 @@ static int context_get_index(struct lttng_ctx *ctx,
        ctx_field = &ctx->fields[idx];
        field = &ctx_field->event_field;
        ptr->type = LOAD_OBJECT;
-       /* field is only used for types nested within variants. */
-       ptr->field = NULL;
+       ptr->field = field;
 
        switch (field->type.atype) {
        case atype_integer:
                ctx_field->get_value(ctx_field, &v);
-               if (field->type.u.basic.integer.signedness) {
+               if (field->type.u.integer.signedness) {
                        ptr->object_type = OBJECT_TYPE_S64;
                        ptr->u.s64 = v.u.s64;
                        ptr->ptr = &ptr->u.s64;
@@ -247,11 +255,16 @@ static int context_get_index(struct lttng_ctx *ctx,
                        ptr->ptr = &ptr->u.u64;
                }
                break;
-       case atype_enum:
+       case atype_enum:        /* Fall-through */
+       case atype_enum_nestable:
        {
-               const struct lttng_integer_type *itype =
-                       &field->type.u.basic.enumeration.container_type;
+               const struct lttng_integer_type *itype;
 
+               if (field->type.atype == atype_enum) {
+                       itype = &field->type.u.legacy.basic.enumeration.container_type;
+               } else {
+                       itype = &field->type.u.enum_nestable.container_type->u.integer;
+               }
                ctx_field->get_value(ctx_field, &v);
                if (itype->signedness) {
                        ptr->object_type = OBJECT_TYPE_S64;
@@ -265,11 +278,24 @@ static int context_get_index(struct lttng_ctx *ctx,
                break;
        }
        case atype_array:
-               if (field->type.u.array.elem_type.atype != atype_integer) {
+               if (field->type.u.legacy.array.elem_type.atype != atype_integer) {
                        ERR("Array nesting only supports integer types.");
                        return -EINVAL;
                }
-               if (field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
+               if (field->type.u.legacy.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
+                       ERR("Only string arrays are supported for contexts.");
+                       return -EINVAL;
+               }
+               ptr->object_type = OBJECT_TYPE_STRING;
+               ctx_field->get_value(ctx_field, &v);
+               ptr->ptr = v.u.str;
+               break;
+       case atype_array_nestable:
+               if (field->type.u.array_nestable.elem_type->atype != atype_integer) {
+                       ERR("Array nesting only supports integer types.");
+                       return -EINVAL;
+               }
+               if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
                        ERR("Only string arrays are supported for contexts.");
                        return -EINVAL;
                }
@@ -278,11 +304,24 @@ static int context_get_index(struct lttng_ctx *ctx,
                ptr->ptr = v.u.str;
                break;
        case atype_sequence:
-               if (field->type.u.sequence.elem_type.atype != atype_integer) {
+               if (field->type.u.legacy.sequence.elem_type.atype != atype_integer) {
+                       ERR("Sequence nesting only supports integer types.");
+                       return -EINVAL;
+               }
+               if (field->type.u.legacy.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
+                       ERR("Only string sequences are supported for contexts.");
+                       return -EINVAL;
+               }
+               ptr->object_type = OBJECT_TYPE_STRING;
+               ctx_field->get_value(ctx_field, &v);
+               ptr->ptr = v.u.str;
+               break;
+       case atype_sequence_nestable:
+               if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) {
                        ERR("Sequence nesting only supports integer types.");
                        return -EINVAL;
                }
-               if (field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
+               if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
                        ERR("Only string sequences are supported for contexts.");
                        return -EINVAL;
                }
@@ -297,6 +336,7 @@ static int context_get_index(struct lttng_ctx *ctx,
                break;
        case atype_float:
                ptr->object_type = OBJECT_TYPE_DOUBLE;
+               ctx_field->get_value(ctx_field, &v);
                ptr->u.d = v.u.d;
                ptr->ptr = &ptr->u.d;
                break;
@@ -337,20 +377,13 @@ static int context_get_index(struct lttng_ctx *ctx,
        return 0;
 }
 
-static int dynamic_get_index(struct lttng_session *session,
+static int dynamic_get_index(struct lttng_ctx *ctx,
                struct bytecode_runtime *runtime,
                uint64_t index, struct estack_entry *stack_top)
 {
        int ret;
        const struct filter_get_index_data *gid;
 
-       /*
-        * Types nested within variants need to perform dynamic lookup
-        * based on the field descriptions. LTTng-UST does not implement
-        * variants for now.
-        */
-       if (stack_top->u.ptr.field)
-               return -EINVAL;
        gid = (const struct filter_get_index_data *) &runtime->data[index];
        switch (stack_top->u.ptr.type) {
        case LOAD_OBJECT:
@@ -366,7 +399,8 @@ static int dynamic_get_index(struct lttng_session *session,
                        stack_top->u.ptr.ptr = ptr;
                        stack_top->u.ptr.object_type = gid->elem.type;
                        stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
-                       /* field is only used for types nested within variants. */
+                       assert(stack_top->u.ptr.field->type.atype == atype_array ||
+                                       stack_top->u.ptr.field->type.atype == atype_array_nestable);
                        stack_top->u.ptr.field = NULL;
                        break;
                }
@@ -385,7 +419,8 @@ static int dynamic_get_index(struct lttng_session *session,
                        stack_top->u.ptr.ptr = ptr;
                        stack_top->u.ptr.object_type = gid->elem.type;
                        stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
-                       /* field is only used for types nested within variants. */
+                       assert(stack_top->u.ptr.field->type.atype == atype_sequence ||
+                                       stack_top->u.ptr.field->type.atype == atype_sequence_nestable);
                        stack_top->u.ptr.field = NULL;
                        break;
                }
@@ -404,9 +439,6 @@ static int dynamic_get_index(struct lttng_session *session,
        case LOAD_ROOT_CONTEXT:
        case LOAD_ROOT_APP_CONTEXT:     /* Fall-through */
        {
-               struct lttng_ctx *ctx;
-
-               ctx = rcu_dereference(session->ctx);
                ret = context_get_index(ctx,
                                &stack_top->u.ptr,
                                gid->ctx_index);
@@ -421,10 +453,13 @@ static int dynamic_get_index(struct lttng_session *session,
                        stack_top->u.ptr.ptr = *(const char * const *) stack_top->u.ptr.ptr;
                stack_top->u.ptr.object_type = gid->elem.type;
                stack_top->u.ptr.type = LOAD_OBJECT;
-               /* field is only used for types nested within variants. */
-               stack_top->u.ptr.field = NULL;
+               stack_top->u.ptr.field = gid->field;
+               stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
                break;
        }
+
+       stack_top->type = REG_PTR;
+
        return 0;
 
 end:
@@ -491,18 +526,18 @@ static int dynamic_load_field(struct estack_entry *stack_top)
        case OBJECT_TYPE_U8:
                dbg_printf("op load field u8\n");
                stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr;
-               stack_top->type = REG_S64;
+               stack_top->type = REG_U64;
                break;
        case OBJECT_TYPE_U16:
        {
                uint16_t tmp;
 
-               dbg_printf("op load field s16\n");
+               dbg_printf("op load field u16\n");
                tmp = *(uint16_t *) stack_top->u.ptr.ptr;
                if (stack_top->u.ptr.rev_bo)
                        tmp = bswap_16(tmp);
                stack_top->u.v = tmp;
-               stack_top->type = REG_S64;
+               stack_top->type = REG_U64;
                break;
        }
        case OBJECT_TYPE_U32:
@@ -514,7 +549,7 @@ static int dynamic_load_field(struct estack_entry *stack_top)
                if (stack_top->u.ptr.rev_bo)
                        tmp = bswap_32(tmp);
                stack_top->u.v = tmp;
-               stack_top->type = REG_S64;
+               stack_top->type = REG_U64;
                break;
        }
        case OBJECT_TYPE_U64:
@@ -526,7 +561,7 @@ static int dynamic_load_field(struct estack_entry *stack_top)
                if (stack_top->u.ptr.rev_bo)
                        tmp = bswap_64(tmp);
                stack_top->u.v = tmp;
-               stack_top->type = REG_S64;
+               stack_top->type = REG_U64;
                break;
        }
        case OBJECT_TYPE_DOUBLE:
@@ -592,16 +627,90 @@ end:
        return ret;
 }
 
+static
+int lttng_bytecode_interpret_format_output(struct estack_entry *ax,
+               struct lttng_interpreter_output *output)
+{
+       int ret;
+
+again:
+       switch (ax->type) {
+       case REG_S64:
+               output->type = LTTNG_INTERPRETER_TYPE_S64;
+               output->u.s = ax->u.v;
+               break;
+       case REG_U64:
+               output->type = LTTNG_INTERPRETER_TYPE_U64;
+               output->u.u = (uint64_t) ax->u.v;
+               break;
+       case REG_DOUBLE:
+               output->type = LTTNG_INTERPRETER_TYPE_DOUBLE;
+               output->u.d = ax->u.d;
+               break;
+       case REG_STRING:
+               output->type = LTTNG_INTERPRETER_TYPE_STRING;
+               output->u.str.str = ax->u.s.str;
+               output->u.str.len = ax->u.s.seq_len;
+               break;
+       case REG_PTR:
+               switch (ax->u.ptr.object_type) {
+               case OBJECT_TYPE_S8:
+               case OBJECT_TYPE_S16:
+               case OBJECT_TYPE_S32:
+               case OBJECT_TYPE_S64:
+               case OBJECT_TYPE_U8:
+               case OBJECT_TYPE_U16:
+               case OBJECT_TYPE_U32:
+               case OBJECT_TYPE_U64:
+               case OBJECT_TYPE_DOUBLE:
+               case OBJECT_TYPE_STRING:
+               case OBJECT_TYPE_STRING_SEQUENCE:
+                       ret = dynamic_load_field(ax);
+                       if (ret)
+                               return ret;
+                       /* Retry after loading ptr into stack top. */
+                       goto again;
+               case OBJECT_TYPE_SEQUENCE:
+                       output->type = LTTNG_INTERPRETER_TYPE_SEQUENCE;
+                       output->u.sequence.ptr = *(const char **) (ax->u.ptr.ptr + sizeof(unsigned long));
+                       output->u.sequence.nr_elem = *(unsigned long *) ax->u.ptr.ptr;
+                       output->u.sequence.nested_type = ax->u.ptr.field->type.u.sequence_nestable.elem_type;
+                       break;
+               case OBJECT_TYPE_ARRAY:
+                       /* Skip count (unsigned long) */
+                       output->type = LTTNG_INTERPRETER_TYPE_SEQUENCE;
+                       output->u.sequence.ptr = *(const char **) (ax->u.ptr.ptr + sizeof(unsigned long));
+                       output->u.sequence.nr_elem = ax->u.ptr.field->type.u.array_nestable.length;
+                       output->u.sequence.nested_type = ax->u.ptr.field->type.u.array_nestable.elem_type;
+                       break;
+               case OBJECT_TYPE_STRUCT:
+               case OBJECT_TYPE_VARIANT:
+               default:
+                       return -EINVAL;
+               }
+
+               break;
+       case REG_STAR_GLOB_STRING:
+       case REG_UNKNOWN:
+       default:
+               return -EINVAL;
+       }
+
+       return LTTNG_FILTER_RECORD_FLAG;
+}
+
 /*
  * Return 0 (discard), or raise the 0x1 flag (log event).
  * Currently, other flags are kept for future extensions and have no
  * effect.
  */
-uint64_t lttng_filter_interpret_bytecode(void *filter_data,
-               const char *filter_stack_data)
+static
+uint64_t bytecode_interpret(void *interpreter_data,
+               const char *interpreter_stack_data,
+               struct lttng_interpreter_output *output)
 {
-       struct bytecode_runtime *bytecode = filter_data;
-       struct lttng_session *session = bytecode->p.session;
+       struct bytecode_runtime *bytecode = interpreter_data;
+       struct lttng_ctx *ctx = rcu_dereference(*bytecode->p.pctx);
        void *pc, *next_pc, *start_pc;
        int ret = -EINVAL;
        uint64_t retval = 0;
@@ -742,6 +851,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                [ FILTER_OP_LOAD_FIELD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_DOUBLE,
 
                [ FILTER_OP_UNARY_BIT_NOT ] = &&LABEL_FILTER_OP_UNARY_BIT_NOT,
+
+               [ FILTER_OP_RETURN_S64 ] = &&LABEL_FILTER_OP_RETURN_S64,
        };
 #endif /* #ifndef INTERPRETER_USE_SWITCH */
 
@@ -758,15 +869,24 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        goto end;
 
                OP(FILTER_OP_RETURN):
-                       /* LTTNG_FILTER_DISCARD  or LTTNG_FILTER_RECORD_FLAG */
+                       /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
                        /* Handle dynamic typing. */
                        switch (estack_ax_t) {
                        case REG_S64:
+                       case REG_U64:
                                retval = !!estack_ax_v;
                                break;
                        case REG_DOUBLE:
                        case REG_STRING:
+                       case REG_PTR:
+                               if (!output) {
+                                       ret = -EINVAL;
+                                       goto end;
+                               }
+                               retval = 0;
+                               break;
                        case REG_STAR_GLOB_STRING:
+                       case REG_UNKNOWN:
                        default:
                                ret = -EINVAL;
                                goto end;
@@ -774,6 +894,12 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        ret = 0;
                        goto end;
 
+               OP(FILTER_OP_RETURN_S64):
+                       /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
+                       retval = !!estack_ax_v;
+                       ret = 0;
+                       goto end;
+
                /* binary */
                OP(FILTER_OP_MUL):
                OP(FILTER_OP_DIV):
@@ -789,9 +915,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_EQ_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_EQ_DOUBLE_S64);
@@ -808,7 +936,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_EQ_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_EQ_DOUBLE);
@@ -826,6 +955,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE:
                                        ret = -EINVAL;
                                        goto end;
@@ -843,6 +973,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STAR_GLOB_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE:
                                        ret = -EINVAL;
                                        goto end;
@@ -869,9 +1000,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_NE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_NE_DOUBLE_S64);
@@ -888,7 +1021,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_NE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_NE_DOUBLE);
@@ -906,6 +1040,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                case REG_DOUBLE:
                                        ret = -EINVAL;
                                        goto end;
@@ -923,6 +1058,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STAR_GLOB_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                case REG_DOUBLE:
                                        ret = -EINVAL;
                                        goto end;
@@ -949,9 +1085,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_GT_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GT_DOUBLE_S64);
@@ -968,7 +1106,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_GT_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GT_DOUBLE);
@@ -986,6 +1125,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE: /* Fall-through */
                                case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
@@ -1010,9 +1150,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_LT_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LT_DOUBLE_S64);
@@ -1029,7 +1171,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_LT_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LT_DOUBLE);
@@ -1047,6 +1190,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE: /* Fall-through */
                                case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
@@ -1071,9 +1215,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_GE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GE_DOUBLE_S64);
@@ -1090,7 +1236,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_GE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GE_DOUBLE);
@@ -1108,6 +1255,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE: /* Fall-through */
                                case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
@@ -1132,9 +1280,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through */
+                       case REG_U64:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_LE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LE_DOUBLE_S64);
@@ -1151,7 +1301,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                break;
                        case REG_DOUBLE:
                                switch (estack_bx_t) {
-                               case REG_S64:
+                               case REG_S64:   /* Fall-through */
+                               case REG_U64:
                                        JUMP_TO(FILTER_OP_LE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LE_DOUBLE);
@@ -1169,6 +1320,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
+                               case REG_U64:   /* Fall-through */
                                case REG_DOUBLE: /* Fall-through */
                                case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
@@ -1552,16 +1704,20 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        int64_t res;
 
-                       /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       res = (estack_bx_v >> estack_ax_v);
+                       /* Catch undefined behavior. */
+                       if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
+                               ret = -EINVAL;
+                               goto end;
+                       }
+                       res = ((uint64_t) estack_bx_v >> (uint32_t) estack_ax_v);
                        estack_pop(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v = res;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct binary_op);
                        PO;
                }
@@ -1569,16 +1725,20 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        int64_t res;
 
-                       /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       res = (estack_bx_v << estack_ax_v);
+                       /* Catch undefined behavior. */
+                       if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
+                               ret = -EINVAL;
+                               goto end;
+                       }
+                       res = ((uint64_t) estack_bx_v << (uint32_t) estack_ax_v);
                        estack_pop(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v = res;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct binary_op);
                        PO;
                }
@@ -1586,16 +1746,15 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        int64_t res;
 
-                       /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       res = (estack_bx_v & estack_ax_v);
+                       res = ((uint64_t) estack_bx_v & (uint64_t) estack_ax_v);
                        estack_pop(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v = res;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct binary_op);
                        PO;
                }
@@ -1603,16 +1762,15 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        int64_t res;
 
-                       /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       res = (estack_bx_v | estack_ax_v);
+                       res = ((uint64_t) estack_bx_v | (uint64_t) estack_ax_v);
                        estack_pop(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v = res;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct binary_op);
                        PO;
                }
@@ -1620,16 +1778,15 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        int64_t res;
 
-                       /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       res = (estack_bx_v ^ estack_ax_v);
+                       res = ((uint64_t) estack_bx_v ^ (uint64_t) estack_ax_v);
                        estack_pop(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v = res;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct binary_op);
                        PO;
                }
@@ -1640,6 +1797,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
                        case REG_S64:   /* Fall-through. */
+                       case REG_U64:
                                JUMP_TO(FILTER_OP_UNARY_PLUS_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE);
@@ -1658,7 +1816,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through. */
+                       case REG_U64:
                                JUMP_TO(FILTER_OP_UNARY_MINUS_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE);
@@ -1677,7 +1836,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        /* Dynamic typing. */
                        switch (estack_ax_t) {
-                       case REG_S64:
+                       case REG_S64:   /* Fall-through. */
+                       case REG_U64:
                                JUMP_TO(FILTER_OP_UNARY_NOT_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE);
@@ -1698,12 +1858,13 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                OP(FILTER_OP_UNARY_BIT_NOT):
                {
                        /* Dynamic typing. */
-                       if (estack_ax_t != REG_S64) {
+                       if (!IS_INTEGER_REGISTER(estack_ax_t)) {
                                ret = -EINVAL;
                                goto end;
                        }
 
-                       estack_ax_v = ~estack_ax_v;
+                       estack_ax_v = ~(uint64_t) estack_ax_v;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct unary_op);
                        PO;
                }
@@ -1729,6 +1890,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                OP(FILTER_OP_UNARY_NOT_S64):
                {
                        estack_ax_v = !estack_ax_v;
+                       estack_ax_t = REG_S64;
                        next_pc += sizeof(struct unary_op);
                        PO;
                }
@@ -1745,7 +1907,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct logical_op *insn = (struct logical_op *) pc;
 
-                       if (estack_ax_t != REG_S64) {
+                       if (estack_ax_t != REG_S64 && estack_ax_t != REG_U64) {
                                ret = -EINVAL;
                                goto end;
                        }
@@ -1765,7 +1927,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct logical_op *insn = (struct logical_op *) pc;
 
-                       if (estack_ax_t != REG_S64) {
+                       if (estack_ax_t != REG_S64 && estack_ax_t != REG_U64) {
                                ret = -EINVAL;
                                goto end;
                        }
@@ -1794,7 +1956,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ref->offset);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax(stack, top)->u.s.str =
-                               *(const char * const *) &filter_stack_data[ref->offset];
+                               *(const char * const *) &interpreter_stack_data[ref->offset];
                        if (unlikely(!estack_ax(stack, top)->u.s.str)) {
                                dbg_printf("Filter warning: loading a NULL string.\n");
                                ret = -EINVAL;
@@ -1818,9 +1980,9 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ref->offset);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax(stack, top)->u.s.seq_len =
-                               *(unsigned long *) &filter_stack_data[ref->offset];
+                               *(unsigned long *) &interpreter_stack_data[ref->offset];
                        estack_ax(stack, top)->u.s.str =
-                               *(const char **) (&filter_stack_data[ref->offset
+                               *(const char **) (&interpreter_stack_data[ref->offset
                                                                + sizeof(unsigned long)]);
                        estack_ax_t = REG_STRING;
                        if (unlikely(!estack_ax(stack, top)->u.s.str)) {
@@ -1843,7 +2005,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ref->offset);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax_v =
-                               ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
+                               ((struct literal_numeric *) &interpreter_stack_data[ref->offset])->v;
                        estack_ax_t = REG_S64;
                        dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
@@ -1858,7 +2020,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("load field ref offset %u type double\n",
                                ref->offset);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
-                       memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
+                       memcpy(&estack_ax(stack, top)->u.d, &interpreter_stack_data[ref->offset],
                                sizeof(struct literal_double));
                        estack_ax_t = REG_DOUBLE;
                        dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
@@ -1933,6 +2095,9 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                JUMP_TO(FILTER_OP_CAST_NOP);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64);
+                       case REG_U64:
+                               estack_ax_t = REG_S64;
+                               next_pc += sizeof(struct cast_op);
                        case REG_STRING: /* Fall-through */
                        case REG_STAR_GLOB_STRING:
                                ret = -EINVAL;
@@ -1964,13 +2129,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct load_op *insn = (struct load_op *) pc;
                        struct field_ref *ref = (struct field_ref *) insn->data;
-                       struct lttng_ctx *ctx;
                        struct lttng_ctx_field *ctx_field;
                        struct lttng_ctx_value v;
 
                        dbg_printf("get context ref offset %u type dynamic\n",
                                ref->offset);
-                       ctx = rcu_dereference(session->ctx);
                        ctx_field = &ctx->fields[ref->offset];
                        ctx_field->get_value(ctx_field, &v);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
@@ -2014,13 +2177,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct load_op *insn = (struct load_op *) pc;
                        struct field_ref *ref = (struct field_ref *) insn->data;
-                       struct lttng_ctx *ctx;
                        struct lttng_ctx_field *ctx_field;
                        struct lttng_ctx_value v;
 
                        dbg_printf("get context ref offset %u type string\n",
                                ref->offset);
-                       ctx = rcu_dereference(session->ctx);
                        ctx_field = &ctx->fields[ref->offset];
                        ctx_field->get_value(ctx_field, &v);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
@@ -2043,13 +2204,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct load_op *insn = (struct load_op *) pc;
                        struct field_ref *ref = (struct field_ref *) insn->data;
-                       struct lttng_ctx *ctx;
                        struct lttng_ctx_field *ctx_field;
                        struct lttng_ctx_value v;
 
                        dbg_printf("get context ref offset %u type s64\n",
                                ref->offset);
-                       ctx = rcu_dereference(session->ctx);
                        ctx_field = &ctx->fields[ref->offset];
                        ctx_field->get_value(ctx_field, &v);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
@@ -2064,13 +2223,11 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                {
                        struct load_op *insn = (struct load_op *) pc;
                        struct field_ref *ref = (struct field_ref *) insn->data;
-                       struct lttng_ctx *ctx;
                        struct lttng_ctx_field *ctx_field;
                        struct lttng_ctx_value v;
 
                        dbg_printf("get context ref offset %u type double\n",
                                ref->offset);
-                       ctx = rcu_dereference(session->ctx);
                        ctx_field = &ctx->fields[ref->offset];
                        ctx_field->get_value(ctx_field, &v);
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
@@ -2110,7 +2267,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("op get app payload root\n");
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_PAYLOAD;
-                       estack_ax(stack, top)->u.ptr.ptr = filter_stack_data;
+                       estack_ax(stack, top)->u.ptr.ptr = interpreter_stack_data;
                        /* "field" only needed for variants. */
                        estack_ax(stack, top)->u.ptr.field = NULL;
                        estack_ax_t = REG_PTR;
@@ -2156,7 +2313,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        struct get_index_u16 *index = (struct get_index_u16 *) insn->data;
 
                        dbg_printf("op get index u16\n");
-                       ret = dynamic_get_index(session, bytecode, index->index, estack_ax(stack, top));
+                       ret = dynamic_get_index(ctx, bytecode, index->index, estack_ax(stack, top));
                        if (ret)
                                goto end;
                        estack_ax_v = estack_ax(stack, top)->u.v;
@@ -2171,7 +2328,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        struct get_index_u64 *index = (struct get_index_u64 *) insn->data;
 
                        dbg_printf("op get index u64\n");
-                       ret = dynamic_get_index(session, bytecode, index->index, estack_ax(stack, top));
+                       ret = dynamic_get_index(ctx, bytecode, index->index, estack_ax(stack, top));
                        if (ret)
                                goto end;
                        estack_ax_v = estack_ax(stack, top)->u.v;
@@ -2233,7 +2390,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("op load field u8\n");
 
                        estack_ax_v = *(uint8_t *) estack_ax(stack, top)->u.ptr.ptr;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct load_op);
                        PO;
                }
@@ -2242,7 +2399,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("op load field u16\n");
 
                        estack_ax_v = *(uint16_t *) estack_ax(stack, top)->u.ptr.ptr;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct load_op);
                        PO;
                }
@@ -2251,7 +2408,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("op load field u32\n");
 
                        estack_ax_v = *(uint32_t *) estack_ax(stack, top)->u.ptr.ptr;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct load_op);
                        PO;
                }
@@ -2260,7 +2417,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        dbg_printf("op load field u64\n");
 
                        estack_ax_v = *(uint64_t *) estack_ax(stack, top)->u.ptr.ptr;
-                       estack_ax_t = REG_S64;
+                       estack_ax_t = REG_U64;
                        next_pc += sizeof(struct load_op);
                        PO;
                }
@@ -2318,12 +2475,24 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
 
        END_OP
 end:
-       /* return 0 (discard) on error */
+       /* Return _DISCARD on error. */
        if (ret)
-               return 0;
+               return LTTNG_FILTER_DISCARD;
+
+       if (output) {
+               return lttng_bytecode_interpret_format_output(estack_ax(stack, top),
+                               output);
+       }
+
        return retval;
 }
 
+uint64_t lttng_filter_interpret_bytecode(void *filter_data,
+               const char *filter_stack_data)
+{
+       return bytecode_interpret(filter_data, filter_stack_data, NULL);
+}
+
 #undef START_OP
 #undef OP
 #undef PO
This page took 0.050816 seconds and 5 git commands to generate.