X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Ffilter%2Ffilter-visitor-generate-bytecode.c;h=34183ed2edf4f79a46ff5624f4ce4e60a593fdfc;hp=8d44f4b7ec29d3b66cde39158711abeb558db135;hb=bff988fac4f8d1ffab3f85f0eec9546c76e57706;hpb=ec96a8f6df4c26c3bf0252a642f90e6a78e02c78 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 8d44f4b7e..34183ed2e 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c @@ -22,56 +22,30 @@ #include #include #include -#include "align.h" +#include +#include + #include "filter-bytecode.h" #include "filter-ir.h" #include "filter-ast.h" +#include + #ifndef max_t #define max_t(type, a, b) ((type) ((a) > (b) ? (a) : (b))) #endif -//#define INIT_ALLOC_SIZE PAGE_SIZE #define INIT_ALLOC_SIZE 4 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; + order = lttng_fls(count) - 1; if (count & (count - 1)) order++; return order; @@ -80,11 +54,14 @@ static inline int get_count_order(unsigned int count) 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; } } @@ -95,18 +72,22 @@ 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) + new_len; + uint32_t new_alloc_len = sizeof(struct lttng_filter_bytecode_alloc) + new_len; uint32_t old_alloc_len = (*fb)->alloc_len; if (new_len > LTTNG_FILTER_MAX_LEN) return -EINVAL; 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); - *fb = realloc(*fb, new_alloc_len); - if (!*fb) + newptr = realloc(*fb, new_alloc_len); + if (!newptr) return -ENOMEM; + *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; } @@ -176,6 +157,167 @@ int visit_node_root(struct filter_parser_ctx *ctx, struct ir_op *node) return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn)); } +static +int visit_node_load_expression(struct filter_parser_ctx *ctx, + const struct ir_op *node) +{ + struct ir_load_expression *exp; + struct ir_load_expression_op *op; + + exp = node->u.load.u.expression; + if (!exp) { + return -EINVAL; + } + op = exp->child; + if (!op) { + return -EINVAL; + } + for (; op != NULL; op = op->next) { + switch (op->type) { + case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op); + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_GET_CONTEXT_ROOT; + ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); + free(insn); + if (ret) { + return ret; + } + break; + } + case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op); + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_GET_APP_CONTEXT_ROOT; + ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); + free(insn); + if (ret) { + return ret; + } + break; + } + case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op); + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_GET_PAYLOAD_ROOT; + ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); + free(insn); + if (ret) { + return ret; + } + break; + } + case IR_LOAD_EXPRESSION_GET_SYMBOL: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op) + + sizeof(struct get_symbol); + struct get_symbol symbol_offset; + uint32_t reloc_offset_u32; + uint16_t reloc_offset; + uint32_t bytecode_reloc_offset_u32; + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_GET_SYMBOL; + bytecode_reloc_offset_u32 = + bytecode_get_len(&ctx->bytecode_reloc->b) + + sizeof(reloc_offset); + symbol_offset.offset = + (uint16_t) bytecode_reloc_offset_u32; + memcpy(insn->data, &symbol_offset, + sizeof(symbol_offset)); + /* reloc_offset points to struct load_op */ + 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); + return ret; + } + /* append reloc */ + ret = bytecode_push(&ctx->bytecode_reloc, &reloc_offset, + 1, sizeof(reloc_offset)); + if (ret) { + free(insn); + return ret; + } + ret = bytecode_push(&ctx->bytecode_reloc, + op->u.symbol, + 1, strlen(op->u.symbol) + 1); + free(insn); + if (ret) { + return ret; + } + break; + } + case IR_LOAD_EXPRESSION_GET_INDEX: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op) + + sizeof(struct get_index_u64); + struct get_index_u64 index; + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_GET_INDEX_U64; + index.index = op->u.index; + memcpy(insn->data, &index, sizeof(index)); + ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); + free(insn); + if (ret) { + return ret; + } + break; + } + case IR_LOAD_EXPRESSION_LOAD_FIELD: + { + struct load_op *insn; + uint32_t insn_len = sizeof(struct load_op); + int ret; + + insn = calloc(insn_len, 1); + if (!insn) + return -ENOMEM; + insn->op = FILTER_OP_LOAD_FIELD; + ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); + free(insn); + if (ret) { + return ret; + } + break; + } + } + } + return 0; +} + static int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) { @@ -192,13 +334,38 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) { struct load_op *insn; uint32_t insn_len = sizeof(struct load_op) - + strlen(node->u.load.u.string) + 1; + + strlen(node->u.load.u.string.value) + 1; insn = calloc(insn_len, 1); if (!insn) return -ENOMEM; - insn->op = FILTER_OP_LOAD_STRING; - strcpy(insn->data, node->u.load.u.string); + + switch (node->u.load.u.string.type) { + case IR_LOAD_STRING_TYPE_GLOB_STAR: + /* + * We explicitly tell the interpreter here that + * this load is a full star globbing pattern so + * that the appropriate matching function can be + * called. Also, see comment below. + */ + insn->op = FILTER_OP_LOAD_STAR_GLOB_STRING; + break; + default: + /* + * This is the "legacy" string, which includes + * star globbing patterns with a star only at + * the end. Both "plain" and "star at the end" + * literal strings are handled at the same place + * by the tracer's filter bytecode interpreter, + * whereas full star globbing patterns (stars + * can be anywhere in the string) is a special + * case. + */ + insn->op = FILTER_OP_LOAD_STRING; + break; + } + + strcpy(insn->data, node->u.load.u.string.value); ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len); free(insn); return ret; @@ -213,7 +380,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; @@ -228,50 +395,13 @@ 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: - { - 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; - ref_offset.offset = (uint16_t) -1U; - memcpy(insn->data, &ref_offset, sizeof(ref_offset)); - /* reloc_offset points to struct load_op */ - 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); - return ret; - } - /* append reloc */ - ret = bytecode_push(&ctx->bytecode_reloc, &reloc_offset, - 1, sizeof(reloc_offset)); - if (ret) { - free(insn); - return ret; - } - ret = bytecode_push(&ctx->bytecode_reloc, node->u.load.u.ref, - 1, strlen(node->u.load.u.ref) + 1); - free(insn); - return ret; - } + case IR_DATA_EXPRESSION: + return visit_node_load_expression(ctx, node); } } @@ -357,14 +487,14 @@ int visit_node_binary(struct filter_parser_ctx *ctx, struct ir_op *node) case AST_OP_LSHIFT: insn.op = FILTER_OP_LSHIFT; break; - case AST_OP_BIN_AND: - insn.op = FILTER_OP_BIN_AND; + case AST_OP_BIT_AND: + insn.op = FILTER_OP_BIT_AND; break; - case AST_OP_BIN_OR: - insn.op = FILTER_OP_BIN_OR; + case AST_OP_BIT_OR: + insn.op = FILTER_OP_BIT_OR; break; - case AST_OP_BIN_XOR: - insn.op = FILTER_OP_BIN_XOR; + case AST_OP_BIT_XOR: + insn.op = FILTER_OP_BIT_XOR; break; case AST_OP_EQ: @@ -405,11 +535,15 @@ 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_EXPRESSION) || 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 + || node->u.binary.left->data_type == IR_DATA_EXPRESSION) { cast_insn.op = FILTER_OP_CAST_TO_S64; } else { cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64; @@ -442,11 +576,15 @@ 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_EXPRESSION) || 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 + || node->u.binary.right->data_type == IR_DATA_EXPRESSION) { cast_insn.op = FILTER_OP_CAST_TO_S64; } else { cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64; @@ -493,16 +631,25 @@ 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) { + return; + } + + 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;