From d97f9b785f05c29dbabb57da9a32c8c4317da8d3 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 23 Mar 2020 09:57:56 -0400 Subject: [PATCH] bytecode: add `REG_U64` interpreter register type This will be used by the capture bytecode for unsigned integer extraction. Signed-off-by: Mathieu Desnoyers Signed-off-by: Mathieu Desnoyers Change-Id: I8ff7ec22eddcf3acb4a359ad398f97476dd079f2 --- liblttng-ust/lttng-filter-interpreter.c | 127 +++++++++++++++--------- liblttng-ust/lttng-filter-specialize.c | 86 +++++++++++----- liblttng-ust/lttng-filter-validator.c | 127 ++++++++++++++++++++++-- liblttng-ust/lttng-filter.h | 1 + 4 files changed, 261 insertions(+), 80 deletions(-) diff --git a/liblttng-ust/lttng-filter-interpreter.c b/liblttng-ust/lttng-filter-interpreter.c index 49daa211..6c77cfe9 100644 --- a/liblttng-ust/lttng-filter-interpreter.c +++ b/liblttng-ust/lttng-filter-interpreter.c @@ -220,6 +220,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) @@ -521,7 +524,7 @@ 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: { @@ -532,7 +535,7 @@ static int dynamic_load_field(struct estack_entry *stack_top) 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: @@ -544,7 +547,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: @@ -556,7 +559,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: @@ -794,6 +797,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, /* Handle dynamic typing. */ switch (estack_ax_t) { case REG_S64: + case REG_U64: retval = !!estack_ax_v; break; case REG_DOUBLE: @@ -827,9 +831,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); @@ -846,7 +852,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); @@ -864,6 +871,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; @@ -881,6 +889,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; @@ -907,9 +916,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); @@ -926,7 +937,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); @@ -944,6 +956,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; @@ -961,6 +974,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; @@ -987,9 +1001,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); @@ -1006,7 +1022,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); @@ -1024,6 +1041,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; @@ -1048,9 +1066,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); @@ -1067,7 +1087,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); @@ -1085,6 +1106,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; @@ -1109,9 +1131,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); @@ -1128,7 +1152,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); @@ -1146,6 +1171,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; @@ -1170,9 +1196,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); @@ -1189,7 +1217,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); @@ -1207,6 +1236,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; @@ -1590,11 +1620,11 @@ 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; } + /* Catch undefined behavior. */ if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) { ret = -EINVAL; @@ -1603,7 +1633,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; } @@ -1611,11 +1641,11 @@ 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; } + /* Catch undefined behavior. */ if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) { ret = -EINVAL; @@ -1624,7 +1654,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; } @@ -1632,8 +1662,7 @@ 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; } @@ -1641,7 +1670,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; } @@ -1649,8 +1678,7 @@ 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; } @@ -1658,7 +1686,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; } @@ -1666,8 +1694,7 @@ 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; } @@ -1675,7 +1702,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; } @@ -1686,6 +1713,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); @@ -1704,7 +1732,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); @@ -1723,7 +1752,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); @@ -1744,12 +1774,13 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data, OP(FILTER_OP_UNARY_BIT_NOT): { /* Dynamic typing. */ - if (estack_ax_t != REG_S64) { + 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; } @@ -1775,6 +1806,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; } @@ -1791,7 +1823,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; } @@ -1811,7 +1843,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; } @@ -1979,6 +2011,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; @@ -2271,7 +2306,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; } @@ -2280,7 +2315,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; } @@ -2289,7 +2324,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; } @@ -2298,7 +2333,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; } diff --git a/liblttng-ust/lttng-filter-specialize.c b/liblttng-ust/lttng-filter-specialize.c index b7ab6158..171895b7 100644 --- a/liblttng-ust/lttng-filter-specialize.c +++ b/liblttng-ust/lttng-filter-specialize.c @@ -157,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; @@ -396,9 +396,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) @@ -700,13 +698,15 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, goto end; case FILTER_OP_RETURN: - if (vstack_ax(stack)->type == REG_S64) + 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) { + if (vstack_ax(stack)->type != REG_S64 && + vstack_ax(stack)->type != REG_U64) { ERR("Unexpected register type\n"); ret = -EINVAL; goto end; @@ -749,9 +749,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -759,7 +761,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -801,9 +804,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -811,7 +816,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -849,9 +855,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -859,7 +867,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -897,9 +906,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -907,7 +918,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -945,9 +957,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -955,7 +969,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -968,7 +983,7 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, ret = -EINVAL; goto end; } - vstack_ax(stack)->type = REG_S64; + vstack_ax(stack)->type = REG_U64; next_pc += sizeof(struct binary_op); break; } @@ -992,9 +1007,11 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -1002,7 +1019,8 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; @@ -1047,6 +1065,17 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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: @@ -1075,6 +1104,7 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_PLUS_S64; break; case REG_DOUBLE: @@ -1099,6 +1129,7 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_MINUS_S64; break; case REG_DOUBLE: @@ -1123,6 +1154,7 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, goto end; case REG_S64: + case REG_U64: insn->op = FILTER_OP_UNARY_NOT_S64; break; case REG_DOUBLE: @@ -1296,6 +1328,7 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, insn->op = FILTER_OP_CAST_DOUBLE_TO_S64; break; case REG_UNKNOWN: + case REG_U64: break; } /* Pop 1, push 1 */ @@ -1371,13 +1404,20 @@ int lttng_filter_specialize_bytecode(const struct lttng_event_desc *event_desc, 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; } diff --git a/liblttng-ust/lttng-filter-validator.c b/liblttng-ust/lttng-filter-validator.c index c1fed3ed..5ac79034 100644 --- a/liblttng-ust/lttng-filter-validator.c +++ b/liblttng-ust/lttng-filter-validator.c @@ -160,6 +160,7 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode, } break; case REG_S64: + case REG_U64: case REG_DOUBLE: goto error_mismatch; } @@ -178,11 +179,13 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode, break; case REG_STAR_GLOB_STRING: case REG_S64: + case REG_U64: case REG_DOUBLE: goto error_mismatch; } break; case REG_S64: + case REG_U64: case REG_DOUBLE: switch (vstack_bx(stack)->type) { default: @@ -194,6 +197,7 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode, case REG_STAR_GLOB_STRING: goto error_mismatch; case REG_S64: + case REG_U64: case REG_DOUBLE: break; } @@ -236,6 +240,7 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode, case REG_UNKNOWN: goto unknown; case REG_S64: + case REG_U64: switch (vstack_bx(stack)->type) { default: goto error_type; @@ -243,6 +248,7 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode, case REG_UNKNOWN: goto unknown; case REG_S64: + case REG_U64: break; } break; @@ -695,8 +701,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: + ERR("Unexpected register type for s64 comparator\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_bx(stack)->type) { + case REG_S64: + case REG_U64: + break; + default: ERR("Unexpected register type for s64 comparator\n"); ret = -EINVAL; goto end; @@ -736,7 +754,19 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - if (vstack_ax(stack)->type != REG_S64 && vstack_bx(stack)->type != REG_DOUBLE) { + switch (vstack_ax(stack)->type) { + case REG_S64: + case REG_U64: + break; + default: + ERR("Double-S64 operator has unexpected register types\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_bx(stack)->type) { + case REG_DOUBLE: + break; + default: ERR("Double-S64 operator has unexpected register types\n"); ret = -EINVAL; goto end; @@ -756,7 +786,19 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, ret = -EINVAL; goto end; } - if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_S64) { + switch (vstack_ax(stack)->type) { + case REG_DOUBLE: + break; + default: + ERR("S64-Double operator has unexpected register types\n"); + ret = -EINVAL; + goto end; + } + switch (vstack_bx(stack)->type) { + case REG_S64: + case REG_U64: + break; + default: ERR("S64-Double operator has unexpected register types\n"); ret = -EINVAL; goto end; @@ -813,6 +855,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, goto end; case REG_S64: break; + case REG_U64: + break; case REG_DOUBLE: break; case REG_UNKNOWN: @@ -841,6 +885,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, goto end; case REG_S64: break; + case REG_U64: + break; case REG_UNKNOWN: break; } @@ -856,7 +902,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) { ERR("Invalid register type\n"); ret = -EINVAL; goto end; @@ -893,8 +940,9 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, goto end; } if (vstack_ax(stack)->type != REG_S64 + && vstack_ax(stack)->type != REG_U64 && vstack_ax(stack)->type != REG_UNKNOWN) { - ERR("Logical comparator expects S64 or dynamic register\n"); + ERR("Logical comparator expects S64, U64 or dynamic register\n"); ret = -EINVAL; goto end; } @@ -985,6 +1033,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode, goto end; case REG_S64: break; + case REG_U64: + break; case REG_DOUBLE: break; case REG_UNKNOWN: @@ -1250,6 +1300,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_UNKNOWN: break; default: @@ -1271,6 +1322,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: break; default: case REG_UNKNOWN: @@ -1335,6 +1387,37 @@ int exec_insn(struct bytecode_runtime *bytecode, 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; + } + if (!vstack_ax(stack)) { + ERR("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_UNKNOWN: + break; + default: + ERR("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: @@ -1353,6 +1436,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: @@ -1365,7 +1449,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; } @@ -1384,6 +1468,7 @@ int exec_insn(struct bytecode_runtime *bytecode, case REG_UNKNOWN: case REG_DOUBLE: case REG_S64: + case REG_U64: break; default: ERR("Unexpected register type %d for operation\n", @@ -1408,6 +1493,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: break; default: ERR("Unexpected register type %d for operation\n", @@ -1416,7 +1502,6 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; next_pc += sizeof(struct unary_op); break; } @@ -1433,6 +1518,7 @@ int exec_insn(struct bytecode_runtime *bytecode, case REG_UNKNOWN: case REG_DOUBLE: case REG_S64: + case REG_U64: break; default: ERR("Unexpected register type %d for operation\n", @@ -1441,7 +1527,6 @@ int exec_insn(struct bytecode_runtime *bytecode, goto end; } - vstack_ax(stack)->type = REG_S64; next_pc += sizeof(struct unary_op); break; } @@ -1457,6 +1542,7 @@ int exec_insn(struct bytecode_runtime *bytecode, switch (vstack_ax(stack)->type) { case REG_UNKNOWN: case REG_S64: + case REG_U64: break; case REG_DOUBLE: default: @@ -1466,7 +1552,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; } @@ -1541,6 +1627,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: ERR("Incorrect register type %d for operation\n", @@ -1674,6 +1761,7 @@ int exec_insn(struct bytecode_runtime *bytecode, } switch (vstack_ax(stack)->type) { case REG_S64: + case REG_U64: case REG_DOUBLE: case REG_UNKNOWN: break; @@ -1731,6 +1819,23 @@ 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)) { + ERR("Empty stack\n"); + ret = -EINVAL; + goto end; + } + if (vstack_ax(stack)->type != REG_PTR) { + ERR("Expecting pointer on top of stack\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: @@ -1747,7 +1852,7 @@ 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; } diff --git a/liblttng-ust/lttng-filter.h b/liblttng-ust/lttng-filter.h index f8e11293..bf553cea 100644 --- a/liblttng-ust/lttng-filter.h +++ b/liblttng-ust/lttng-filter.h @@ -87,6 +87,7 @@ struct bytecode_runtime { enum entry_type { REG_S64, + REG_U64, REG_DOUBLE, REG_STRING, REG_STAR_GLOB_STRING, -- 2.34.1