X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=src%2Flttng-filter-interpreter.c;h=403a712fa0ade1c5c959780916f0b8ec6e7f0e96;hb=7ab8c61663d23386a58fb2f36ab8e22d1c0b1efd;hp=4aefb04ed50a43ed10b895091c5001c7cb59e4b5;hpb=d644d1df290531d8c2be54d6cf4485cc5ebeefde;p=lttng-modules.git diff --git a/src/lttng-filter-interpreter.c b/src/lttng-filter-interpreter.c index 4aefb04e..403a712f 100644 --- a/src/lttng-filter-interpreter.c +++ b/src/lttng-filter-interpreter.c @@ -15,8 +15,6 @@ #include #include -LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode); - /* * get_char should be called with page fault handler disabled if it is expected * to handle user-space read. @@ -209,7 +207,7 @@ 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, struct lttng_probe_ctx *lttng_probe_ctx, const char *filter_stack_data) { @@ -262,7 +260,8 @@ LABEL_##name #endif -#define IS_INTEGER_REGISTER(reg_type) (reg_type == REG_S64) +#define IS_INTEGER_REGISTER(reg_type) \ + (reg_type == REG_S64 || reg_type == REG_U64) static int context_get_index(struct lttng_probe_ctx *lttng_probe_ctx, struct load_ptr *ptr, @@ -360,13 +359,6 @@ static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_ctx, 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: @@ -382,7 +374,7 @@ static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_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; - /* field is only used for types nested within variants. */ + BUG_ON(stack_top->u.ptr.field->type.atype != atype_array_nestable); stack_top->u.ptr.field = NULL; break; } @@ -401,7 +393,7 @@ static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_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; - /* field is only used for types nested within variants. */ + BUG_ON(stack_top->u.ptr.field->type.atype != atype_sequence_nestable); stack_top->u.ptr.field = NULL; break; } @@ -434,10 +426,13 @@ static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_ctx, 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: @@ -504,7 +499,7 @@ static int dynamic_load_field(struct estack_entry *stack_top) case OBJECT_TYPE_U8: dbg_printk("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: { @@ -515,7 +510,7 @@ static int dynamic_load_field(struct estack_entry *stack_top) if (stack_top->u.ptr.rev_bo) __swab16s(&tmp); stack_top->u.v = tmp; - stack_top->type = REG_S64; + stack_top->type = REG_U64; break; } case OBJECT_TYPE_U32: @@ -527,7 +522,7 @@ static int dynamic_load_field(struct estack_entry *stack_top) if (stack_top->u.ptr.rev_bo) __swab32s(&tmp); stack_top->u.v = tmp; - stack_top->type = REG_S64; + stack_top->type = REG_U64; break; } case OBJECT_TYPE_U64: @@ -539,7 +534,7 @@ static int dynamic_load_field(struct estack_entry *stack_top) if (stack_top->u.ptr.rev_bo) __swab64s(&tmp); stack_top->u.v = tmp; - stack_top->type = REG_S64; + stack_top->type = REG_U64; break; } case OBJECT_TYPE_STRING: @@ -602,16 +597,86 @@ 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_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_TYPE_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, +static +uint64_t bytecode_interpret(void *interpreter_data, struct lttng_probe_ctx *lttng_probe_ctx, - const char *filter_stack_data) + const char *interpreter_stack_data, + struct lttng_interpreter_output *output) { - struct bytecode_runtime *bytecode = filter_data; + struct bytecode_runtime *bytecode = interpreter_data; void *pc, *next_pc, *start_pc; int ret = -EINVAL; uint64_t retval = 0; @@ -779,11 +844,18 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */ 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_TYPE_UNKNOWN: ret = -EINVAL; @@ -1016,7 +1088,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, 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; } @@ -1037,7 +1109,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, 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; } @@ -1053,7 +1125,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, 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; } @@ -1069,7 +1141,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, 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; } @@ -1085,7 +1157,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, 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; } @@ -1186,7 +1258,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_printk("Filter warning: loading a NULL string.\n"); ret = -EINVAL; @@ -1211,9 +1283,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)]); if (unlikely(!estack_ax(stack, top)->u.s.str)) { dbg_printk("Filter warning: loading a NULL sequence.\n"); @@ -1236,7 +1308,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_printk("ref load s64 %lld\n", (long long) estack_ax_v); @@ -1385,7 +1457,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.user_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_printk("Filter warning: loading a NULL string.\n"); ret = -EINVAL; @@ -1410,9 +1482,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.user_str = - *(const char **) (&filter_stack_data[ref->offset + *(const char **) (&interpreter_stack_data[ref->offset + sizeof(unsigned long)]); if (unlikely(!estack_ax(stack, top)->u.s.str)) { dbg_printk("Filter warning: loading a NULL sequence.\n"); @@ -1449,7 +1521,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, dbg_printk("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(stack, top)->type = REG_PTR; @@ -1654,8 +1726,23 @@ end: /* Return _DISCARD on error. */ if (ret) return LTTNG_FILTER_DISCARD; + + if (output) { + return lttng_bytecode_interpret_format_output( + estack_ax(stack, top), output); + } + return retval; } +LTTNG_STACK_FRAME_NON_STANDARD(bytecode_interpret); + +uint64_t lttng_filter_interpret_bytecode(void *filter_data, + struct lttng_probe_ctx *lttng_probe_ctx, + const char *filter_stack_data) +{ + return bytecode_interpret(filter_data, lttng_probe_ctx, + filter_stack_data, NULL); +} #undef START_OP #undef OP