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 \
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,
AST_UNARY_PLUS,
AST_UNARY_MINUS,
AST_UNARY_NOT,
- AST_UNARY_BIN_NOT,
+ AST_UNARY_BIT_NOT,
};
enum ast_link_type {
*/
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;
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);
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 {
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,
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,
};
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) {
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 {
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 {
int64_t num;
double flt;
char *ref;
- struct {
- char *symbol;
- uint64_t index;
- } ref_index;
+ struct ir_load_expression *expression;
} u;
};
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}+)
%type <gs> s_char s_char_sequence c_char c_char_sequence
%type <n> primary_expression
+%type <n> prefix_expression
+%type <n> prefix_expression_rec
%type <n> postfix_expression
%type <n> unary_expression
%type <n> unary_operator
%type <n> logical_and_expression
%type <n> logical_or_expression
%type <n> expression
+%type <n> identifiers
%%
}
;
-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;
}
;
-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;
}
;
unary_expression
: postfix_expression
{ $$ = $1; }
+ | primary_expression
+ { $$ = $1; }
| unary_operator unary_expression
{
$$ = $1;
| 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;
}
;
{ $$ = $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);
}
;
{ $$ = $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);
}
;
{ $$ = $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);
}
;
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)
{
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);
}
}
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:
/* 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;
/* 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;
case IR_DATA_NUMERIC:
case IR_DATA_FIELD_REF:
case IR_DATA_GET_CONTEXT_REF:
+ case IR_DATA_EXPRESSION:
/* ok */
break;
}
}
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;
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;
}
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)
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)
{
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;
}
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);
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 = "*";
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:
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;
}
}
return op;
}
- case AST_UNARY_BIN_NOT:
+ case AST_UNARY_BIT_NOT:
{
op_str = "~";
goto error_not_supported;
{
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)
+++ /dev/null
-/*
- * filter-visitor-set-parent.c
- *
- * LTTng filter set parent visitor
- *
- * Copyright 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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 <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <inttypes.h>
-#include "filter-ast.h"
-#include "filter-parser.h"
-
-#include <common/macros.h>
-
-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);
-}
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;
case AST_UNARY_NOT:
fprintf(stream, "\"!\"");
break;
- case AST_UNARY_BIN_NOT:
+ case AST_UNARY_BIT_NOT:
fprintf(stream, "\"~\"");
break;
}
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) {
{
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;
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);
}
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
"intfield-1"
"intfield>>1"
"intfield<<1"
- "intfield&1"
- "intfield|1"
- "intfield^1"
"~intfield"
"1+11111-3333+1"
"(1+2)*(55*666)"
'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
# 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
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
# 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[@]}
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
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"
has_no_event
"0 == \$ctx.vtid.blah"
- has_no_event
- "\$ctx.44 == 0"
-
- has_no_event
- "0 == \$ctx.44"
-
END
)
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"
has_no_event
"0 == \$ctx.vtid.blah"
- has_no_event
- "\$ctx.44 == 0"
-
- has_no_event
- "0 == \$ctx.44"
-
stringfield_has_events
'stringfield == "test"'
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)
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)