diff options
Diffstat (limited to '')
-rw-r--r-- | tools/perf/util/bpf-filter.y | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tools/perf/util/bpf-filter.y b/tools/perf/util/bpf-filter.y new file mode 100644 index 000000000000..5a79a8e7a45b --- /dev/null +++ b/tools/perf/util/bpf-filter.y @@ -0,0 +1,109 @@ +%parse-param {struct list_head *expr_head} +%define parse.error verbose + +%{ + +#ifndef NDEBUG +#define YYDEBUG 1 +#endif + +#include <stdio.h> +#include <string.h> +#include <linux/compiler.h> +#include <linux/list.h> +#include "bpf-filter.h" +#include "cgroup.h" + +int perf_bpf_filter_lex(void); + +/* To indicate if the current term needs a pathname or not */ +int perf_bpf_filter_needs_path; + +static void perf_bpf_filter_error(struct list_head *expr __maybe_unused, + char const *msg) +{ + printf("perf_bpf_filter: %s\n", msg); +} + +%} + +%union +{ + unsigned long num; + char *path; + struct { + enum perf_bpf_filter_term term; + int part; + } sample; + enum perf_bpf_filter_op op; + struct perf_bpf_filter_expr *expr; +} + +%token BFT_SAMPLE BFT_SAMPLE_PATH BFT_OP BFT_ERROR BFT_NUM BFT_LOGICAL_OR BFT_PATH +%type <expr> filter_term filter_expr +%destructor { free ($$); } <expr> +%type <sample> BFT_SAMPLE BFT_SAMPLE_PATH +%type <op> BFT_OP +%type <num> BFT_NUM +%type <path> BFT_PATH + +%% + +filter: +filter ',' filter_term +{ + list_add_tail(&$3->list, expr_head); +} +| +filter_term +{ + list_add_tail(&$1->list, expr_head); +} + +filter_term: +filter_term BFT_LOGICAL_OR filter_expr +{ + struct perf_bpf_filter_expr *expr; + + if ($1->op == PBF_OP_GROUP_BEGIN) { + expr = $1; + } else { + expr = perf_bpf_filter_expr__new(PBF_TERM_NONE, /*part=*/0, + PBF_OP_GROUP_BEGIN, /*val=*/1); + list_add_tail(&$1->list, &expr->groups); + } + expr->val++; + list_add_tail(&$3->list, &expr->groups); + $$ = expr; +} +| +filter_expr +{ + $$ = $1; +} + +filter_expr: +BFT_SAMPLE BFT_OP BFT_NUM +{ + $$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, $3); +} +| +BFT_SAMPLE_PATH BFT_OP BFT_PATH +{ + struct cgroup *cgrp; + unsigned long cgroup_id = 0; + + if ($2 != PBF_OP_EQ && $2 != PBF_OP_NEQ) { + printf("perf_bpf_filter: cgroup accepts '==' or '!=' only\n"); + YYERROR; + } + + cgrp = cgroup__new($3, /*do_open=*/false); + if (cgrp && read_cgroup_id(cgrp) == 0) + cgroup_id = cgrp->id; + + $$ = perf_bpf_filter_expr__new($1.term, $1.part, $2, cgroup_id); + cgroup__put(cgrp); +} + +%% |