X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-filter-specialize.c;h=947fde29288c222b6f6f384d208907c1c4a8daa4;hb=9fe043d73a3e2112f859ce1fa489021a96efecc9;hp=6de25047787d2b09954d1ce88815f53988463cea;hpb=0039e2d8d79c3260d29591fc10a07d57bcc535b3;p=lttng-ust.git diff --git a/liblttng-ust/lttng-filter-specialize.c b/liblttng-ust/lttng-filter-specialize.c index 6de25047..947fde29 100644 --- a/liblttng-ust/lttng-filter-specialize.c +++ b/liblttng-ust/lttng-filter-specialize.c @@ -25,8 +25,12 @@ */ #define _LGPL_SOURCE +#include +#include + #include "lttng-filter.h" #include +#include "ust-events-internal.h" static int lttng_fls(int val) { @@ -71,7 +75,7 @@ static ssize_t bytecode_reserve_data(struct bytecode_runtime *runtime, size_t align, size_t len) { ssize_t ret; - size_t padding = offset_align(runtime->data_len, align); + size_t padding = lttng_ust_offset_align(runtime->data_len, align); size_t new_len = runtime->data_len + padding + len; size_t new_alloc_len = new_len; size_t old_alloc_len = runtime->data_alloc_len; @@ -153,24 +157,24 @@ static int specialize_load_field(struct vstack_entry *stack_top, break; case OBJECT_TYPE_U8: dbg_printf("op load field u8\n"); - stack_top->type = REG_S64; + stack_top->type = REG_U64; insn->op = FILTER_OP_LOAD_FIELD_U8; break; case OBJECT_TYPE_U16: dbg_printf("op load field u16\n"); - stack_top->type = REG_S64; + stack_top->type = REG_U64; if (!stack_top->load.rev_bo) insn->op = FILTER_OP_LOAD_FIELD_U16; break; case OBJECT_TYPE_U32: dbg_printf("op load field u32\n"); - stack_top->type = REG_S64; + stack_top->type = REG_U64; if (!stack_top->load.rev_bo) insn->op = FILTER_OP_LOAD_FIELD_U32; break; case OBJECT_TYPE_U64: dbg_printf("op load field u64\n"); - stack_top->type = REG_S64; + stack_top->type = REG_U64; if (!stack_top->load.rev_bo) insn->op = FILTER_OP_LOAD_FIELD_U64; break; @@ -256,14 +260,31 @@ static int specialize_get_index(struct bytecode_runtime *runtime, switch (stack_top->load.object_type) { case OBJECT_TYPE_ARRAY: { + const struct lttng_integer_type *integer_type; const struct lttng_event_field *field; uint32_t elem_len, num_elems; int signedness; field = stack_top->load.field; - elem_len = field->type.u.array.elem_type.u.basic.integer.size; - signedness = field->type.u.array.elem_type.u.basic.integer.signedness; - num_elems = field->type.u.array.length; + switch (field->type.atype) { + case atype_array: + integer_type = &field->type.u.legacy.array.elem_type.u.basic.integer; + num_elems = field->type.u.legacy.array.length; + break; + case atype_array_nestable: + if (field->type.u.array_nestable.elem_type->atype != atype_integer) { + ret = -EINVAL; + goto end; + } + integer_type = &field->type.u.array_nestable.elem_type->u.integer; + num_elems = field->type.u.array_nestable.length; + break; + default: + ret = -EINVAL; + goto end; + } + elem_len = integer_type->size; + signedness = integer_type->signedness; if (index >= num_elems) { ret = -EINVAL; goto end; @@ -276,20 +297,36 @@ static int specialize_get_index(struct bytecode_runtime *runtime, gid.array_len = num_elems * (elem_len / CHAR_BIT); gid.elem.type = stack_top->load.object_type; gid.elem.len = elem_len; - if (field->type.u.array.elem_type.u.basic.integer.reverse_byte_order) + if (integer_type->reverse_byte_order) gid.elem.rev_bo = true; stack_top->load.rev_bo = gid.elem.rev_bo; break; } case OBJECT_TYPE_SEQUENCE: { + const struct lttng_integer_type *integer_type; const struct lttng_event_field *field; uint32_t elem_len; int signedness; field = stack_top->load.field; - elem_len = field->type.u.sequence.elem_type.u.basic.integer.size; - signedness = field->type.u.sequence.elem_type.u.basic.integer.signedness; + switch (field->type.atype) { + case atype_sequence: + integer_type = &field->type.u.legacy.sequence.elem_type.u.basic.integer; + break; + case atype_sequence_nestable: + if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) { + ret = -EINVAL; + goto end; + } + integer_type = &field->type.u.sequence_nestable.elem_type->u.integer; + break; + default: + ret = -EINVAL; + goto end; + } + elem_len = integer_type->size; + signedness = integer_type->signedness; ret = specialize_get_index_object_type(&stack_top->load.object_type, signedness, elem_len); if (ret) @@ -297,7 +334,7 @@ static int specialize_get_index(struct bytecode_runtime *runtime, gid.offset = index * (elem_len / CHAR_BIT); gid.elem.type = stack_top->load.object_type; gid.elem.len = elem_len; - if (field->type.u.sequence.elem_type.u.basic.integer.reverse_byte_order) + if (integer_type->reverse_byte_order) gid.elem.rev_bo = true; stack_top->load.rev_bo = gid.elem.rev_bo; break; @@ -359,22 +396,25 @@ static int specialize_load_object(const struct lttng_event_field *field, struct vstack_load *load, bool is_context) { load->type = LOAD_OBJECT; - /* - * LTTng-UST layout all integer fields as s64 on the stack for the filter. - */ + switch (field->type.atype) { case atype_integer: - if (field->type.u.basic.integer.signedness) + if (field->type.u.integer.signedness) load->object_type = OBJECT_TYPE_S64; else load->object_type = OBJECT_TYPE_U64; load->rev_bo = false; break; case atype_enum: + 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; + } if (itype->signedness) load->object_type = OBJECT_TYPE_S64; else @@ -383,14 +423,30 @@ static int specialize_load_object(const struct lttng_event_field *field, 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 (is_context) { load->object_type = OBJECT_TYPE_STRING; } else { - 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) { + load->object_type = OBJECT_TYPE_ARRAY; + load->field = field; + } else { + load->object_type = OBJECT_TYPE_STRING_SEQUENCE; + } + } + 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 (is_context) { + load->object_type = OBJECT_TYPE_STRING; + } else { + if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) { load->object_type = OBJECT_TYPE_ARRAY; load->field = field; } else { @@ -399,14 +455,30 @@ static int specialize_load_object(const struct lttng_event_field *field, } 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 (is_context) { + load->object_type = OBJECT_TYPE_STRING; + } else { + if (field->type.u.legacy.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) { + load->object_type = OBJECT_TYPE_SEQUENCE; + load->field = field; + } else { + load->object_type = OBJECT_TYPE_STRING_SEQUENCE; + } + } + 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 (is_context) { load->object_type = OBJECT_TYPE_STRING; } else { - 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) { load->object_type = OBJECT_TYPE_SEQUENCE; load->field = field; } else { @@ -414,6 +486,7 @@ static int specialize_load_object(const struct lttng_event_field *field, } } break; + case atype_string: load->object_type = OBJECT_TYPE_STRING; break; @@ -422,7 +495,7 @@ static int specialize_load_object(const struct lttng_event_field *field, break; case atype_dynamic: load->object_type = OBJECT_TYPE_DYNAMIC; - return -EINVAL; + break; case atype_struct: ERR("Structure type cannot be loaded."); return -EINVAL; @@ -433,7 +506,7 @@ static int specialize_load_object(const struct lttng_event_field *field, return 0; } -static int specialize_context_lookup(struct lttng_session *session, +static int specialize_context_lookup(struct lttng_ctx *ctx, struct bytecode_runtime *runtime, struct load_op *insn, struct vstack_load *load) @@ -444,11 +517,11 @@ static int specialize_context_lookup(struct lttng_session *session, struct filter_get_index_data gid; ssize_t data_offset; - idx = specialize_context_lookup_name(session->ctx, runtime, insn); + idx = specialize_context_lookup_name(ctx, runtime, insn); if (idx < 0) { return -ENOENT; } - ctx_field = &session->ctx->fields[idx]; + ctx_field = &ctx->fields[idx]; field = &ctx_field->event_field; ret = specialize_load_object(field, load, true); if (ret) @@ -458,6 +531,8 @@ static int specialize_context_lookup(struct lttng_session *session, memset(&gid, 0, sizeof(gid)); gid.ctx_index = idx; gid.elem.type = load->object_type; + gid.elem.rev_bo = load->rev_bo; + gid.field = field; data_offset = bytecode_push_data(runtime, &gid, __alignof__(gid), sizeof(gid)); if (data_offset < 0) { @@ -467,7 +542,7 @@ static int specialize_context_lookup(struct lttng_session *session, return 0; } -static int specialize_app_context_lookup(struct lttng_session *session, +static int specialize_app_context_lookup(struct lttng_ctx **pctx, struct bytecode_runtime *runtime, struct load_op *insn, struct vstack_load *load) @@ -490,19 +565,18 @@ static int specialize_app_context_lookup(struct lttng_session *session, } strcpy(name, "$app."); strcat(name, orig_name); - idx = lttng_get_context_index(session->ctx, name); + idx = lttng_get_context_index(*pctx, name); if (idx < 0) { assert(lttng_context_is_app(name)); ret = lttng_ust_add_app_context_to_ctx_rcu(name, - &session->ctx); + pctx); if (ret) return ret; - idx = lttng_get_context_index(session->ctx, - name); + idx = lttng_get_context_index(*pctx, name); if (idx < 0) return -ENOENT; } - ctx_field = &session->ctx->fields[idx]; + ctx_field = &(*pctx)->fields[idx]; field = &ctx_field->event_field; ret = specialize_load_object(field, load, true); if (ret) @@ -512,6 +586,8 @@ static int specialize_app_context_lookup(struct lttng_session *session, memset(&gid, 0, sizeof(gid)); gid.ctx_index = idx; gid.elem.type = load->object_type; + gid.elem.rev_bo = load->rev_bo; + gid.field = field; data_offset = bytecode_push_data(runtime, &gid, __alignof__(gid), sizeof(gid)); if (data_offset < 0) { @@ -525,14 +601,13 @@ end: return ret; } -static int specialize_event_payload_lookup(struct lttng_event *event, +static int specialize_payload_lookup(const struct lttng_event_desc *event_desc, struct bytecode_runtime *runtime, struct load_op *insn, struct vstack_load *load) { const char *name; uint16_t offset; - const struct lttng_event_desc *desc = event->desc; unsigned int i, nr_fields; bool found = false; uint32_t field_offset = 0; @@ -541,11 +616,14 @@ static int specialize_event_payload_lookup(struct lttng_event *event, struct filter_get_index_data gid; ssize_t data_offset; - nr_fields = desc->nr_fields; + nr_fields = event_desc->nr_fields; offset = ((struct get_symbol *) insn->data)->offset; name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset; for (i = 0; i < nr_fields; i++) { - field = &desc->fields[i]; + field = &event_desc->fields[i]; + if (field->u.ext.nofilter) { + continue; + } if (!strcmp(field->name, name)) { found = true; break; @@ -554,10 +632,13 @@ static int specialize_event_payload_lookup(struct lttng_event *event, switch (field->type.atype) { case atype_integer: case atype_enum: + case atype_enum_nestable: field_offset += sizeof(int64_t); break; case atype_array: + case atype_array_nestable: case atype_sequence: + case atype_sequence_nestable: field_offset += sizeof(unsigned long); field_offset += sizeof(void *); break; @@ -586,6 +667,8 @@ static int specialize_event_payload_lookup(struct lttng_event *event, memset(&gid, 0, sizeof(gid)); gid.offset = field_offset; gid.elem.type = load->object_type; + gid.elem.rev_bo = load->rev_bo; + gid.field = field; data_offset = bytecode_push_data(runtime, &gid, __alignof__(gid), sizeof(gid)); if (data_offset < 0) { @@ -598,14 +681,14 @@ end: return ret; } -int lttng_filter_specialize_bytecode(struct lttng_event *event, +int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, struct bytecode_runtime *bytecode) { void *pc, *next_pc, *start_pc; int ret = -EINVAL; struct vstack _stack; struct vstack *stack = &_stack; - struct lttng_session *session = bytecode->p.session; + struct lttng_ctx **pctx = bytecode->p.pctx; vstack_init(stack); @@ -621,6 +704,19 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, goto end; case FILTER_OP_RETURN: + if (vstack_ax(stack)->type == REG_S64 || + vstack_ax(stack)->type == REG_U64) + *(filter_opcode_t *) pc = FILTER_OP_RETURN_S64; + ret = 0; + goto end; + + case FILTER_OP_RETURN_S64: + if (vstack_ax(stack)->type != REG_S64 && + vstack_ax(stack)->type != REG_U64) { + ERR("Unexpected register type\n"); + ret = -EINVAL; + goto end; + } ret = 0; goto end; @@ -659,9 +755,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_EQ_STAR_GLOB_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_EQ_S64; else insn->op = FILTER_OP_EQ_DOUBLE_S64; @@ -669,7 +767,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_EQ_S64_DOUBLE; else insn->op = FILTER_OP_EQ_DOUBLE; @@ -711,9 +810,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_NE_STAR_GLOB_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_NE_S64; else insn->op = FILTER_OP_NE_DOUBLE_S64; @@ -721,7 +822,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_NE_S64_DOUBLE; else insn->op = FILTER_OP_NE_DOUBLE; @@ -759,9 +861,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_GT_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_GT_S64; else insn->op = FILTER_OP_GT_DOUBLE_S64; @@ -769,7 +873,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_GT_S64_DOUBLE; else insn->op = FILTER_OP_GT_DOUBLE; @@ -807,9 +912,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_LT_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_LT_S64; else insn->op = FILTER_OP_LT_DOUBLE_S64; @@ -817,7 +924,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_LT_S64_DOUBLE; else insn->op = FILTER_OP_LT_DOUBLE; @@ -855,9 +963,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_GE_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_GE_S64; else insn->op = FILTER_OP_GE_DOUBLE_S64; @@ -865,7 +975,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_GE_S64_DOUBLE; else insn->op = FILTER_OP_GE_DOUBLE; @@ -878,7 +989,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, ret = -EINVAL; goto end; } - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct binary_op); break; } @@ -902,9 +1013,11 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_LE_STRING; break; case REG_S64: + case REG_U64: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_LE_S64; else insn->op = FILTER_OP_LE_DOUBLE_S64; @@ -912,7 +1025,8 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case REG_DOUBLE: if (vstack_bx(stack)->type == REG_UNKNOWN) break; - if (vstack_bx(stack)->type == REG_S64) + if (vstack_bx(stack)->type == REG_S64 || + vstack_bx(stack)->type == REG_U64) insn->op = FILTER_OP_LE_S64_DOUBLE; else insn->op = FILTER_OP_LE_DOUBLE; @@ -957,6 +1071,17 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case FILTER_OP_LT_S64_DOUBLE: case FILTER_OP_GE_S64_DOUBLE: case FILTER_OP_LE_S64_DOUBLE: + { + /* Pop 2, push 1 */ + if (vstack_pop(stack)) { + ret = -EINVAL; + goto end; + } + vstack_ax(stack)->type = REG_S64; + next_pc += sizeof(struct binary_op); + break; + } + case FILTER_OP_BIT_RSHIFT: case FILTER_OP_BIT_LSHIFT: case FILTER_OP_BIT_AND: @@ -985,6 +1110,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_PLUS_S64; break; case REG_DOUBLE: @@ -1009,6 +1135,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_MINUS_S64; break; case REG_DOUBLE: @@ -1033,6 +1160,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_NOT_S64; break; case REG_DOUBLE: @@ -1206,6 +1334,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, insn->op = FILTER_OP_CAST_DOUBLE_TO_S64; break; case REG_UNKNOWN: + case REG_U64: break; } /* Pop 1, push 1 */ @@ -1281,13 +1410,20 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, case FILTER_OP_LOAD_FIELD_S16: case FILTER_OP_LOAD_FIELD_S32: case FILTER_OP_LOAD_FIELD_S64: + { + /* Pop 1, push 1 */ + vstack_ax(stack)->type = REG_S64; + next_pc += sizeof(struct load_op); + break; + } + case FILTER_OP_LOAD_FIELD_U8: case FILTER_OP_LOAD_FIELD_U16: case FILTER_OP_LOAD_FIELD_U32: case FILTER_OP_LOAD_FIELD_U64: { /* Pop 1, push 1 */ - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct load_op); break; } @@ -1321,7 +1457,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, goto end; case LOAD_ROOT_CONTEXT: /* Lookup context field. */ - ret = specialize_context_lookup(session, + ret = specialize_context_lookup(*pctx, bytecode, insn, &vstack_ax(stack)->load); if (ret) @@ -1329,7 +1465,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, break; case LOAD_ROOT_APP_CONTEXT: /* Lookup app context field. */ - ret = specialize_app_context_lookup(session, + ret = specialize_app_context_lookup(pctx, bytecode, insn, &vstack_ax(stack)->load); if (ret) @@ -1337,7 +1473,7 @@ int lttng_filter_specialize_bytecode(struct lttng_event *event, break; case LOAD_ROOT_PAYLOAD: /* Lookup event payload field. */ - ret = specialize_event_payload_lookup(event, + ret = specialize_payload_lookup(event_desc, bytecode, insn, &vstack_ax(stack)->load); if (ret)