aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/perf/util/bpf-filter.y
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/perf/util/bpf-filter.y109
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);
+}
+
+%%