X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Ffilter%2Ffilter-visitor-generate-bytecode.c;h=7d62757477febbcddd0a88e8f4524d74c74682a9;hb=3f0c88379cfbbbec84641e13b21f290a563f8729;hp=36d35c558727e6df654a55b3bebc1bee4fb069de;hpb=d00c599e39ae45ec7c8e12e6bac6b5e58f08f817;p=lttng-tools.git diff --git a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c index 36d35c558..7d6275747 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c @@ -27,6 +27,8 @@ #include "filter-ir.h" #include "filter-ast.h" +#include + #ifndef max_t #define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b))) #endif @@ -38,14 +40,56 @@ static int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx, struct ir_op *node); +static inline int fls(unsigned int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xFFFF0000U)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xFF000000U)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xF0000000U)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xC0000000U)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000U)) { + x <<= 1; + r -= 1; + } + return r; +} + +static inline int get_count_order(unsigned int count) +{ + int order; + + order = fls(count) - 1; + if (count & (count - 1)) + order++; + return order; +} + static int bytecode_init(struct lttng_filter_bytecode_alloc **fb) { - *fb = calloc(sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1); + uint32_t alloc_len; + + alloc_len = sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE; + *fb = calloc(alloc_len, 1); if (!*fb) { return -ENOMEM; } else { - (*fb)->alloc_len = INIT_ALLOC_SIZE; + (*fb)->alloc_len = alloc_len; return 0; } } @@ -55,20 +99,25 @@ int32_t bytecode_reserve(struct lttng_filter_bytecode_alloc **fb, uint32_t align { int32_t ret; uint32_t padding = offset_align((*fb)->b.len, align); + uint32_t new_len = (*fb)->b.len + padding + len; + uint32_t new_alloc_len = sizeof(struct lttng_filter_bytecode_alloc) + new_len; + uint32_t old_alloc_len = (*fb)->alloc_len; - if ((*fb)->b.len + padding + len > (*fb)->alloc_len) { - uint32_t new_len = - max_t(uint32_t, (*fb)->b.len + padding + len, - (*fb)->alloc_len << 1); - uint32_t old_len = (*fb)->alloc_len; + if (new_len > LTTNG_FILTER_MAX_LEN) + return -EINVAL; - if (new_len > 0xFFFF) - return -EINVAL; - *fb = realloc(*fb, sizeof(struct lttng_filter_bytecode_alloc) + new_len); - if (!*fb) + if (new_alloc_len > old_alloc_len) { + struct lttng_filter_bytecode_alloc *newptr; + + new_alloc_len = + max_t(uint32_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1); + newptr = realloc(*fb, new_alloc_len); + if (!newptr) return -ENOMEM; - memset(&(*fb)->b.data[old_len], 0, new_len - old_len); - (*fb)->alloc_len = new_len; + *fb = newptr; + /* We zero directly the memory from start of allocation. */ + memset(&((char *) *fb)[old_alloc_len], 0, new_alloc_len - old_alloc_len); + (*fb)->alloc_len = new_alloc_len; } (*fb)->b.len += padding; ret = (*fb)->b.len; @@ -173,7 +222,7 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) if (!insn) return -ENOMEM; insn->op = FILTER_OP_LOAD_S64; - *(int64_t *) insn->data = node->u.load.u.num; + memcpy(insn->data, &node->u.load.u.num, sizeof(int64_t)); ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); free(insn); return ret; @@ -188,27 +237,44 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) if (!insn) return -ENOMEM; insn->op = FILTER_OP_LOAD_DOUBLE; - *(double *) insn->data = node->u.load.u.flt; + memcpy(insn->data, &node->u.load.u.flt, sizeof(double)); ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); free(insn); return ret; } - case IR_DATA_FIELD_REF: + case IR_DATA_FIELD_REF: /* fall-through */ + case IR_DATA_GET_CONTEXT_REF: { struct load_op *insn; uint32_t insn_len = sizeof(struct load_op) + sizeof(struct field_ref); struct field_ref ref_offset; + uint32_t reloc_offset_u32; uint16_t reloc_offset; insn = calloc(insn_len, 1); if (!insn) return -ENOMEM; - insn->op = FILTER_OP_LOAD_FIELD_REF; + switch(node->data_type) { + case IR_DATA_FIELD_REF: + insn->op = FILTER_OP_LOAD_FIELD_REF; + break; + case IR_DATA_GET_CONTEXT_REF: + insn->op = FILTER_OP_GET_CONTEXT_REF; + break; + default: + free(insn); + return -EINVAL; + } ref_offset.offset = (uint16_t) -1U; memcpy(insn->data, &ref_offset, sizeof(ref_offset)); /* reloc_offset points to struct load_op */ - reloc_offset = bytecode_get_len(&ctx->bytecode->b); + reloc_offset_u32 = bytecode_get_len(&ctx->bytecode->b); + if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) { + free(insn); + return -EINVAL; + } + reloc_offset = (uint16_t) reloc_offset_u32; ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); if (ret) { free(insn); @@ -359,11 +425,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) if (ret) return ret; /* Cast to s64 if float or field ref */ - if (node->u.binary.left->data_type == IR_DATA_FIELD_REF + if ((node->u.binary.left->data_type == IR_DATA_FIELD_REF + || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF) || node->u.binary.left->data_type == IR_DATA_FLOAT) { struct cast_op cast_insn; - if (node->u.binary.left->data_type == IR_DATA_FIELD_REF) { + if (node->u.binary.left->data_type == IR_DATA_FIELD_REF + || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF) { cast_insn.op = FILTER_OP_CAST_TO_S64; } else { cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64; @@ -396,11 +464,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) if (ret) return ret; /* Cast to s64 if float or field ref */ - if (node->u.binary.right->data_type == IR_DATA_FIELD_REF + if ((node->u.binary.right->data_type == IR_DATA_FIELD_REF + || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF) || node->u.binary.right->data_type == IR_DATA_FLOAT) { struct cast_op cast_insn; - if (node->u.binary.right->data_type == IR_DATA_FIELD_REF) { + if (node->u.binary.right->data_type == IR_DATA_FIELD_REF + || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF) { cast_insn.op = FILTER_OP_CAST_TO_S64; } else { cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64; @@ -447,16 +517,21 @@ int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx, } } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN void filter_bytecode_free(struct filter_parser_ctx *ctx) { - free(ctx->bytecode); - ctx->bytecode = NULL; - free(ctx->bytecode_reloc); - ctx->bytecode_reloc = NULL; + if (ctx->bytecode) { + free(ctx->bytecode); + ctx->bytecode = NULL; + } + + if (ctx->bytecode_reloc) { + free(ctx->bytecode_reloc); + ctx->bytecode_reloc = NULL; + } } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx) { int ret;