X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;ds=sidebyside;f=liblttng-ust%2Flttng-filter-interpreter.c;h=d00179cdd7ff234de83390267a3e9a3de2767fd2;hb=6bbd9df3c4006bb904c9efc5620d2c29ac2178fb;hp=5c0cea5a4d2d99c05513b74f44be72bf04fdb7f9;hpb=47e5f13e885764eecde371627001d26da2a2f41f;p=lttng-ust.git diff --git a/liblttng-ust/lttng-filter-interpreter.c b/liblttng-ust/lttng-filter-interpreter.c index 5c0cea5a..d00179cd 100644 --- a/liblttng-ust/lttng-filter-interpreter.c +++ b/liblttng-ust/lttng-filter-interpreter.c @@ -25,12 +25,18 @@ */ #define _LGPL_SOURCE -#include +#include #include +#include #include + +#include +#include + #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.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) { + 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_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; @@ -622,8 +731,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 +849,10 @@ 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, + + [ FILTER_OP_RETURN_S64 ] = &&LABEL_FILTER_OP_RETURN_S64, }; #endif /* #ifndef INTERPRETER_USE_SWITCH */ @@ -756,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; @@ -772,14 +894,18 @@ 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): 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; @@ -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; @@ -1548,20 +1700,61 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, next_pc += sizeof(struct binary_op); PO; } + OP(FILTER_OP_BIT_RSHIFT): + { + int64_t res; + + if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) { + ret = -EINVAL; + goto end; + } + + /* 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_U64; + next_pc += sizeof(struct binary_op); + PO; + } + OP(FILTER_OP_BIT_LSHIFT): + { + int64_t res; + + if (!IS_INTEGER_REGISTER(estack_ax_t) || !IS_INTEGER_REGISTER(estack_bx_t)) { + ret = -EINVAL; + goto end; + } + + /* 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_U64; + next_pc += sizeof(struct binary_op); + PO; + } OP(FILTER_OP_BIT_AND): { 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; } @@ -1569,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; } @@ -1586,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; } @@ -1606,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); @@ -1624,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); @@ -1643,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); @@ -1661,6 +1855,20 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, PO; } + OP(FILTER_OP_UNARY_BIT_NOT): + { + /* Dynamic typing. */ + if (!IS_INTEGER_REGISTER(estack_ax_t)) { + ret = -EINVAL; + goto end; + } + + estack_ax_v = ~(uint64_t) estack_ax_v; + estack_ax_t = REG_U64; + next_pc += sizeof(struct unary_op); + PO; + } + OP(FILTER_OP_UNARY_PLUS_S64): OP(FILTER_OP_UNARY_PLUS_DOUBLE): { @@ -1682,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; } @@ -1698,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; } @@ -1718,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; } @@ -1747,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; @@ -1771,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)) { @@ -1796,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); @@ -1811,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); @@ -1886,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; @@ -1917,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); @@ -1967,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); @@ -1996,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); @@ -2017,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); @@ -2063,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; @@ -2109,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; @@ -2124,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; @@ -2186,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; } @@ -2195,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; } @@ -2204,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; } @@ -2213,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; } @@ -2271,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