From bff988fac4f8d1ffab3f85f0eec9546c76e57706 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 4 Jul 2017 16:28:54 -0400 Subject: [PATCH] Filter: index array, sequences, implement bitwise binary operators MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add load expressions, and produce bytecode allowing indexing of array and sequence of integers, as well as bitwise binary operators &, |, ^. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- src/lib/lttng-ctl/filter/Makefile.am | 1 - src/lib/lttng-ctl/filter/filter-ast.h | 15 +- src/lib/lttng-ctl/filter/filter-bytecode.h | 50 ++- .../lttng-ctl/filter/filter-grammar-test.c | 5 - src/lib/lttng-ctl/filter/filter-ir.h | 30 +- src/lib/lttng-ctl/filter/filter-lexer.l | 2 +- src/lib/lttng-ctl/filter/filter-parser.y | 89 +++-- .../filter/filter-visitor-generate-bytecode.c | 288 ++++++++------ .../filter/filter-visitor-generate-ir.c | 376 ++++++++++-------- ...ilter-visitor-ir-check-binary-op-nesting.c | 4 - .../filter/filter-visitor-set-parent.c | 149 ------- src/lib/lttng-ctl/filter/filter-visitor-xml.c | 8 +- src/lib/lttng-ctl/lttng-ctl.c | 6 - .../tools/filtering/gen-ust-events.c | 8 +- .../tools/filtering/test_invalid_filter | 12 +- .../tools/filtering/test_unsupported_op | 8 +- .../tools/filtering/test_valid_filter | 124 +++++- tests/regression/tools/filtering/tp.h | 6 +- 18 files changed, 649 insertions(+), 532 deletions(-) delete mode 100644 src/lib/lttng-ctl/filter/filter-visitor-set-parent.c diff --git a/src/lib/lttng-ctl/filter/Makefile.am b/src/lib/lttng-ctl/filter/Makefile.am index e338eee6e..35feee9a7 100644 --- a/src/lib/lttng-ctl/filter/Makefile.am +++ b/src/lib/lttng-ctl/filter/Makefile.am @@ -9,7 +9,6 @@ BUILT_SOURCES = filter-parser.h libfilter_la_SOURCES = \ filter-parser.y filter-lexer.l \ - filter-visitor-set-parent.c \ filter-visitor-xml.c \ filter-visitor-generate-ir.c \ filter-visitor-ir-check-binary-op-nesting.c \ diff --git a/src/lib/lttng-ctl/filter/filter-ast.h b/src/lib/lttng-ctl/filter/filter-ast.h index 067624906..4bf42fd3f 100644 --- a/src/lib/lttng-ctl/filter/filter-ast.h +++ b/src/lib/lttng-ctl/filter/filter-ast.h @@ -71,9 +71,9 @@ enum op_type { AST_OP_LSHIFT, AST_OP_AND, AST_OP_OR, - AST_OP_BIN_AND, - AST_OP_BIN_OR, - AST_OP_BIN_XOR, + AST_OP_BIT_AND, + AST_OP_BIT_OR, + AST_OP_BIT_XOR, AST_OP_EQ, AST_OP_NE, @@ -88,7 +88,7 @@ enum unary_op_type { AST_UNARY_PLUS, AST_UNARY_MINUS, AST_UNARY_NOT, - AST_UNARY_BIN_NOT, + AST_UNARY_BIT_NOT, }; enum ast_link_type { @@ -134,10 +134,12 @@ struct filter_node { */ struct filter_node *child; } u; - /* prev: linked dot/arrow chain (postfix expression) */ + /* prev: backward dot/arrow chain (postfix expression) */ struct filter_node *prev; - /* next: linked bracket chain (prefix expression) */ + /* next: forward dot/arrow chain, generated by a visitor. */ struct filter_node *next; + /* next_bracket: linked bracket chain (prefix expression) */ + struct filter_node *next_bracket; } expression; struct { enum op_type type; @@ -179,7 +181,6 @@ struct filter_ast *filter_parser_get_ast(struct filter_parser_ctx *parser_ctx) return parser_ctx->ast; } -int filter_visitor_set_parent(struct filter_parser_ctx *ctx); int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream, int indent); int filter_visitor_ir_generate(struct filter_parser_ctx *ctx); diff --git a/src/lib/lttng-ctl/filter/filter-bytecode.h b/src/lib/lttng-ctl/filter/filter-bytecode.h index b7b71ad53..a86963f73 100644 --- a/src/lib/lttng-ctl/filter/filter-bytecode.h +++ b/src/lib/lttng-ctl/filter/filter-bytecode.h @@ -35,10 +35,17 @@ struct field_ref { uint16_t offset; } LTTNG_PACKED; -struct field_ref_index { - /* Initially, symbol offset. After link, field offset. */ +struct get_symbol { + /* Symbol offset. */ uint16_t offset; - uint64_t index; /* array index */ +} LTTNG_PACKED; + +struct get_index_u16 { + uint16_t index; +} LTTNG_PACKED; + +struct get_index_u64 { + uint64_t index; } LTTNG_PACKED; struct literal_numeric { @@ -66,9 +73,9 @@ enum filter_op { FILTER_OP_MINUS = 6, FILTER_OP_RSHIFT = 7, FILTER_OP_LSHIFT = 8, - FILTER_OP_BIN_AND = 9, - FILTER_OP_BIN_OR = 10, - FILTER_OP_BIN_XOR = 11, + FILTER_OP_BIT_AND = 9, + FILTER_OP_BIT_OR = 10, + FILTER_OP_BIT_XOR = 11, /* binary comparators */ FILTER_OP_EQ = 12, @@ -169,13 +176,30 @@ enum filter_op { FILTER_OP_EQ_STAR_GLOB_STRING = 77, FILTER_OP_NE_STAR_GLOB_STRING = 78, - /* load field ref with index */ - FILTER_OP_LOAD_FIELD_REF_INDEX = 79, - FILTER_OP_LOAD_FIELD_REF_INDEX_S64 = 80, - - /* get context ref with index */ - FILTER_OP_GET_CONTEXT_REF_INDEX = 81, - FILTER_OP_GET_CONTEXT_REF_INDEX_S64 = 82, + /* + * Instructions for recursive traversal through composed types. + */ + FILTER_OP_GET_CONTEXT_ROOT = 79, + FILTER_OP_GET_APP_CONTEXT_ROOT = 80, + FILTER_OP_GET_PAYLOAD_ROOT = 81, + + FILTER_OP_GET_SYMBOL = 82, + FILTER_OP_GET_SYMBOL_FIELD = 83, + FILTER_OP_GET_INDEX_U16 = 84, + FILTER_OP_GET_INDEX_U64 = 85, + + FILTER_OP_LOAD_FIELD = 86, + FILTER_OP_LOAD_FIELD_S8 = 87, + FILTER_OP_LOAD_FIELD_S16 = 88, + FILTER_OP_LOAD_FIELD_S32 = 89, + FILTER_OP_LOAD_FIELD_S64 = 90, + FILTER_OP_LOAD_FIELD_U8 = 91, + FILTER_OP_LOAD_FIELD_U16 = 92, + FILTER_OP_LOAD_FIELD_U32 = 93, + FILTER_OP_LOAD_FIELD_U64 = 94, + FILTER_OP_LOAD_FIELD_STRING = 95, + FILTER_OP_LOAD_FIELD_SEQUENCE = 96, + FILTER_OP_LOAD_FIELD_DOUBLE = 97, NR_FILTER_OPS, }; diff --git a/src/lib/lttng-ctl/filter/filter-grammar-test.c b/src/lib/lttng-ctl/filter/filter-grammar-test.c index 782154306..b5e6616f5 100644 --- a/src/lib/lttng-ctl/filter/filter-grammar-test.c +++ b/src/lib/lttng-ctl/filter/filter-grammar-test.c @@ -61,11 +61,6 @@ int main(int argc, char **argv) fprintf(stderr, "Parse error\n"); goto parse_error; } - ret = filter_visitor_set_parent(ctx); - if (ret) { - fprintf(stderr, "Set parent error\n"); - goto parse_error; - } if (print_xml) { ret = filter_visitor_print_xml(ctx, stdout, 0); if (ret) { diff --git a/src/lib/lttng-ctl/filter/filter-ir.h b/src/lib/lttng-ctl/filter/filter-ir.h index c07050df5..9d2079393 100644 --- a/src/lib/lttng-ctl/filter/filter-ir.h +++ b/src/lib/lttng-ctl/filter/filter-ir.h @@ -38,8 +38,7 @@ enum ir_data_type { IR_DATA_FLOAT, IR_DATA_FIELD_REF, IR_DATA_GET_CONTEXT_REF, - IR_DATA_FIELD_REF_INDEX, - IR_DATA_GET_CONTEXT_REF_INDEX, + IR_DATA_EXPRESSION, }; enum ir_op_type { @@ -73,6 +72,28 @@ struct ir_op_root { struct ir_op *child; }; +enum ir_load_expression_type { + IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT, + IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT, + IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT, + IR_LOAD_EXPRESSION_GET_SYMBOL, + IR_LOAD_EXPRESSION_GET_INDEX, + IR_LOAD_EXPRESSION_LOAD_FIELD, +}; + +struct ir_load_expression_op { + struct ir_load_expression_op *next; + enum ir_load_expression_type type; + union { + char *symbol; + uint64_t index; + } u; +}; + +struct ir_load_expression { + struct ir_load_expression_op *child; +}; + struct ir_op_load { union { struct { @@ -82,10 +103,7 @@ struct ir_op_load { int64_t num; double flt; char *ref; - struct { - char *symbol; - uint64_t index; - } ref_index; + struct ir_load_expression *expression; } u; }; diff --git a/src/lib/lttng-ctl/filter/filter-lexer.l b/src/lib/lttng-ctl/filter/filter-lexer.l index a45b6e838..8a6afff06 100644 --- a/src/lib/lttng-ctl/filter/filter-lexer.l +++ b/src/lib/lttng-ctl/filter/filter-lexer.l @@ -49,7 +49,7 @@ HEXDIGIT [0-9A-Fa-f] OCTALDIGIT [0-7] UCHARLOWERCASE \\u{HEXDIGIT}{4} UCHARUPPERCASE \\U{HEXDIGIT}{8} -ID_EXTRA_CHAR (":"|".") +ID_EXTRA_CHAR (":") ID_NONDIGIT {NONDIGIT}|{UCHARLOWERCASE}|{UCHARUPPERCASE}|{ID_EXTRA_CHAR} IDENTIFIER {ID_NONDIGIT}({ID_NONDIGIT}|{DIGIT})* ESCSEQ \\(\'|\"|\?|\\|a|b|f|n|r|t|v|{OCTALDIGIT}{1,3}|u{HEXDIGIT}{4}|U{HEXDIGIT}{8}|x{HEXDIGIT}+) diff --git a/src/lib/lttng-ctl/filter/filter-parser.y b/src/lib/lttng-ctl/filter/filter-parser.y index 12605cd38..7c4aebe8d 100644 --- a/src/lib/lttng-ctl/filter/filter-parser.y +++ b/src/lib/lttng-ctl/filter/filter-parser.y @@ -336,6 +336,8 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %type s_char s_char_sequence c_char c_char_sequence %type primary_expression +%type prefix_expression +%type prefix_expression_rec %type postfix_expression %type unary_expression %type unary_operator @@ -350,6 +352,7 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %type logical_and_expression %type logical_or_expression %type expression +%type identifiers %% @@ -390,21 +393,8 @@ s_char: } ; -primary_expression - : IDENTIFIER - { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_IDENTIFIER; - $$->u.expression.u.identifier = yylval.gs->s; - } - | GLOBAL_IDENTIFIER - { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER; - $$->u.expression.u.identifier = yylval.gs->s; - } - - | DECIMAL_CONSTANT +primary_expression: + DECIMAL_CONSTANT { $$ = make_node(parser_ctx, NODE_EXPRESSION); $$->u.expression.type = AST_EXP_CONSTANT; @@ -468,29 +458,62 @@ primary_expression } ; -postfix_expression - : primary_expression - { $$ = $1; } - | postfix_expression LSBRAC unary_expression RSBRAC +identifiers + : IDENTIFIER + { + $$ = make_node(parser_ctx, NODE_EXPRESSION); + $$->u.expression.type = AST_EXP_IDENTIFIER; + $$->u.expression.u.identifier = yylval.gs->s; + } + | GLOBAL_IDENTIFIER + { + $$ = make_node(parser_ctx, NODE_EXPRESSION); + $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER; + $$->u.expression.u.identifier = yylval.gs->s; + } + ; + +prefix_expression_rec + : LSBRAC unary_expression RSBRAC + { + $$ = $2; + } + | LSBRAC unary_expression RSBRAC prefix_expression_rec + { + $$ = $2; + $$->u.expression.pre_op = AST_LINK_BRACKET; + $$->u.expression.prev = $4; + } + ; + +prefix_expression + : identifiers + { + $$ = $1; + } + | identifiers prefix_expression_rec { $$ = $1; $$->u.expression.pre_op = AST_LINK_BRACKET; - $$->u.expression.next = $3; + $$->u.expression.next_bracket = $2; } - | postfix_expression DOT IDENTIFIER + ; + +postfix_expression + : prefix_expression { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_IDENTIFIER; + $$ = $1; + } + | postfix_expression DOT prefix_expression + { + $$ = $3; $$->u.expression.post_op = AST_LINK_DOT; - $$->u.expression.u.identifier = $3->s; $$->u.expression.prev = $1; } - | postfix_expression RARROW IDENTIFIER + | postfix_expression RARROW prefix_expression { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_IDENTIFIER; + $$ = $3; $$->u.expression.post_op = AST_LINK_RARROW; - $$->u.expression.u.identifier = $3->s; $$->u.expression.prev = $1; } ; @@ -498,6 +521,8 @@ postfix_expression unary_expression : postfix_expression { $$ = $1; } + | primary_expression + { $$ = $1; } | unary_operator unary_expression { $$ = $1; @@ -524,7 +549,7 @@ unary_operator | NOT_BIN { $$ = make_node(parser_ctx, NODE_UNARY_OP); - $$->u.unary_op.type = AST_UNARY_BIN_NOT; + $$->u.unary_op.type = AST_UNARY_BIT_NOT; } ; @@ -610,7 +635,7 @@ and_expression { $$ = $1; } | and_expression AND_BIN equality_expression { - $$ = make_op_node(parser_ctx, AST_OP_BIN_AND, $1, $3); + $$ = make_op_node(parser_ctx, AST_OP_BIT_AND, $1, $3); } ; @@ -619,7 +644,7 @@ exclusive_or_expression { $$ = $1; } | exclusive_or_expression XOR_BIN and_expression { - $$ = make_op_node(parser_ctx, AST_OP_BIN_XOR, $1, $3); + $$ = make_op_node(parser_ctx, AST_OP_BIT_XOR, $1, $3); } ; @@ -628,7 +653,7 @@ inclusive_or_expression { $$ = $1; } | inclusive_or_expression OR_BIN exclusive_or_expression { - $$ = make_op_node(parser_ctx, AST_OP_BIN_OR, $1, $3); + $$ = make_op_node(parser_ctx, AST_OP_BIT_OR, $1, $3); } ; 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 74cef91dc..34183ed2e 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c @@ -157,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) { @@ -239,107 +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_FIELD_REF_INDEX: /* fall-through */ - case IR_DATA_GET_CONTEXT_REF_INDEX: - { - struct load_op *insn; - uint32_t insn_len = sizeof(struct load_op) - + sizeof(struct field_ref_index); - struct field_ref_index ref_index_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_INDEX: - insn->op = FILTER_OP_LOAD_FIELD_REF_INDEX; - break; - case IR_DATA_GET_CONTEXT_REF_INDEX: - insn->op = FILTER_OP_GET_CONTEXT_REF_INDEX; - break; - default: - free(insn); - return -EINVAL; - } - ref_index_offset.offset = (uint16_t) -1U; - ref_index_offset.index = node->u.load.u.ref_index.index; - memcpy(insn->data, &ref_index_offset, sizeof(ref_index_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_index.symbol, - 1, strlen(node->u.load.u.ref_index.symbol) + 1); - free(insn); - return ret; - } + case IR_DATA_EXPRESSION: + return visit_node_load_expression(ctx, node); } } @@ -425,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: @@ -475,15 +537,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) /* 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_FIELD_REF_INDEX - || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) + || 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_FIELD_REF_INDEX - || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) { + || 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; @@ -518,15 +578,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node) /* 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_FIELD_REF_INDEX - || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) + || 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_FIELD_REF_INDEX - || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) { + || 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; diff --git a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c index 85aadcae6..cd7930ad5 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c @@ -58,6 +58,7 @@ struct ir_op *make_op_root(struct ir_op *child, enum ir_side side) case IR_DATA_NUMERIC: case IR_DATA_FIELD_REF: case IR_DATA_GET_CONTEXT_REF: + case IR_DATA_EXPRESSION: /* ok */ break; } @@ -140,99 +141,148 @@ struct ir_op *make_op_load_float(double v, enum ir_side side) } static -struct ir_op *make_op_load_field_ref(char *string, - enum ir_side side) +void free_load_expression(struct ir_load_expression *load_expression) { - struct ir_op *op; + struct ir_load_expression_op *exp_op; - op = calloc(sizeof(struct ir_op), 1); - if (!op) - return NULL; - op->op = IR_OP_LOAD; - op->data_type = IR_DATA_FIELD_REF; - op->signedness = IR_SIGN_DYN; - op->side = side; - op->u.load.u.ref = strdup(string); - if (!op->u.load.u.ref) { - goto error; - } - return op; + if (!load_expression) + return; + exp_op = load_expression->child; + for (;;) { + struct ir_load_expression_op *prev_exp_op; -error: - free(op); - return NULL; + if (!exp_op) + break; + switch (exp_op->type) { + case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT: + case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT: + case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT: + case IR_LOAD_EXPRESSION_GET_INDEX: + case IR_LOAD_EXPRESSION_LOAD_FIELD: + break; + case IR_LOAD_EXPRESSION_GET_SYMBOL: + free(exp_op->u.symbol); + break; + } + prev_exp_op = exp_op; + exp_op = exp_op->next; + free(prev_exp_op); + } + free(load_expression); } +/* + * Returns the first node of the chain, after initializing the next + * pointers. + */ static -struct ir_op *make_op_load_field_ref_index(char *string, - struct filter_node *next, - enum ir_side side) +struct filter_node *load_expression_get_forward_chain(struct filter_node *node) { - struct ir_op *op; + struct filter_node *prev_node; - op = calloc(sizeof(struct ir_op), 1); - if (!op) - return NULL; - op->op = IR_OP_LOAD; - op->data_type = IR_DATA_FIELD_REF_INDEX; - op->signedness = IR_SIGN_DYN; - op->side = side; - op->u.load.u.ref_index.symbol = strdup(string); - if (!op->u.load.u.ref_index.symbol) { - goto error; - } - /* Only positive integer literals accepted as index. */ - if (next->type == NODE_UNARY_OP) { - fprintf(stderr, "[error] Unexpected unary operator as index\n"); - goto error; - } - if (next->type != NODE_EXPRESSION) { - fprintf(stderr, "[error] Expecting expression as index\n"); - goto error; - } - if (next->u.expression.type != AST_EXP_CONSTANT) { - fprintf(stderr, "[error] Expecting constant index\n"); - goto error; - } - if (next->u.expression.u.constant < 0) { - fprintf(stderr, "[error] Expecting positive constant index\n"); - goto error; + for (;;) { + assert(node->type == NODE_EXPRESSION); + prev_node = node; + node = node->u.expression.prev; + if (!node) { + break; + } + node->u.expression.next = prev_node; } - op->u.load.u.ref_index.index = next->u.expression.u.constant; - return op; - -error: - free(op); - return NULL; + return prev_node; } static -struct ir_op *make_op_load_get_context_ref(char *string, - enum ir_side side) +struct ir_load_expression *create_load_expression(struct filter_node *node) { - struct ir_op *op; + struct ir_load_expression *load_exp; + struct ir_load_expression_op *load_exp_op, *prev_op; + char *str; - op = calloc(sizeof(struct ir_op), 1); - if (!op) + /* Get forward chain. */ + node = load_expression_get_forward_chain(node); + if (!node) return NULL; - op->op = IR_OP_LOAD; - op->data_type = IR_DATA_GET_CONTEXT_REF; - op->signedness = IR_SIGN_DYN; - op->side = side; - op->u.load.u.ref = strdup(string); - if (!op->u.load.u.ref) { + load_exp = calloc(sizeof(struct ir_load_expression), 1); + if (!load_exp) + return NULL; + + /* Root */ + load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1); + if (!load_exp_op) + goto error; + load_exp->child = load_exp_op; + str = node->u.expression.u.string; + if (!strcmp(str, "$ctx")) { + load_exp_op->type = IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT; + node = node->u.expression.next; + if (!node) { + fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str); + goto error; + } + str = node->u.expression.u.string; + } else if (!strcmp(str, "$app")) { + load_exp_op->type = IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT; + node = node->u.expression.next; + if (!node) { + fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str); + goto error; + } + str = node->u.expression.u.string; + } else if (str[0] == '$') { + fprintf(stderr, "[error] Unexpected identifier \'%s\'\n", str); goto error; + } else { + load_exp_op->type = IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT; + } + + for (;;) { + struct filter_node *bracket_node; + + prev_op = load_exp_op; + load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1); + if (!load_exp_op) + goto error; + prev_op->next = load_exp_op; + load_exp_op->type = IR_LOAD_EXPRESSION_GET_SYMBOL; + load_exp_op->u.symbol = strdup(str); + if (!load_exp_op->u.symbol) + goto error; + + /* Explore brackets from current node. */ + for (bracket_node = node->u.expression.next_bracket; + bracket_node != NULL; + bracket_node = bracket_node->u.expression.next_bracket) { + prev_op = load_exp_op; + load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1); + if (!load_exp_op) + goto error; + prev_op->next = load_exp_op; + load_exp_op->type = IR_LOAD_EXPRESSION_GET_INDEX; + load_exp_op->u.index = bracket_node->u.expression.u.constant; + } + /* Go to next chain element. */ + node = node->u.expression.next; + if (!node) + break; + str = node->u.expression.u.string; } - return op; + /* Add final load field */ + prev_op = load_exp_op; + load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1); + if (!load_exp_op) + goto error; + prev_op->next = load_exp_op; + load_exp_op->type = IR_LOAD_EXPRESSION_LOAD_FIELD; + return load_exp; error: - free(op); + free_load_expression(load_exp); return NULL; } static -struct ir_op *make_op_load_get_context_ref_index(char *string, - struct filter_node *next, +struct ir_op *make_op_load_expression(struct filter_node *node, enum ir_side side) { struct ir_op *op; @@ -241,34 +291,17 @@ struct ir_op *make_op_load_get_context_ref_index(char *string, if (!op) return NULL; op->op = IR_OP_LOAD; - op->data_type = IR_DATA_GET_CONTEXT_REF_INDEX; + op->data_type = IR_DATA_EXPRESSION; op->signedness = IR_SIGN_DYN; op->side = side; - op->u.load.u.ref_index.symbol = strdup(string); - if (!op->u.load.u.ref_index.symbol) { - goto error; - } - /* Only positive integer literals accepted as offset. */ - if (next->type == NODE_UNARY_OP) { - fprintf(stderr, "[error] Unexpected unary operator as index\n"); - goto error; - } - if (next->type != NODE_EXPRESSION) { - fprintf(stderr, "[error] Expecting expression as index\n"); - goto error; - } - if (next->u.expression.type != AST_EXP_CONSTANT) { - fprintf(stderr, "[error] Expecting constant index\n"); - goto error; - } - if (next->u.expression.u.constant < 0) { - fprintf(stderr, "[error] Expecting positive constant index\n"); + op->u.load.u.expression = create_load_expression(node); + if (!op->u.load.u.expression) { goto error; } - op->u.load.u.ref_index.index = next->u.expression.u.constant; return op; error: + free_load_expression(op->u.load.u.expression); free(op); return NULL; } @@ -447,6 +480,50 @@ error: return NULL; } +static +struct ir_op *make_op_binary_bitwise(enum op_type bin_op_type, + const char *op_str, struct ir_op *left, struct ir_op *right, + enum ir_side side) +{ + struct ir_op *op = NULL; + + if (left->data_type == IR_DATA_UNKNOWN + || right->data_type == IR_DATA_UNKNOWN) { + fprintf(stderr, "[error] bitwise binary operation '%s' has unknown operand type\n", op_str); + goto error; + + } + if (left->data_type == IR_DATA_STRING + || right->data_type == IR_DATA_STRING) { + fprintf(stderr, "[error] bitwise binary operation '%s' cannot have string operand\n", op_str); + goto error; + } + if (left->data_type == IR_DATA_FLOAT + || right->data_type == IR_DATA_FLOAT) { + fprintf(stderr, "[error] bitwise binary operation '%s' cannot have floating point operand\n", op_str); + goto error; + } + + op = calloc(sizeof(struct ir_op), 1); + if (!op) + return NULL; + op->op = IR_OP_BINARY; + op->u.binary.type = bin_op_type; + op->u.binary.left = left; + op->u.binary.right = right; + + /* we return a signed numeric */ + op->data_type = IR_DATA_NUMERIC; + op->signedness = IR_SIGNED; + op->side = side; + + return op; + +error: + free(op); + return NULL; +} + static struct ir_op *make_op_binary_logical_and(struct ir_op *left, struct ir_op *right, enum ir_side side) @@ -461,6 +538,27 @@ struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right, return make_op_binary_logical(AST_OP_OR, "||", left, right, side); } +static +struct ir_op *make_op_binary_bitwise_and(struct ir_op *left, struct ir_op *right, + enum ir_side side) +{ + return make_op_binary_bitwise(AST_OP_BIT_AND, "&", left, right, side); +} + +static +struct ir_op *make_op_binary_bitwise_or(struct ir_op *left, struct ir_op *right, + enum ir_side side) +{ + return make_op_binary_bitwise(AST_OP_BIT_OR, "|", left, right, side); +} + +static +struct ir_op *make_op_binary_bitwise_xor(struct ir_op *left, struct ir_op *right, + enum ir_side side) +{ + return make_op_binary_bitwise(AST_OP_BIT_XOR, "^", left, right, side); +} + static void filter_free_ir_recursive(struct ir_op *op) { @@ -484,10 +582,8 @@ void filter_free_ir_recursive(struct ir_op *op) case IR_DATA_GET_CONTEXT_REF: free(op->u.load.u.ref); break; - case IR_DATA_FIELD_REF_INDEX: /* fall-through */ - case IR_DATA_GET_CONTEXT_REF_INDEX: - free(op->u.load.u.ref_index.symbol); - break; + case IR_DATA_EXPRESSION: + free_load_expression(op->u.load.u.expression); default: break; } @@ -526,57 +622,8 @@ struct ir_op *make_expression(struct filter_parser_ctx *ctx, return make_op_load_float(node->u.expression.u.float_constant, side); case AST_EXP_IDENTIFIER: - switch (node->u.expression.pre_op) { - case AST_LINK_UNKNOWN: - return make_op_load_field_ref(node->u.expression.u.identifier, - side); - case AST_LINK_BRACKET: - return make_op_load_field_ref_index(node->u.expression.u.identifier, - node->u.expression.next, - side); - default: - fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__); - return NULL; - } case AST_EXP_GLOBAL_IDENTIFIER: - { - const char *name; - - /* - * We currently only support $ctx (context) and $app - * identifiers. - */ - if (strncmp(node->u.expression.u.identifier, - "$ctx.", strlen("$ctx.")) != 0 - && strncmp(node->u.expression.u.identifier, - "$app.", strlen("$app.")) != 0) { - fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__, node->u.expression.u.identifier); - return NULL; - } - name = strchr(node->u.expression.u.identifier, '.'); - if (!name) { - fprintf(stderr, "[error] %s: Expecting '.'\n", __func__); - return NULL; - } - name++; /* Skip . */ - if (!strlen(name)) { - fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__); - return NULL; - } - switch (node->u.expression.pre_op) { - case AST_LINK_UNKNOWN: - return make_op_load_get_context_ref(node->u.expression.u.identifier, - side); - case AST_LINK_BRACKET: - return make_op_load_get_context_ref_index(node->u.expression.u.identifier, - node->u.expression.next, - side); - default: - fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__); - return NULL; - } - - } + return make_op_load_expression(node, side); case AST_EXP_NESTED: return generate_ir_recursive(ctx, node->u.expression.u.child, side); @@ -597,10 +644,8 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx, return NULL; /* - * Binary operators other than comparators and logical and/or - * are not supported. If we ever want to support those, we will - * need a stack for the general case rather than just 2 - * registers (see bytecode). + * The following binary operators other than comparators and + * logical and/or are not supported yet. */ case AST_OP_MUL: op_str = "*"; @@ -623,15 +668,19 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx, case AST_OP_LSHIFT: op_str = "<<"; goto error_not_supported; - case AST_OP_BIN_AND: - op_str = "&"; - goto error_not_supported; - case AST_OP_BIN_OR: - op_str = "|"; - goto error_not_supported; - case AST_OP_BIN_XOR: - op_str = "^"; - goto error_not_supported; + + case AST_OP_BIT_AND: + case AST_OP_BIT_OR: + case AST_OP_BIT_XOR: + lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT); + if (!lchild) + return NULL; + rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_RIGHT); + if (!rchild) { + filter_free_ir_recursive(lchild); + return NULL; + } + break; case AST_OP_EQ: case AST_OP_NE: @@ -691,6 +740,15 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx, case AST_OP_LE: op = make_op_binary_le(lchild, rchild, side); break; + case AST_OP_BIT_AND: + op = make_op_binary_bitwise_and(lchild, rchild, side); + break; + case AST_OP_BIT_OR: + op = make_op_binary_bitwise_or(lchild, rchild, side); + break; + case AST_OP_BIT_XOR: + op = make_op_binary_bitwise_xor(lchild, rchild, side); + break; default: break; } @@ -764,7 +822,7 @@ struct ir_op *make_unary_op(struct filter_parser_ctx *ctx, } return op; } - case AST_UNARY_BIN_NOT: + case AST_UNARY_BIT_NOT: { op_str = "~"; goto error_not_supported; diff --git a/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c b/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c index e093957c2..aa3edd592 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c @@ -53,10 +53,6 @@ int check_bin_op_nesting_recursive(struct ir_op *node, int nesting) { int ret; - if (nesting > 0) { - fprintf(stderr, "[error] Nesting of binary operators is not allowed, except for logical operators.\n"); - return -EINVAL; - } ret = check_bin_op_nesting_recursive(node->u.binary.left, nesting + 1); if (ret) diff --git a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c b/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c deleted file mode 100644 index 458688da4..000000000 --- a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * filter-visitor-set-parent.c - * - * LTTng filter set parent visitor - * - * Copyright 2012 - Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License, version 2.1 only, - * as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include "filter-ast.h" -#include "filter-parser.h" - -#include - -static -int update_child(struct filter_node *parent, - struct filter_node *old_child, - struct filter_node *new_child) -{ - if (!parent) { - fprintf(stderr, "[error] %s: NULL parent\n", __func__); - return -EINVAL; - } - - switch (parent->type) { - case NODE_UNKNOWN: - default: - fprintf(stderr, "[error] %s: unknown node type\n", __func__); - return -EINVAL; - case NODE_ROOT: - assert(parent->u.root.child == old_child); - parent->u.root.child = new_child; - break; - case NODE_EXPRESSION: - assert(parent->u.expression.type == AST_EXP_NESTED); - assert(parent->u.expression.u.child == old_child); - parent->u.expression.u.child = new_child; - break; - case NODE_OP: - assert(parent->u.op.lchild == old_child || - parent->u.op.rchild == old_child); - if (parent->u.op.lchild == old_child) - parent->u.op.lchild = new_child; - else - parent->u.op.rchild = new_child; - break; - case NODE_UNARY_OP: - assert(parent->u.unary_op.child == old_child); - parent->u.unary_op.child = new_child; - break; - } - return 0; -} - -static -int recursive_visit_set_parent(struct filter_node *node, - struct filter_node *parent) -{ - int ret; - - if (!node) { - fprintf(stderr, "[error] %s: NULL child\n", __func__); - return -EINVAL; - } - node->parent = parent; - switch (node->type) { - case NODE_UNKNOWN: - default: - fprintf(stderr, "[error] %s: unknown node type\n", __func__); - return -EINVAL; - case NODE_ROOT: - assert(parent == NULL); - return recursive_visit_set_parent(node->u.root.child, node); - case NODE_EXPRESSION: - switch (node->u.expression.type) { - case AST_EXP_UNKNOWN: - default: - fprintf(stderr, "[error] %s: unknown expression type\n", __func__); - return -EINVAL; - case AST_EXP_NESTED: - return recursive_visit_set_parent(node->u.expression.u.child, node); - case AST_EXP_IDENTIFIER: /* fall-through */ - case AST_EXP_GLOBAL_IDENTIFIER: - { - struct filter_node *orig_node = node; - - while (node->u.expression.prev) { - struct filter_node *prev; - - prev = node->u.expression.prev; - if (prev->type != NODE_EXPRESSION || - (prev->u.expression.type != AST_EXP_IDENTIFIER - && prev->u.expression.type != AST_EXP_GLOBAL_IDENTIFIER)) { - fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__); - return -EINVAL; - } - - prev->u.expression.next = node; - prev->u.expression.pre_op = - node->u.expression.post_op; - prev->parent = node->parent; - node = prev; - } - /* Set first child as forward */ - ret = update_child(parent, orig_node, node); - if (ret) - return ret; - } - case AST_EXP_CONSTANT: - case AST_EXP_FLOAT_CONSTANT: - case AST_EXP_STRING: - break; - } - break; - case NODE_OP: - ret = recursive_visit_set_parent(node->u.op.lchild, node); - if (ret) - return ret; - return recursive_visit_set_parent(node->u.op.rchild, node); - case NODE_UNARY_OP: - return recursive_visit_set_parent(node->u.unary_op.child, node); - } - return 0; -} - -LTTNG_HIDDEN -int filter_visitor_set_parent(struct filter_parser_ctx *ctx) -{ - return recursive_visit_set_parent(&ctx->ast->root, NULL); -} diff --git a/src/lib/lttng-ctl/filter/filter-visitor-xml.c b/src/lib/lttng-ctl/filter/filter-visitor-xml.c index c293ad15e..1e5812015 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-xml.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-xml.c @@ -169,13 +169,13 @@ int recursive_visit_print(struct filter_node *node, FILE *stream, int indent) case AST_OP_OR: fprintf(stream, "\"||\""); break; - case AST_OP_BIN_AND: + case AST_OP_BIT_AND: fprintf(stream, "\"&\""); break; - case AST_OP_BIN_OR: + case AST_OP_BIT_OR: fprintf(stream, "\"|\""); break; - case AST_OP_BIN_XOR: + case AST_OP_BIT_XOR: fprintf(stream, "\"^\""); break; @@ -227,7 +227,7 @@ int recursive_visit_print(struct filter_node *node, FILE *stream, int indent) case AST_UNARY_NOT: fprintf(stream, "\"!\""); break; - case AST_UNARY_BIN_NOT: + case AST_UNARY_BIT_NOT: fprintf(stream, "\"~\""); break; } diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 0468b6746..8ca8e46ef 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -887,12 +887,6 @@ static int generate_filter(char *filter_expression, ret = -LTTNG_ERR_FILTER_INVAL; goto parse_error; } - ret = filter_visitor_set_parent(ctx); - if (ret) { - fprintf(stderr, "Set parent error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } if (print_xml) { ret = filter_visitor_print_xml(ctx, stdout, 0); if (ret) { diff --git a/tests/regression/tools/filtering/gen-ust-events.c b/tests/regression/tools/filtering/gen-ust-events.c index c789c89d4..91360afb9 100644 --- a/tests/regression/tools/filtering/gen-ust-events.c +++ b/tests/regression/tools/filtering/gen-ust-events.c @@ -32,6 +32,7 @@ int main(int argc, char **argv) { int i, netint; long values[] = { 1, 2, 3 }; + uint32_t net_values[] = { 1, 2, 3 }; char text[10] = "test"; char escape[10] = "\\*"; double dbl = 2.0; @@ -49,9 +50,14 @@ int main(int argc, char **argv) nr_usec = atoi(argv[2]); } + for (i = 0; i < 3; i++) { + net_values[i] = htonl(net_values[i]); + } + for (i = 0; i < nr_iter; i++) { netint = htonl(i); - tracepoint(tp, tptest, i, netint, values, text, strlen(text), escape, dbl, flt); + tracepoint(tp, tptest, i, netint, values, text, strlen(text), escape, dbl, flt, + net_values); usleep(nr_usec); } diff --git a/tests/regression/tools/filtering/test_invalid_filter b/tests/regression/tools/filtering/test_invalid_filter index 68bbdc18c..2c45ee09e 100755 --- a/tests/regression/tools/filtering/test_invalid_filter +++ b/tests/regression/tools/filtering/test_invalid_filter @@ -25,8 +25,8 @@ EVENT_NAME="bogus" ENABLE_EVENT_STDERR="/tmp/invalid-filters-stderr" TRACE_PATH=$(mktemp -d) NUM_GLOBAL_TESTS=2 -NUM_UST_TESTS=165 -NUM_KERNEL_TESTS=165 +NUM_UST_TESTS=144 +NUM_KERNEL_TESTS=144 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS)) source $TESTDIR/utils/utils.sh @@ -103,9 +103,6 @@ INVALID_FILTERS=( "intfield-1" "intfield>>1" "intfield<<1" - "intfield&1" - "intfield|1" - "intfield^1" "~intfield" "1+11111-3333+1" "(1+2)*(55*666)" @@ -120,9 +117,7 @@ INVALID_FILTERS=( '0 || ("abc" != "def")) && (3 < 4)' "a->" "a-->a" - "a->a" "a.b.c->d.e.f+1" - "asdfasdf->asdfasdf < 2" # String can\'t be root node "\"somestring\"" # Unary op on string not allowed @@ -135,9 +130,6 @@ INVALID_FILTERS=( # Logical operator with string type not allowed "\"somestring\" || 1" "1 || \"somestring\"" - # Nesting of binary operator not allowed - "1 | (1 | (1 | 1))" - "1 > (1 > (1 > 1))" "\$ctx == 0" "0 == \$ctx" # Only \$ctx is supported for now diff --git a/tests/regression/tools/filtering/test_unsupported_op b/tests/regression/tools/filtering/test_unsupported_op index 985f14e14..7395da0dd 100755 --- a/tests/regression/tools/filtering/test_unsupported_op +++ b/tests/regression/tools/filtering/test_unsupported_op @@ -25,8 +25,8 @@ EVENT_NAME="bogus" ENABLE_EVENT_STDERR="/tmp/unsupported-ops-enable" TRACE_PATH=$(mktemp -d) NUM_GLOBAL_TESTS=2 -NUM_UST_TESTS=44 -NUM_KERNEL_TESTS=44 +NUM_UST_TESTS=32 +NUM_KERNEL_TESTS=32 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS)) source $TESTDIR/utils/utils.sh @@ -94,9 +94,9 @@ print_test_banner "$TEST_DESC" # Unsupported operators OP_STR=("MUL" "DIV" "MOD" "PLUS" "MINUS" "LSHIFT" "RSHIFT" - "BIN_AND" "BIN_OR" "BIN_XOR" "UNARY_BIN_NOT") + "UNARY_BIN_NOT") -OP_TKN=("*" "/" "%" "+" "-" "<<" ">>" "&" "|" "^" "~") +OP_TKN=("*" "/" "%" "+" "-" "<<" ">>" "~") OP_COUNT=${#OP_STR[@]} diff --git a/tests/regression/tools/filtering/test_valid_filter b/tests/regression/tools/filtering/test_valid_filter index a425a2972..a916b1884 100755 --- a/tests/regression/tools/filtering/test_valid_filter +++ b/tests/regression/tools/filtering/test_valid_filter @@ -24,8 +24,8 @@ STATS_BIN="$TESTDIR/utils/babelstats.pl" SESSION_NAME="valid_filter" NR_ITER=100 NUM_GLOBAL_TESTS=2 -NUM_UST_TESTS=906 -NUM_KERNEL_TESTS=840 +NUM_UST_TESTS=1002 +NUM_KERNEL_TESTS=936 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS)) source $TESTDIR/utils/utils.sh @@ -643,6 +643,60 @@ UST_FILTERS=( intfield $issue_356_filter + true_statement + "1&1" + + true_statement + "0|1" + + true_statement + "0^1" + + true_statement + "seqfield4[1]==2" + + true_statement + "arrfield1[1]==2" + + true_statement + "arrfield1[1]==2" + + true_statement + "arrfield3[1]==2" + + true_statement + "seqfield3[1]==2" + + true_statement + "1 | (1 | (1 | 1))" + + true_statement + "1 >= (1 >= (1 >= 1))" + + true_statement + "0x101 & 0x100 == 0x100" + + true_statement + "0x101 | 0x10100 == 0x10101" + + true_statement + "0xF00F0F ^ 0xFF0F00 == 0x0F000F" + + true_statement + "arrfield1[2] & 1 == 1" + + true_statement + "arrfield1[2] | 0x111000 == 0x111003" + + true_statement + "(arrfield1[0] | arrfield1[1] | arrfield1[2]) == 0x3" + + true_statement + "seqfield4[2] & 1 == 1" + + true_statement + "seqfield4[2] | 0x111000 == 0x111003" + true_statement "intfield < 0xDEADBEEF" @@ -736,12 +790,6 @@ UST_FILTERS=( has_no_event "0 == \$ctx.vtid.blah" - has_no_event - "\$ctx.44 == 0" - - has_no_event - "0 == \$ctx.44" - END ) @@ -1020,6 +1068,60 @@ KERNEL_FILTERS=( intfield $issue_356_filter + true_statement + "1&1" + + true_statement + "0|1" + + true_statement + "0^1" + + true_statement + "seqfield4[1]==2" + + true_statement + "arrfield1[1]==2" + + true_statement + "arrfield1[1]==2" + + true_statement + "arrfield3[1]==2" + + true_statement + "seqfield3[1]==2" + + true_statement + "1 | (1 | (1 | 1))" + + true_statement + "1 >= (1 >= (1 >= 1))" + + true_statement + "0x101 & 0x100 == 0x100" + + true_statement + "0x101 | 0x10100 == 0x10101" + + true_statement + "0xF00F0F ^ 0xFF0F00 == 0x0F000F" + + true_statement + "arrfield1[2] & 1 == 1" + + true_statement + "arrfield1[2] | 0x111000 == 0x111003" + + true_statement + "(arrfield1[0] | arrfield1[1] | arrfield1[2]) == 0x3" + + true_statement + "seqfield4[2] & 1 == 1" + + true_statement + "seqfield4[2] | 0x111000 == 0x111003" + true_statement "intfield < 0xDEADBEEF" @@ -1113,12 +1215,6 @@ KERNEL_FILTERS=( has_no_event "0 == \$ctx.vtid.blah" - has_no_event - "\$ctx.44 == 0" - - has_no_event - "0 == \$ctx.44" - stringfield_has_events 'stringfield == "test"' diff --git a/tests/regression/tools/filtering/tp.h b/tests/regression/tools/filtering/tp.h index dde56afbb..287260189 100644 --- a/tests/regression/tools/filtering/tp.h +++ b/tests/regression/tools/filtering/tp.h @@ -22,7 +22,8 @@ TRACEPOINT_EVENT(tp, tptest, TP_ARGS(int, anint, int, netint, long *, values, char *, text, size_t, textlen, - char *, etext, double, doublearg, float, floatarg), + char *, etext, double, doublearg, float, floatarg, + uint32_t *, net_values), TP_FIELDS( ctf_integer(int, intfield, anint) ctf_integer_hex(int, intfield2, anint) @@ -31,8 +32,11 @@ TRACEPOINT_EVENT(tp, tptest, ctf_integer_network_hex(int, netintfieldhex, netint) ctf_array(long, arrfield1, values, 3) ctf_array_text(char, arrfield2, text, 10) + ctf_array_network(uint32_t, arrfield3, net_values, 3) ctf_sequence(char, seqfield1, text, size_t, textlen) ctf_sequence_text(char, seqfield2, text, size_t, textlen) + ctf_sequence_network(uint32_t, seqfield3, net_values, size_t, 3) + ctf_sequence(long, seqfield4, values, size_t, 3) ctf_string(stringfield, text) ctf_string(stringfield2, etext) ctf_float(float, floatfield, floatarg) -- 2.34.1