From 586dc72f727912b4aa381789c418e062bce89d08 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 25 Mar 2013 22:33:57 -0400 Subject: [PATCH] Implement per-context filtering Signed-off-by: Mathieu Desnoyers --- src/lib/lttng-ctl/filter/filter-ast.h | 1 + src/lib/lttng-ctl/filter/filter-bytecode.h | 9 ++- src/lib/lttng-ctl/filter/filter-ir.h | 1 + src/lib/lttng-ctl/filter/filter-lexer.l | 1 + src/lib/lttng-ctl/filter/filter-parser.y | 9 ++- .../filter/filter-visitor-generate-bytecode.c | 26 ++++++-- .../filter/filter-visitor-generate-ir.c | 61 ++++++++++++++++++- .../filter/filter-visitor-set-parent.c | 6 +- src/lib/lttng-ctl/filter/filter-visitor-xml.c | 7 ++- 9 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/lib/lttng-ctl/filter/filter-ast.h b/src/lib/lttng-ctl/filter/filter-ast.h index 176716474..4fb60d0b2 100644 --- a/src/lib/lttng-ctl/filter/filter-ast.h +++ b/src/lib/lttng-ctl/filter/filter-ast.h @@ -121,6 +121,7 @@ struct filter_node { AST_EXP_CONSTANT, AST_EXP_FLOAT_CONSTANT, AST_EXP_IDENTIFIER, + AST_EXP_GLOBAL_IDENTIFIER, AST_EXP_NESTED, } type; enum ast_link_type post_op; /* reverse */ diff --git a/src/lib/lttng-ctl/filter/filter-bytecode.h b/src/lib/lttng-ctl/filter/filter-bytecode.h index 786174484..b9991284f 100644 --- a/src/lib/lttng-ctl/filter/filter-bytecode.h +++ b/src/lib/lttng-ctl/filter/filter-bytecode.h @@ -126,13 +126,14 @@ enum filter_op { FILTER_OP_AND = 57, FILTER_OP_OR = 58, - /* load */ + /* load field ref */ FILTER_OP_LOAD_FIELD_REF = 59, FILTER_OP_LOAD_FIELD_REF_STRING = 60, FILTER_OP_LOAD_FIELD_REF_SEQUENCE = 61, FILTER_OP_LOAD_FIELD_REF_S64 = 62, FILTER_OP_LOAD_FIELD_REF_DOUBLE = 63, + /* load immediate from operand */ FILTER_OP_LOAD_STRING = 64, FILTER_OP_LOAD_S64 = 65, FILTER_OP_LOAD_DOUBLE = 66, @@ -142,6 +143,12 @@ enum filter_op { FILTER_OP_CAST_DOUBLE_TO_S64 = 68, FILTER_OP_CAST_NOP = 69, + /* get context ref */ + FILTER_OP_GET_CONTEXT_REF = 70, + FILTER_OP_GET_CONTEXT_REF_STRING = 71, + FILTER_OP_GET_CONTEXT_REF_S64 = 72, + FILTER_OP_GET_CONTEXT_REF_DOUBLE = 73, + NR_FILTER_OPS, }; diff --git a/src/lib/lttng-ctl/filter/filter-ir.h b/src/lib/lttng-ctl/filter/filter-ir.h index 39ac76c41..5c3fa4ab5 100644 --- a/src/lib/lttng-ctl/filter/filter-ir.h +++ b/src/lib/lttng-ctl/filter/filter-ir.h @@ -37,6 +37,7 @@ enum ir_data_type { IR_DATA_NUMERIC, /* numeric and boolean */ IR_DATA_FLOAT, IR_DATA_FIELD_REF, + IR_DATA_GET_CONTEXT_REF, }; enum ir_op_type { diff --git a/src/lib/lttng-ctl/filter/filter-lexer.l b/src/lib/lttng-ctl/filter/filter-lexer.l index de74e7a09..ab887f74c 100644 --- a/src/lib/lttng-ctl/filter/filter-lexer.l +++ b/src/lib/lttng-ctl/filter/filter-lexer.l @@ -130,6 +130,7 @@ L\" BEGIN(string_lit); return STRING_LITERAL_START; "&" return AND_BIN; "|" return OR_BIN; "~" return NOT_BIN; +"$"{IDENTIFIER} printf_debug("\n", yytext); setstring(yyextra, yylval, yytext); return GLOBAL_IDENTIFIER; {IDENTIFIER} printf_debug("\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER; [ \t\n]+ ; /* ignore */ . return ERROR; diff --git a/src/lib/lttng-ctl/filter/filter-parser.y b/src/lib/lttng-ctl/filter/filter-parser.y index 6250054a0..3f301340d 100644 --- a/src/lib/lttng-ctl/filter/filter-parser.y +++ b/src/lib/lttng-ctl/filter/filter-parser.y @@ -313,7 +313,7 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %token ASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA %token XOR_BIN AND_BIN OR_BIN NOT_BIN -%token IDENTIFIER +%token IDENTIFIER GLOBAL_IDENTIFIER %token ERROR %union { @@ -387,6 +387,13 @@ primary_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 { $$ = make_node(parser_ctx, NODE_EXPRESSION); 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 898072227..785c1135e 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c @@ -242,7 +242,8 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) 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) @@ -254,7 +255,16 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node) 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: + return -EINVAL; + } ref_offset.offset = (uint16_t) -1U; memcpy(insn->data, &ref_offset, sizeof(ref_offset)); /* reloc_offset points to struct load_op */ @@ -414,11 +424,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; @@ -451,11 +463,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; 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 e1cab3468..1458cc728 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c @@ -56,6 +56,7 @@ struct ir_op *make_op_root(struct ir_op *child, enum ir_side side) return NULL; case IR_DATA_NUMERIC: case IR_DATA_FIELD_REF: + case IR_DATA_GET_CONTEXT_REF: /* ok */ break; } @@ -140,6 +141,26 @@ struct ir_op *make_op_load_field_ref(char *string, enum ir_side side) return op; } +static +struct ir_op *make_op_load_get_context_ref(char *string, enum ir_side side) +{ + struct ir_op *op; + + op = calloc(sizeof(struct ir_op), 1); + if (!op) + 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) { + free(op); + return NULL; + } + return op; +} + static struct ir_op *make_op_unary(enum unary_op_type unary_op_type, const char *op_str, enum ir_op_signedness signedness, @@ -224,7 +245,8 @@ struct ir_op *make_op_binary_numeric(enum op_type bin_op_type, /* * The field that is not a field ref will select type. */ - if (left->data_type != IR_DATA_FIELD_REF) + if (left->data_type != IR_DATA_FIELD_REF + && left->data_type != IR_DATA_GET_CONTEXT_REF) op->data_type = left->data_type; else op->data_type = right->data_type; @@ -475,7 +497,8 @@ void filter_free_ir_recursive(struct ir_op *op) case IR_DATA_STRING: free(op->u.load.u.string); break; - case IR_DATA_FIELD_REF: + case IR_DATA_FIELD_REF: /* fall-through */ + case IR_DATA_GET_CONTEXT_REF: free(op->u.load.u.ref); break; default: @@ -522,6 +545,40 @@ struct ir_op *make_expression(struct filter_parser_ctx *ctx, } return make_op_load_field_ref(node->u.expression.u.identifier, side); + case AST_EXP_GLOBAL_IDENTIFIER: + { + struct filter_node *next; + + if (node->u.expression.pre_op == AST_LINK_UNKNOWN) { + fprintf(stderr, "[error] %s: global identifiers need chained identifier \n", __func__); + return NULL; + } + /* We currently only support $ctx (context) identifiers */ + if (strncmp(node->u.expression.u.identifier, + "$ctx", strlen("$ctx")) != 0) { + fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" currently implemented.\n", __func__, node->u.expression.u.identifier); + return NULL; + } + next = node->u.expression.next; + if (!next) { + fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__); + return NULL; + } + if (next->type != NODE_EXPRESSION) { + fprintf(stderr, "[error] %s: Expecting expression.\n", __func__); + return NULL; + } + if (next->u.expression.type != AST_EXP_IDENTIFIER) { + fprintf(stderr, "[error] %s: Expecting identifier.\n", __func__); + return NULL; + } + if (next->u.expression.pre_op != AST_LINK_UNKNOWN) { + fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported after identifier\n", __func__); + return NULL; + } + return make_op_load_get_context_ref(next->u.expression.u.identifier, + side); + } case AST_EXP_NESTED: return generate_ir_recursive(ctx, node->u.expression.u.child, side); diff --git a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c b/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c index bd5e5a343..91c89dccb 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c @@ -93,7 +93,8 @@ int recursive_visit_set_parent(struct filter_node *node, return -EINVAL; case AST_EXP_NESTED: return recursive_visit_set_parent(node->u.expression.u.child, node); - case AST_EXP_IDENTIFIER: + case AST_EXP_IDENTIFIER: /* fall-through */ + case AST_EXP_GLOBAL_IDENTIFIER: { struct filter_node *orig_node = node; @@ -102,7 +103,8 @@ int recursive_visit_set_parent(struct filter_node *node, prev = node->u.expression.prev; if (prev->type != NODE_EXPRESSION || - prev->u.expression.type != AST_EXP_IDENTIFIER) { + (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; } diff --git a/src/lib/lttng-ctl/filter/filter-visitor-xml.c b/src/lib/lttng-ctl/filter/filter-visitor-xml.c index d27a3bf0e..24d618ac9 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-xml.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-xml.c @@ -73,9 +73,12 @@ int recursive_visit_print_expression(struct filter_node *node, fprintf(stream, "\n", node->u.expression.u.float_constant); break; - case AST_EXP_IDENTIFIER: + case AST_EXP_IDENTIFIER: /* fall-through */ + case AST_EXP_GLOBAL_IDENTIFIER: print_tabs(stream, indent); - fprintf(stream, "\n", + fprintf(stream, "<%s value=\"%s\"/>\n", + node->u.expression.type == AST_EXP_IDENTIFIER ? + "identifier" : "global_identifier", node->u.expression.u.identifier); while (node->u.expression.next) { print_tabs(stream, indent); -- 2.34.1