From 1242217a08db0fb08a4f8f7bb3a94b82647b17e4 Mon Sep 17 00:00:00 2001 From: Francis Deslauriers Date: Thu, 30 Apr 2020 17:30:45 -0400 Subject: [PATCH] bytecode: add `REG_U64` interpreter register type Signed-off-by: Francis Deslauriers Signed-off-by: Mathieu Desnoyers Change-Id: I53c12a54cbd416617834982bbd2b7cf528d41a76 --- include/lttng/filter.h | 1 + src/lttng-filter-interpreter.c | 22 ++++---- src/lttng-filter-specialize.c | 4 +- src/lttng-filter-validator.c | 97 ++++++++++++++++++++++++++++++---- 4 files changed, 100 insertions(+), 24 deletions(-) diff --git a/include/lttng/filter.h b/include/lttng/filter.h index ce269213..26538b5e 100644 --- a/include/lttng/filter.h +++ b/include/lttng/filter.h @@ -47,6 +47,7 @@ struct bytecode_runtime { enum entry_type { REG_S64, + REG_U64, REG_DOUBLE, REG_STRING, REG_STAR_GLOB_STRING, diff --git a/src/lttng-filter-interpreter.c b/src/lttng-filter-interpreter.c index 4aefb04e..7c05c24f 100644 --- a/src/lttng-filter-interpreter.c +++ b/src/lttng-filter-interpreter.c @@ -262,7 +262,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, @@ -504,7 +505,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 +516,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 +528,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 +540,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: @@ -779,6 +780,7 @@ 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: @@ -1016,7 +1018,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 +1039,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 +1055,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 +1071,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 +1087,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; } diff --git a/src/lttng-filter-specialize.c b/src/lttng-filter-specialize.c index c7718ec7..82b5cb64 100644 --- a/src/lttng-filter-specialize.c +++ b/src/lttng-filter-specialize.c @@ -313,9 +313,7 @@ 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.integer.signedness) diff --git a/src/lttng-filter-validator.c b/src/lttng-filter-validator.c index 9057ee8a..7e308281 100644 --- a/src/lttng-filter-validator.c +++ b/src/lttng-filter-validator.c @@ -127,6 +127,7 @@ int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode, } break; case REG_S64: + case REG_U64: goto error_mismatch; } break; @@ -144,10 +145,12 @@ int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode, break; case REG_STAR_GLOB_STRING: case REG_S64: + case REG_U64: goto error_mismatch; } break; case REG_S64: + case REG_U64: switch (vstack_bx(stack)->type) { default: case REG_DOUBLE: @@ -158,6 +161,7 @@ int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode, case REG_STAR_GLOB_STRING: goto error_mismatch; case REG_S64: + case REG_U64: break; } break; @@ -170,6 +174,7 @@ int bin_op_compare_check(struct vstack *stack, const filter_opcode_t opcode, case REG_STRING: case REG_STAR_GLOB_STRING: case REG_S64: + case REG_U64: goto unknown; } break; @@ -216,10 +221,12 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode, goto error_type; case REG_TYPE_UNKNOWN: case REG_S64: + case REG_U64: goto unknown; } break; case REG_S64: + case REG_U64: switch (vstack_bx(stack)->type) { default: case REG_DOUBLE: @@ -227,6 +234,7 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode, case REG_TYPE_UNKNOWN: goto unknown; case REG_S64: + case REG_U64: break; } break; @@ -707,8 +715,20 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - if (vstack_ax(stack)->type != REG_S64 - || vstack_bx(stack)->type != REG_S64) { + switch (vstack_ax(stack)->type) { + case REG_S64: + case REG_U64: + break; + default: + printk(KERN_WARNING "LTTng: filter: Unexpected register type for s64 comparator\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_bx(stack)->type) { + case REG_S64: + case REG_U64: + break; + default: printk(KERN_WARNING "LTTng: filter: Unexpected register type for s64 comparator\n"); ret = -EINVAL; goto end; @@ -765,6 +785,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; case REG_S64: + case REG_U64: case REG_TYPE_UNKNOWN: break; } @@ -790,7 +811,7 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; case REG_S64: - break; + case REG_U64: case REG_TYPE_UNKNOWN: break; } @@ -806,7 +827,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - if (vstack_ax(stack)->type != REG_S64) { + if (vstack_ax(stack)->type != REG_S64 && + vstack_ax(stack)->type != REG_U64) { printk(KERN_WARNING "LTTng: filter: Invalid register type\n"); ret = -EINVAL; goto end; @@ -825,7 +847,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - if (vstack_ax(stack)->type != REG_S64) { + if (vstack_ax(stack)->type != REG_S64 && + vstack_ax(stack)->type != REG_U64) { printk(KERN_WARNING "LTTng: filter: Logical comparator expects S64 register\n"); ret = -EINVAL; goto end; @@ -1154,6 +1177,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_TYPE_UNKNOWN: break; default: @@ -1176,6 +1200,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: break; default: case REG_TYPE_UNKNOWN: @@ -1248,6 +1273,36 @@ int exec_insn(struct bytecode_runtime *bytecode, case FILTER_OP_LT_S64: case FILTER_OP_GE_S64: case FILTER_OP_LE_S64: + { + /* Pop 2, push 1 */ + if (vstack_pop(stack)) { + ret = -EINVAL; + goto end; + } + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_ax(stack)->type) { + case REG_S64: + case REG_U64: + case REG_DOUBLE: + case REG_STRING: + case REG_STAR_GLOB_STRING: + case REG_TYPE_UNKNOWN: + break; + default: + printk(KERN_WARNING "Unexpected register type %d for operation\n", + (int) vstack_ax(stack)->type); + 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: @@ -1266,6 +1321,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_DOUBLE: case REG_STRING: case REG_STAR_GLOB_STRING: @@ -1278,7 +1334,7 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct binary_op); break; } @@ -1295,6 +1351,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_TYPE_UNKNOWN: break; default: @@ -1321,6 +1378,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: break; default: printk(KERN_WARNING "LTTng: filter: Unexpected register type %d for operation\n", @@ -1329,7 +1387,6 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; next_pc += sizeof(struct unary_op); break; } @@ -1344,6 +1401,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_TYPE_UNKNOWN: break; default: @@ -1353,7 +1411,6 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; next_pc += sizeof(struct unary_op); break; } @@ -1368,6 +1425,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_TYPE_UNKNOWN: break; case REG_DOUBLE: @@ -1378,7 +1436,7 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct unary_op); break; } @@ -1406,6 +1464,7 @@ int exec_insn(struct bytecode_runtime *bytecode, /* There is always a cast-to-s64 operation before a or/and op. */ switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: break; default: printk(KERN_WARNING "LTTng: filter: Incorrect register type %d for operation\n", @@ -1513,6 +1572,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_DOUBLE: case REG_TYPE_UNKNOWN: break; @@ -1570,6 +1630,22 @@ int exec_insn(struct bytecode_runtime *bytecode, case FILTER_OP_LOAD_FIELD_S16: case FILTER_OP_LOAD_FIELD_S32: case FILTER_OP_LOAD_FIELD_S64: + { + /* Pop 1, push 1 */ + if (!vstack_ax(stack)) { + printk(KERN_WARNING "Empty stack\n\n"); + ret = -EINVAL; + goto end; + } + if (vstack_ax(stack)->type != REG_PTR) { + printk(KERN_WARNING "Expecting pointer on top of stack\n\n"); + ret = -EINVAL; + goto end; + } + 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: @@ -1586,11 +1662,10 @@ int exec_insn(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct load_op); break; } - case FILTER_OP_LOAD_FIELD_STRING: case FILTER_OP_LOAD_FIELD_SEQUENCE: { -- 2.34.1