X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-bytecode-interpreter.c;h=cb128a692adda5de9901429964c2bdf96d535bc8;hb=4e48b5d;hp=46351a25f3ed4e23cd68a6edc7deafa7327794cc;hpb=25cff019d711338b8a7efe1cc54e4b1870157348;p=lttng-ust.git diff --git a/liblttng-ust/lttng-bytecode-interpreter.c b/liblttng-ust/lttng-bytecode-interpreter.c index 46351a25..cb128a69 100644 --- a/liblttng-ust/lttng-bytecode-interpreter.c +++ b/liblttng-ust/lttng-bytecode-interpreter.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include "ust-events-internal.h" @@ -56,7 +57,8 @@ size_t get_str_or_seq_len(const struct estack_entry *entry) } static -int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type) +int stack_star_glob_match(struct estack *stack, int top, + const char *cmp_type __attribute__((unused))) { const char *pattern; const char *candidate; @@ -82,7 +84,7 @@ int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type) } static -int stack_strcmp(struct estack *stack, int top, const char *cmp_type) +int stack_strcmp(struct estack *stack, int top, const char *cmp_type __attribute__((unused))) { const char *p = estack_bx(stack, top)->u.s.str, *q = estack_ax(stack, top)->u.s.str; int ret; @@ -148,17 +150,12 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type) return diff; } -uint64_t lttng_bytecode_filter_interpret_false(void *filter_data, - const char *filter_stack_data) +int lttng_bytecode_interpret_error( + struct lttng_ust_bytecode_runtime *bytecode_runtime __attribute__((unused)), + const char *stack_data __attribute__((unused)), + void *ctx __attribute__((unused))) { - return LTTNG_INTERPRETER_DISCARD; -} - -uint64_t lttng_bytecode_capture_interpret_false(void *capture_data, - const char *capture_stack_data, - struct lttng_interpreter_output *output) -{ - return LTTNG_INTERPRETER_DISCARD; + return LTTNG_UST_BYTECODE_INTERPRETER_ERROR; } #ifdef INTERPRETER_USE_SWITCH @@ -217,24 +214,24 @@ LABEL_##name #define IS_INTEGER_REGISTER(reg_type) \ (reg_type == REG_U64 || reg_type == REG_S64) -static int context_get_index(struct lttng_ctx *ctx, +static int context_get_index(struct lttng_ust_ctx *ctx, struct load_ptr *ptr, uint32_t idx) { - struct lttng_ctx_field *ctx_field; - struct lttng_ust_event_field *field; - struct lttng_ctx_value v; + const struct lttng_ust_ctx_field *ctx_field; + const struct lttng_ust_event_field *field; + struct lttng_ust_ctx_value v; ctx_field = &ctx->fields[idx]; - field = &ctx_field->event_field; + field = ctx_field->event_field; ptr->type = LOAD_OBJECT; ptr->field = field; - switch (field->type.atype) { - case atype_integer: - ctx_field->get_value(ctx_field, &v); - if (field->type.u.integer.signedness) { + switch (field->type->type) { + case lttng_ust_type_integer: + ctx_field->get_value(ctx_field->priv, &v); + if (lttng_ust_get_type_integer(field->type)->signedness) { ptr->object_type = OBJECT_TYPE_S64; ptr->u.s64 = v.u.s64; ptr->ptr = &ptr->u.s64; @@ -244,12 +241,12 @@ static int context_get_index(struct lttng_ctx *ctx, ptr->ptr = &ptr->u.u64; } break; - case atype_enum_nestable: + case lttng_ust_type_enum: { - const struct lttng_integer_type *itype; + const struct lttng_ust_type_integer *itype; - itype = &field->type.u.enum_nestable.container_type->u.integer; - ctx_field->get_value(ctx_field, &v); + itype = lttng_ust_get_type_integer(lttng_ust_get_type_enum(field->type)->container_type); + ctx_field->get_value(ctx_field->priv, &v); if (itype->signedness) { ptr->object_type = OBJECT_TYPE_SIGNED_ENUM; ptr->u.s64 = v.u.s64; @@ -261,45 +258,45 @@ static int context_get_index(struct lttng_ctx *ctx, } break; } - case atype_array_nestable: - if (field->type.u.array_nestable.elem_type->atype != atype_integer) { + case lttng_ust_type_array: + if (lttng_ust_get_type_array(field->type)->elem_type->type != lttng_ust_type_integer) { ERR("Array nesting only supports integer types."); return -EINVAL; } - if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) { + if (lttng_ust_get_type_array(field->type)->encoding == lttng_ust_string_encoding_none) { ERR("Only string arrays are supported for contexts."); return -EINVAL; } ptr->object_type = OBJECT_TYPE_STRING; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); ptr->ptr = v.u.str; break; - case atype_sequence_nestable: - if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) { + case lttng_ust_type_sequence: + if (lttng_ust_get_type_sequence(field->type)->elem_type->type != lttng_ust_type_integer) { ERR("Sequence nesting only supports integer types."); return -EINVAL; } - if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) { + if (lttng_ust_get_type_sequence(field->type)->encoding == lttng_ust_string_encoding_none) { ERR("Only string sequences are supported for contexts."); return -EINVAL; } ptr->object_type = OBJECT_TYPE_STRING; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); ptr->ptr = v.u.str; break; - case atype_string: + case lttng_ust_type_string: ptr->object_type = OBJECT_TYPE_STRING; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); ptr->ptr = v.u.str; break; - case atype_float: + case lttng_ust_type_float: ptr->object_type = OBJECT_TYPE_DOUBLE; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); ptr->u.d = v.u.d; ptr->ptr = &ptr->u.d; break; - case atype_dynamic: - ctx_field->get_value(ctx_field, &v); + case lttng_ust_type_dynamic: + ctx_field->get_value(ctx_field->priv, &v); switch (v.sel) { case LTTNG_UST_DYNAMIC_TYPE_NONE: return -EINVAL; @@ -339,13 +336,13 @@ static int context_get_index(struct lttng_ctx *ctx, } break; default: - ERR("Unknown type: %d", (int) field->type.atype); + ERR("Unknown type: %d", (int) field->type->type); return -EINVAL; } return 0; } -static int dynamic_get_index(struct lttng_ctx *ctx, +static int dynamic_get_index(struct lttng_ust_ctx *ctx, struct bytecode_runtime *runtime, uint64_t index, struct estack_entry *stack_top) { @@ -367,7 +364,7 @@ static int dynamic_get_index(struct lttng_ctx *ctx, 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; - assert(stack_top->u.ptr.field->type.atype == atype_array_nestable); + assert(stack_top->u.ptr.field->type->type == lttng_ust_type_array); stack_top->u.ptr.field = NULL; break; } @@ -386,7 +383,7 @@ static int dynamic_get_index(struct lttng_ctx *ctx, 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; - assert(stack_top->u.ptr.field->type.atype == atype_sequence_nestable); + assert(stack_top->u.ptr.field->type->type == lttng_ust_type_sequence); stack_top->u.ptr.field = NULL; break; } @@ -664,14 +661,14 @@ again: 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; + output->u.sequence.nested_type = lttng_ust_get_type_sequence(ax->u.ptr.field->type)->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; + output->u.sequence.nr_elem = lttng_ust_get_type_array(ax->u.ptr.field->type)->length; + output->u.sequence.nested_type = lttng_ust_get_type_array(ax->u.ptr.field->type)->elem_type; break; case OBJECT_TYPE_SIGNED_ENUM: ret = dynamic_load_field(ax); @@ -700,27 +697,26 @@ again: return -EINVAL; } - return LTTNG_INTERPRETER_RECORD_FLAG; + return 0; } /* - * For `output` equal to NULL: - * Return 0 (discard), or raise the 0x1 flag (log event). - * Currently, other flags are kept for future extensions and have no - * effect. - * For `output` not equal to NULL: - * Return 0 on success, negative error value on error. + * Return LTTNG_UST_BYTECODE_INTERPRETER_OK on success. + * Return LTTNG_UST_BYTECODE_INTERPRETER_ERROR on error. + * + * For FILTER bytecode: expect a struct lttng_ust_bytecode_filter_ctx * + * as @ctx argument. + * For CAPTURE bytecode: expect a struct lttng_interpreter_output * + * as @ctx argument. */ -static -uint64_t bytecode_interpret(void *interpreter_data, +int lttng_bytecode_interpret(struct lttng_ust_bytecode_runtime *ust_bytecode, const char *interpreter_stack_data, - struct lttng_interpreter_output *output) + void *caller_ctx) { - struct bytecode_runtime *bytecode = interpreter_data; - struct lttng_ctx *ctx = lttng_ust_rcu_dereference(*bytecode->p.priv->pctx); + struct bytecode_runtime *bytecode = caa_container_of(ust_bytecode, struct bytecode_runtime, p); + struct lttng_ust_ctx *ctx = lttng_ust_rcu_dereference(*ust_bytecode->pctx); void *pc, *next_pc, *start_pc; - int ret = -EINVAL; - uint64_t retval = 0; + int ret = -EINVAL, retval = 0; struct estack _stack; struct estack *stack = &_stack; register int64_t ax = 0, bx = 0; @@ -876,7 +872,7 @@ uint64_t bytecode_interpret(void *interpreter_data, goto end; OP(BYTECODE_OP_RETURN): - /* LTTNG_INTERPRETER_DISCARD or LTTNG_INTERPRETER_RECORD_FLAG */ + /* LTTNG_UST_BYTECODE_INTERPRETER_ERROR or LTTNG_UST_BYTECODE_INTERPRETER_OK */ /* Handle dynamic typing. */ switch (estack_ax_t) { case REG_S64: @@ -886,7 +882,7 @@ uint64_t bytecode_interpret(void *interpreter_data, case REG_DOUBLE: case REG_STRING: case REG_PTR: - if (!output) { + if (ust_bytecode->type != LTTNG_UST_BYTECODE_TYPE_CAPTURE) { ret = -EINVAL; goto end; } @@ -902,7 +898,7 @@ uint64_t bytecode_interpret(void *interpreter_data, goto end; OP(BYTECODE_OP_RETURN_S64): - /* LTTNG_INTERPRETER_DISCARD or LTTNG_INTERPRETER_RECORD_FLAG */ + /* LTTNG_UST_BYTECODE_INTERPRETER_ERROR or LTTNG_UST_BYTECODE_INTERPRETER_OK */ retval = !!estack_ax_v; ret = 0; goto end; @@ -2104,7 +2100,7 @@ uint64_t bytecode_interpret(void *interpreter_data, JUMP_TO(BYTECODE_OP_CAST_DOUBLE_TO_S64); case REG_U64: estack_ax_t = REG_S64; - next_pc += sizeof(struct cast_op); + next_pc += sizeof(struct cast_op); /* Fall-through */ case REG_STRING: /* Fall-through */ case REG_STAR_GLOB_STRING: ret = -EINVAL; @@ -2136,13 +2132,13 @@ uint64_t bytecode_interpret(void *interpreter_data, { struct load_op *insn = (struct load_op *) pc; struct field_ref *ref = (struct field_ref *) insn->data; - struct lttng_ctx_field *ctx_field; - struct lttng_ctx_value v; + const struct lttng_ust_ctx_field *ctx_field; + struct lttng_ust_ctx_value v; dbg_printf("get context ref offset %u type dynamic\n", ref->offset); ctx_field = &ctx->fields[ref->offset]; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); estack_push(stack, top, ax, bx, ax_t, bx_t); switch (v.sel) { case LTTNG_UST_DYNAMIC_TYPE_NONE: @@ -2184,13 +2180,13 @@ uint64_t bytecode_interpret(void *interpreter_data, { struct load_op *insn = (struct load_op *) pc; struct field_ref *ref = (struct field_ref *) insn->data; - struct lttng_ctx_field *ctx_field; - struct lttng_ctx_value v; + const struct lttng_ust_ctx_field *ctx_field; + struct lttng_ust_ctx_value v; dbg_printf("get context ref offset %u type string\n", ref->offset); ctx_field = &ctx->fields[ref->offset]; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); estack_push(stack, top, ax, bx, ax_t, bx_t); estack_ax(stack, top)->u.s.str = v.u.str; if (unlikely(!estack_ax(stack, top)->u.s.str)) { @@ -2211,13 +2207,13 @@ uint64_t bytecode_interpret(void *interpreter_data, { struct load_op *insn = (struct load_op *) pc; struct field_ref *ref = (struct field_ref *) insn->data; - struct lttng_ctx_field *ctx_field; - struct lttng_ctx_value v; + const struct lttng_ust_ctx_field *ctx_field; + struct lttng_ust_ctx_value v; dbg_printf("get context ref offset %u type s64\n", ref->offset); ctx_field = &ctx->fields[ref->offset]; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); estack_push(stack, top, ax, bx, ax_t, bx_t); estack_ax_v = v.u.s64; estack_ax_t = REG_S64; @@ -2230,13 +2226,13 @@ uint64_t bytecode_interpret(void *interpreter_data, { struct load_op *insn = (struct load_op *) pc; struct field_ref *ref = (struct field_ref *) insn->data; - struct lttng_ctx_field *ctx_field; - struct lttng_ctx_value v; + const struct lttng_ust_ctx_field *ctx_field; + struct lttng_ust_ctx_value v; dbg_printf("get context ref offset %u type double\n", ref->offset); ctx_field = &ctx->fields[ref->offset]; - ctx_field->get_value(ctx_field, &v); + ctx_field->get_value(ctx_field->priv, &v); estack_push(stack, top, ax, bx, ax_t, bx_t); memcpy(&estack_ax(stack, top)->u.d, &v.u.d, sizeof(struct literal_double)); estack_ax_t = REG_DOUBLE; @@ -2482,30 +2478,61 @@ uint64_t bytecode_interpret(void *interpreter_data, END_OP end: - /* Return _DISCARD on error. */ + /* No need to prepare output if an error occurred. */ if (ret) - return LTTNG_INTERPRETER_DISCARD; + return LTTNG_UST_BYTECODE_INTERPRETER_ERROR; - if (output) { - return lttng_bytecode_interpret_format_output(estack_ax(stack, top), - output); + /* Prepare output. */ + switch (ust_bytecode->type) { + case LTTNG_UST_BYTECODE_TYPE_FILTER: + { + struct lttng_ust_bytecode_filter_ctx *filter_ctx = + (struct lttng_ust_bytecode_filter_ctx *) caller_ctx; + if (retval) + filter_ctx->result = LTTNG_UST_BYTECODE_FILTER_ACCEPT; + else + filter_ctx->result = LTTNG_UST_BYTECODE_FILTER_REJECT; + break; } - - return retval; -} - -uint64_t lttng_bytecode_filter_interpret(void *filter_data, - const char *filter_stack_data) -{ - return bytecode_interpret(filter_data, filter_stack_data, NULL); + case LTTNG_UST_BYTECODE_TYPE_CAPTURE: + ret = lttng_bytecode_interpret_format_output(estack_ax(stack, top), + (struct lttng_interpreter_output *) caller_ctx); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + return LTTNG_UST_BYTECODE_INTERPRETER_ERROR; + else + return LTTNG_UST_BYTECODE_INTERPRETER_OK; } -uint64_t lttng_bytecode_capture_interpret(void *capture_data, - const char *capture_stack_data, - struct lttng_interpreter_output *output) +/* + * Return LTTNG_UST_EVENT_FILTER_ACCEPT or LTTNG_UST_EVENT_FILTER_REJECT. + */ +int lttng_ust_interpret_event_filter(struct lttng_ust_event_common *event, + const char *interpreter_stack_data, + void *event_filter_ctx __attribute__((unused))) { - return bytecode_interpret(capture_data, capture_stack_data, - (struct lttng_interpreter_output *) output); + struct lttng_ust_bytecode_runtime *filter_bc_runtime; + struct cds_list_head *filter_bytecode_runtime_head = &event->priv->filter_bytecode_runtime_head; + struct lttng_ust_bytecode_filter_ctx bytecode_filter_ctx; + bool filter_record = false; + + cds_list_for_each_entry_rcu(filter_bc_runtime, filter_bytecode_runtime_head, node) { + if (caa_likely(filter_bc_runtime->interpreter_func(filter_bc_runtime, + interpreter_stack_data, &bytecode_filter_ctx) == LTTNG_UST_BYTECODE_INTERPRETER_OK)) { + if (caa_unlikely(bytecode_filter_ctx.result == LTTNG_UST_BYTECODE_FILTER_ACCEPT)) { + filter_record = true; + break; + } + } + } + if (filter_record) + return LTTNG_UST_EVENT_FILTER_ACCEPT; + else + return LTTNG_UST_EVENT_FILTER_REJECT; } #undef START_OP