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=8c6dc96ff236520de23ea0efa7ee7b37f1c20784;hb=bff988fac4f8d1ffab3f85f0eec9546c76e57706;hpb=58d494e4e885915ac387de8aa74f810d4d160bb0 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 8c6dc96ff..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,7 +22,9 @@ #include #include #include -#include "align.h" +#include +#include + #include "filter-bytecode.h" #include "filter-ir.h" #include "filter-ast.h" @@ -33,47 +35,17 @@ #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; @@ -185,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) { @@ -201,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; @@ -242,56 +400,8 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) free(insn); return ret; } - 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; - 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_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); } } @@ -377,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: @@ -426,12 +536,14 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) return ret; /* Cast to s64 if float or 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_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 - || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_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; @@ -465,12 +577,14 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) return ret; /* Cast to s64 if float or 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_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 - || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_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; @@ -520,10 +634,19 @@ int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx, 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; + } } LTTNG_HIDDEN