Implement per-context filtering
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 26 Mar 2013 02:33:57 +0000 (22:33 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 27 Mar 2013 17:34:52 +0000 (13:34 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
src/lib/lttng-ctl/filter/filter-ast.h
src/lib/lttng-ctl/filter/filter-bytecode.h
src/lib/lttng-ctl/filter/filter-ir.h
src/lib/lttng-ctl/filter/filter-lexer.l
src/lib/lttng-ctl/filter/filter-parser.y
src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c
src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c
src/lib/lttng-ctl/filter/filter-visitor-set-parent.c
src/lib/lttng-ctl/filter/filter-visitor-xml.c

index 176716474c850b297a6858d31aded176422f8e55..4fb60d0b264b7a175bf340ad7cb33ef3f2bd9f4c 100644 (file)
@@ -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 */
index 786174484d509d1f432ddeca902c45be59420740..b9991284f636c3c0f82af1e9f7863fedacd2bd74 100644 (file)
@@ -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,
 };
 
index 39ac76c4174c53beca08bd21cd126a3298e66726..5c3fa4ab52f97332095bc9923fde9c1c188a0771 100644 (file)
@@ -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 {
index de74e7a09715c11206d207b519f3c3e0dfcc53c0..ab887f74c285c0485b962089862bd39d4f5302c1 100644 (file)
@@ -130,6 +130,7 @@ L\"                         BEGIN(string_lit); return STRING_LITERAL_START;
 "&"                            return AND_BIN;
 "|"                            return OR_BIN;
 "~"                            return NOT_BIN;
+"$"{IDENTIFIER}                        printf_debug("<GLOBAL_IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return GLOBAL_IDENTIFIER;
 {IDENTIFIER}                   printf_debug("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER;
 [ \t\n]+                       ; /* ignore */
 .                              return ERROR;
index 6250054a0eb788a59f7dbffe42bf9e32d0f9ffa4..3f301340dbb4ccff7150d9ce79d4d86046d07563 100644 (file)
@@ -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 <gs> IDENTIFIER
+%token <gs> 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);
index 898072227775b2e568d5c7a90033e0403958753a..785c1135ef6b4606bdcb76c960a7611b4b142c28 100644 (file)
@@ -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;
index e1cab3468686691ecae04fbd680bf7bf4f174182..1458cc72857dc2eb4378603d0fe6c180e4108537 100644 (file)
@@ -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);
index bd5e5a343cc884a9c7ff4c8223489cf4b23416fd..91c89dccb81b633463a0169d18af0d187530b25d 100644 (file)
@@ -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;
                                        }
index d27a3bf0ee50f65f95871145dd339f3180842160..24d618ac9b45920cdb02393d26ae87f4bd45aaab 100644 (file)
@@ -73,9 +73,12 @@ int recursive_visit_print_expression(struct filter_node *node,
                fprintf(stream, "<float_constant value=\"%lg\"/>\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, "<identifier value=\"%s\"/>\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);
This page took 0.030149 seconds and 4 git commands to generate.