1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdarg.h>
24#include <errno.h>
25#include <sys/types.h>
26
27#include "event-parse.h"
28#include "event-utils.h"
29
30#define COMM "COMM"
31#define CPU "CPU"
32
33static struct format_field comm = {
34 .name = "COMM",
35};
36
37static struct format_field cpu = {
38 .name = "CPU",
39};
40
41struct event_list {
42 struct event_list *next;
43 struct event_format *event;
44};
45
46static void show_error(char *error_buf, const char *fmt, ...)
47{
48 unsigned long long index;
49 const char *input;
50 va_list ap;
51 int len;
52 int i;
53
54 input = pevent_get_input_buf();
55 index = pevent_get_input_buf_ptr();
56 len = input ? strlen(input) : 0;
57
58 if (len) {
59 strcpy(error_buf, input);
60 error_buf[len] = '\n';
61 for (i = 1; i < len && i < index; i++)
62 error_buf[len+i] = ' ';
63 error_buf[len + i] = '^';
64 error_buf[len + i + 1] = '\n';
65 len += i+2;
66 }
67
68 va_start(ap, fmt);
69 vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
70 va_end(ap);
71}
72
73static void free_token(char *token)
74{
75 pevent_free_token(token);
76}
77
78static enum event_type read_token(char **tok)
79{
80 enum event_type type;
81 char *token = NULL;
82
83 do {
84 free_token(token);
85 type = pevent_read_token(&token);
86 } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
87
88
89 if (token &&
90 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
91 pevent_peek_char() == '~') {
92
93 *tok = malloc(3);
94 if (*tok == NULL) {
95 free_token(token);
96 return EVENT_ERROR;
97 }
98 sprintf(*tok, "%c%c", *token, '~');
99 free_token(token);
100
101 pevent_read_token(&token);
102 free_token(token);
103 } else
104 *tok = token;
105
106 return type;
107}
108
109static int filter_cmp(const void *a, const void *b)
110{
111 const struct filter_type *ea = a;
112 const struct filter_type *eb = b;
113
114 if (ea->event_id < eb->event_id)
115 return -1;
116
117 if (ea->event_id > eb->event_id)
118 return 1;
119
120 return 0;
121}
122
123static struct filter_type *
124find_filter_type(struct event_filter *filter, int id)
125{
126 struct filter_type *filter_type;
127 struct filter_type key;
128
129 key.event_id = id;
130
131 filter_type = bsearch(&key, filter->event_filters,
132 filter->filters,
133 sizeof(*filter->event_filters),
134 filter_cmp);
135
136 return filter_type;
137}
138
139static struct filter_type *
140add_filter_type(struct event_filter *filter, int id)
141{
142 struct filter_type *filter_type;
143 int i;
144
145 filter_type = find_filter_type(filter, id);
146 if (filter_type)
147 return filter_type;
148
149 filter_type = realloc(filter->event_filters,
150 sizeof(*filter->event_filters) *
151 (filter->filters + 1));
152 if (!filter_type)
153 return NULL;
154
155 filter->event_filters = filter_type;
156
157 for (i = 0; i < filter->filters; i++) {
158 if (filter->event_filters[i].event_id > id)
159 break;
160 }
161
162 if (i < filter->filters)
163 memmove(&filter->event_filters[i+1],
164 &filter->event_filters[i],
165 sizeof(*filter->event_filters) *
166 (filter->filters - i));
167
168 filter_type = &filter->event_filters[i];
169 filter_type->event_id = id;
170 filter_type->event = pevent_find_event(filter->pevent, id);
171 filter_type->filter = NULL;
172
173 filter->filters++;
174
175 return filter_type;
176}
177
178
179
180
181
182struct event_filter *pevent_filter_alloc(struct pevent *pevent)
183{
184 struct event_filter *filter;
185
186 filter = malloc(sizeof(*filter));
187 if (filter == NULL)
188 return NULL;
189
190 memset(filter, 0, sizeof(*filter));
191 filter->pevent = pevent;
192 pevent_ref(pevent);
193
194 return filter;
195}
196
197static struct filter_arg *allocate_arg(void)
198{
199 return calloc(1, sizeof(struct filter_arg));
200}
201
202static void free_arg(struct filter_arg *arg)
203{
204 if (!arg)
205 return;
206
207 switch (arg->type) {
208 case FILTER_ARG_NONE:
209 case FILTER_ARG_BOOLEAN:
210 break;
211
212 case FILTER_ARG_NUM:
213 free_arg(arg->num.left);
214 free_arg(arg->num.right);
215 break;
216
217 case FILTER_ARG_EXP:
218 free_arg(arg->exp.left);
219 free_arg(arg->exp.right);
220 break;
221
222 case FILTER_ARG_STR:
223 free(arg->str.val);
224 regfree(&arg->str.reg);
225 free(arg->str.buffer);
226 break;
227
228 case FILTER_ARG_VALUE:
229 if (arg->value.type == FILTER_STRING ||
230 arg->value.type == FILTER_CHAR)
231 free(arg->value.str);
232 break;
233
234 case FILTER_ARG_OP:
235 free_arg(arg->op.left);
236 free_arg(arg->op.right);
237 default:
238 break;
239 }
240
241 free(arg);
242}
243
244static int add_event(struct event_list **events,
245 struct event_format *event)
246{
247 struct event_list *list;
248
249 list = malloc(sizeof(*list));
250 if (list == NULL)
251 return -1;
252
253 list->next = *events;
254 *events = list;
255 list->event = event;
256 return 0;
257}
258
259static int event_match(struct event_format *event,
260 regex_t *sreg, regex_t *ereg)
261{
262 if (sreg) {
263 return !regexec(sreg, event->system, 0, NULL, 0) &&
264 !regexec(ereg, event->name, 0, NULL, 0);
265 }
266
267 return !regexec(ereg, event->system, 0, NULL, 0) ||
268 !regexec(ereg, event->name, 0, NULL, 0);
269}
270
271static enum pevent_errno
272find_event(struct pevent *pevent, struct event_list **events,
273 char *sys_name, char *event_name)
274{
275 struct event_format *event;
276 regex_t ereg;
277 regex_t sreg;
278 int match = 0;
279 int fail = 0;
280 char *reg;
281 int ret;
282 int i;
283
284 if (!event_name) {
285
286 event_name = sys_name;
287 sys_name = NULL;
288 }
289
290 reg = malloc(strlen(event_name) + 3);
291 if (reg == NULL)
292 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
293
294 sprintf(reg, "^%s$", event_name);
295
296 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
297 free(reg);
298
299 if (ret)
300 return PEVENT_ERRNO__INVALID_EVENT_NAME;
301
302 if (sys_name) {
303 reg = malloc(strlen(sys_name) + 3);
304 if (reg == NULL) {
305 regfree(&ereg);
306 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
307 }
308
309 sprintf(reg, "^%s$", sys_name);
310 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
311 free(reg);
312 if (ret) {
313 regfree(&ereg);
314 return PEVENT_ERRNO__INVALID_EVENT_NAME;
315 }
316 }
317
318 for (i = 0; i < pevent->nr_events; i++) {
319 event = pevent->events[i];
320 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
321 match = 1;
322 if (add_event(events, event) < 0) {
323 fail = 1;
324 break;
325 }
326 }
327 }
328
329 regfree(&ereg);
330 if (sys_name)
331 regfree(&sreg);
332
333 if (!match)
334 return PEVENT_ERRNO__EVENT_NOT_FOUND;
335 if (fail)
336 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
337
338 return 0;
339}
340
341static void free_events(struct event_list *events)
342{
343 struct event_list *event;
344
345 while (events) {
346 event = events;
347 events = events->next;
348 free(event);
349 }
350}
351
352static enum pevent_errno
353create_arg_item(struct event_format *event, const char *token,
354 enum event_type type, struct filter_arg **parg, char *error_str)
355{
356 struct format_field *field;
357 struct filter_arg *arg;
358
359 arg = allocate_arg();
360 if (arg == NULL) {
361 show_error(error_str, "failed to allocate filter arg");
362 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
363 }
364
365 switch (type) {
366
367 case EVENT_SQUOTE:
368 case EVENT_DQUOTE:
369 arg->type = FILTER_ARG_VALUE;
370 arg->value.type =
371 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
372 arg->value.str = strdup(token);
373 if (!arg->value.str) {
374 free_arg(arg);
375 show_error(error_str, "failed to allocate string filter arg");
376 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
377 }
378 break;
379 case EVENT_ITEM:
380
381 if (isdigit(token[0])) {
382 arg->type = FILTER_ARG_VALUE;
383 arg->value.type = FILTER_NUMBER;
384 arg->value.val = strtoull(token, NULL, 0);
385 break;
386 }
387
388 field = pevent_find_any_field(event, token);
389 if (!field) {
390
391 if (strcmp(token, COMM) == 0) {
392 field = &comm;
393 } else if (strcmp(token, CPU) == 0) {
394 field = &cpu;
395 } else {
396
397 arg->type = FILTER_ARG_BOOLEAN;
398 arg->boolean.value = FILTER_FALSE;
399 break;
400 }
401 }
402 arg->type = FILTER_ARG_FIELD;
403 arg->field.field = field;
404 break;
405 default:
406 free_arg(arg);
407 show_error(error_str, "expected a value but found %s", token);
408 return PEVENT_ERRNO__UNEXPECTED_TYPE;
409 }
410 *parg = arg;
411 return 0;
412}
413
414static struct filter_arg *
415create_arg_op(enum filter_op_type btype)
416{
417 struct filter_arg *arg;
418
419 arg = allocate_arg();
420 if (!arg)
421 return NULL;
422
423 arg->type = FILTER_ARG_OP;
424 arg->op.type = btype;
425
426 return arg;
427}
428
429static struct filter_arg *
430create_arg_exp(enum filter_exp_type etype)
431{
432 struct filter_arg *arg;
433
434 arg = allocate_arg();
435 if (!arg)
436 return NULL;
437
438 arg->type = FILTER_ARG_EXP;
439 arg->op.type = etype;
440
441 return arg;
442}
443
444static struct filter_arg *
445create_arg_cmp(enum filter_exp_type etype)
446{
447 struct filter_arg *arg;
448
449 arg = allocate_arg();
450 if (!arg)
451 return NULL;
452
453
454 arg->type = FILTER_ARG_NUM;
455 arg->op.type = etype;
456
457 return arg;
458}
459
460static enum pevent_errno
461add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
462{
463 struct filter_arg *left;
464 char *str;
465 int op_type;
466 int ret;
467
468 switch (op->type) {
469 case FILTER_ARG_EXP:
470 if (op->exp.right)
471 goto out_fail;
472 op->exp.right = arg;
473 break;
474
475 case FILTER_ARG_OP:
476 if (op->op.right)
477 goto out_fail;
478 op->op.right = arg;
479 break;
480
481 case FILTER_ARG_NUM:
482 if (op->op.right)
483 goto out_fail;
484
485
486
487 switch (arg->type) {
488 case FILTER_ARG_VALUE:
489 case FILTER_ARG_FIELD:
490 break;
491 default:
492 show_error(error_str, "Illegal rvalue");
493 return PEVENT_ERRNO__ILLEGAL_RVALUE;
494 }
495
496
497
498
499
500 switch (arg->value.type) {
501 case FILTER_CHAR:
502
503
504
505
506
507 if (strlen(arg->value.str) == 1 &&
508 op->num.type != FILTER_CMP_REGEX &&
509 op->num.type != FILTER_CMP_NOT_REGEX) {
510 arg->value.type = FILTER_NUMBER;
511 goto do_int;
512 }
513
514 case FILTER_STRING:
515
516
517 op_type = op->num.type;
518 left = op->num.left;
519 str = arg->value.str;
520
521
522 memset(op, 0, sizeof(*op));
523
524
525
526
527
528 if (left->type == FILTER_ARG_BOOLEAN) {
529 free_arg(left);
530 free_arg(arg);
531 op->type = FILTER_ARG_BOOLEAN;
532 op->boolean.value = FILTER_FALSE;
533 break;
534 }
535
536
537 if (left->type != FILTER_ARG_FIELD) {
538 show_error(error_str,
539 "Illegal lvalue for string comparison");
540 return PEVENT_ERRNO__ILLEGAL_LVALUE;
541 }
542
543
544 switch (op_type) {
545 case FILTER_CMP_EQ:
546 op_type = FILTER_CMP_MATCH;
547 break;
548 case FILTER_CMP_NE:
549 op_type = FILTER_CMP_NOT_MATCH;
550 break;
551
552 case FILTER_CMP_REGEX:
553 case FILTER_CMP_NOT_REGEX:
554 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
555 if (ret) {
556 show_error(error_str,
557 "RegEx '%s' did not compute",
558 str);
559 return PEVENT_ERRNO__INVALID_REGEX;
560 }
561 break;
562 default:
563 show_error(error_str,
564 "Illegal comparison for string");
565 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
566 }
567
568 op->type = FILTER_ARG_STR;
569 op->str.type = op_type;
570 op->str.field = left->field.field;
571 op->str.val = strdup(str);
572 if (!op->str.val) {
573 show_error(error_str, "Failed to allocate string filter");
574 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
575 }
576
577
578
579 op->str.buffer = malloc(op->str.field->size + 1);
580 if (!op->str.buffer) {
581 show_error(error_str, "Failed to allocate string filter");
582 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
583 }
584
585 op->str.buffer[op->str.field->size] = 0;
586
587
588 free_arg(arg);
589 free_arg(left);
590
591 break;
592
593 case FILTER_NUMBER:
594
595 do_int:
596 switch (op->num.type) {
597 case FILTER_CMP_REGEX:
598 case FILTER_CMP_NOT_REGEX:
599 show_error(error_str,
600 "Op not allowed with integers");
601 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
602
603 default:
604 break;
605 }
606
607
608 op->num.right = arg;
609 break;
610 default:
611 goto out_fail;
612 }
613 break;
614 default:
615 goto out_fail;
616 }
617
618 return 0;
619
620 out_fail:
621 show_error(error_str, "Syntax error");
622 return PEVENT_ERRNO__SYNTAX_ERROR;
623}
624
625static struct filter_arg *
626rotate_op_right(struct filter_arg *a, struct filter_arg *b)
627{
628 struct filter_arg *arg;
629
630 arg = a->op.right;
631 a->op.right = b;
632 return arg;
633}
634
635static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
636{
637 switch (op->type) {
638 case FILTER_ARG_EXP:
639 if (arg->type == FILTER_ARG_OP)
640 arg = rotate_op_right(arg, op);
641 op->exp.left = arg;
642 break;
643
644 case FILTER_ARG_OP:
645 op->op.left = arg;
646 break;
647 case FILTER_ARG_NUM:
648 if (arg->type == FILTER_ARG_OP)
649 arg = rotate_op_right(arg, op);
650
651
652 if (arg->type != FILTER_ARG_FIELD &&
653 arg->type != FILTER_ARG_BOOLEAN)
654 return PEVENT_ERRNO__INVALID_ARG_TYPE;
655 op->num.left = arg;
656 break;
657 default:
658 return PEVENT_ERRNO__INVALID_ARG_TYPE;
659 }
660 return 0;
661}
662
663enum op_type {
664 OP_NONE,
665 OP_BOOL,
666 OP_NOT,
667 OP_EXP,
668 OP_CMP,
669};
670
671static enum op_type process_op(const char *token,
672 enum filter_op_type *btype,
673 enum filter_cmp_type *ctype,
674 enum filter_exp_type *etype)
675{
676 *btype = FILTER_OP_NOT;
677 *etype = FILTER_EXP_NONE;
678 *ctype = FILTER_CMP_NONE;
679
680 if (strcmp(token, "&&") == 0)
681 *btype = FILTER_OP_AND;
682 else if (strcmp(token, "||") == 0)
683 *btype = FILTER_OP_OR;
684 else if (strcmp(token, "!") == 0)
685 return OP_NOT;
686
687 if (*btype != FILTER_OP_NOT)
688 return OP_BOOL;
689
690
691 if (strcmp(token, "+") == 0) {
692 *etype = FILTER_EXP_ADD;
693 } else if (strcmp(token, "-") == 0) {
694 *etype = FILTER_EXP_SUB;
695 } else if (strcmp(token, "*") == 0) {
696 *etype = FILTER_EXP_MUL;
697 } else if (strcmp(token, "/") == 0) {
698 *etype = FILTER_EXP_DIV;
699 } else if (strcmp(token, "%") == 0) {
700 *etype = FILTER_EXP_MOD;
701 } else if (strcmp(token, ">>") == 0) {
702 *etype = FILTER_EXP_RSHIFT;
703 } else if (strcmp(token, "<<") == 0) {
704 *etype = FILTER_EXP_LSHIFT;
705 } else if (strcmp(token, "&") == 0) {
706 *etype = FILTER_EXP_AND;
707 } else if (strcmp(token, "|") == 0) {
708 *etype = FILTER_EXP_OR;
709 } else if (strcmp(token, "^") == 0) {
710 *etype = FILTER_EXP_XOR;
711 } else if (strcmp(token, "~") == 0)
712 *etype = FILTER_EXP_NOT;
713
714 if (*etype != FILTER_EXP_NONE)
715 return OP_EXP;
716
717
718 if (strcmp(token, "==") == 0)
719 *ctype = FILTER_CMP_EQ;
720 else if (strcmp(token, "!=") == 0)
721 *ctype = FILTER_CMP_NE;
722 else if (strcmp(token, "<") == 0)
723 *ctype = FILTER_CMP_LT;
724 else if (strcmp(token, ">") == 0)
725 *ctype = FILTER_CMP_GT;
726 else if (strcmp(token, "<=") == 0)
727 *ctype = FILTER_CMP_LE;
728 else if (strcmp(token, ">=") == 0)
729 *ctype = FILTER_CMP_GE;
730 else if (strcmp(token, "=~") == 0)
731 *ctype = FILTER_CMP_REGEX;
732 else if (strcmp(token, "!~") == 0)
733 *ctype = FILTER_CMP_NOT_REGEX;
734 else
735 return OP_NONE;
736
737 return OP_CMP;
738}
739
740static int check_op_done(struct filter_arg *arg)
741{
742 switch (arg->type) {
743 case FILTER_ARG_EXP:
744 return arg->exp.right != NULL;
745
746 case FILTER_ARG_OP:
747 return arg->op.right != NULL;
748
749 case FILTER_ARG_NUM:
750 return arg->num.right != NULL;
751
752 case FILTER_ARG_STR:
753
754 return 1;
755
756 case FILTER_ARG_BOOLEAN:
757
758 return 1;
759
760 default:
761 return 0;
762 }
763}
764
765enum filter_vals {
766 FILTER_VAL_NORM,
767 FILTER_VAL_FALSE,
768 FILTER_VAL_TRUE,
769};
770
771static enum pevent_errno
772reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
773 struct filter_arg *arg, char *error_str)
774{
775 struct filter_arg *other_child;
776 struct filter_arg **ptr;
777
778 if (parent->type != FILTER_ARG_OP &&
779 arg->type != FILTER_ARG_OP) {
780 show_error(error_str, "can not reparent other than OP");
781 return PEVENT_ERRNO__REPARENT_NOT_OP;
782 }
783
784
785 if (old_child->op.right == arg) {
786 ptr = &old_child->op.right;
787 other_child = old_child->op.left;
788 } else if (old_child->op.left == arg) {
789 ptr = &old_child->op.left;
790 other_child = old_child->op.right;
791 } else {
792 show_error(error_str, "Error in reparent op, find other child");
793 return PEVENT_ERRNO__REPARENT_FAILED;
794 }
795
796
797 *ptr = NULL;
798
799
800 if (parent == old_child) {
801 free_arg(other_child);
802 *parent = *arg;
803
804 free(arg);
805 return 0;
806 }
807
808 if (parent->op.right == old_child)
809 ptr = &parent->op.right;
810 else if (parent->op.left == old_child)
811 ptr = &parent->op.left;
812 else {
813 show_error(error_str, "Error in reparent op");
814 return PEVENT_ERRNO__REPARENT_FAILED;
815 }
816
817 *ptr = arg;
818
819 free_arg(old_child);
820 return 0;
821}
822
823
824static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
825 char *error_str)
826{
827 int lval, rval;
828
829 switch (arg->type) {
830
831
832 case FILTER_ARG_BOOLEAN:
833 return FILTER_VAL_FALSE + arg->boolean.value;
834
835
836 case FILTER_ARG_STR:
837 case FILTER_ARG_VALUE:
838 case FILTER_ARG_FIELD:
839 return FILTER_VAL_NORM;
840
841 case FILTER_ARG_EXP:
842 lval = test_arg(arg, arg->exp.left, error_str);
843 if (lval != FILTER_VAL_NORM)
844 return lval;
845 rval = test_arg(arg, arg->exp.right, error_str);
846 if (rval != FILTER_VAL_NORM)
847 return rval;
848 return FILTER_VAL_NORM;
849
850 case FILTER_ARG_NUM:
851 lval = test_arg(arg, arg->num.left, error_str);
852 if (lval != FILTER_VAL_NORM)
853 return lval;
854 rval = test_arg(arg, arg->num.right, error_str);
855 if (rval != FILTER_VAL_NORM)
856 return rval;
857 return FILTER_VAL_NORM;
858
859 case FILTER_ARG_OP:
860 if (arg->op.type != FILTER_OP_NOT) {
861 lval = test_arg(arg, arg->op.left, error_str);
862 switch (lval) {
863 case FILTER_VAL_NORM:
864 break;
865 case FILTER_VAL_TRUE:
866 if (arg->op.type == FILTER_OP_OR)
867 return FILTER_VAL_TRUE;
868 rval = test_arg(arg, arg->op.right, error_str);
869 if (rval != FILTER_VAL_NORM)
870 return rval;
871
872 return reparent_op_arg(parent, arg, arg->op.right,
873 error_str);
874
875 case FILTER_VAL_FALSE:
876 if (arg->op.type == FILTER_OP_AND)
877 return FILTER_VAL_FALSE;
878 rval = test_arg(arg, arg->op.right, error_str);
879 if (rval != FILTER_VAL_NORM)
880 return rval;
881
882 return reparent_op_arg(parent, arg, arg->op.right,
883 error_str);
884
885 default:
886 return lval;
887 }
888 }
889
890 rval = test_arg(arg, arg->op.right, error_str);
891 switch (rval) {
892 case FILTER_VAL_NORM:
893 default:
894 break;
895
896 case FILTER_VAL_TRUE:
897 if (arg->op.type == FILTER_OP_OR)
898 return FILTER_VAL_TRUE;
899 if (arg->op.type == FILTER_OP_NOT)
900 return FILTER_VAL_FALSE;
901
902 return reparent_op_arg(parent, arg, arg->op.left,
903 error_str);
904
905 case FILTER_VAL_FALSE:
906 if (arg->op.type == FILTER_OP_AND)
907 return FILTER_VAL_FALSE;
908 if (arg->op.type == FILTER_OP_NOT)
909 return FILTER_VAL_TRUE;
910
911 return reparent_op_arg(parent, arg, arg->op.left,
912 error_str);
913 }
914
915 return rval;
916 default:
917 show_error(error_str, "bad arg in filter tree");
918 return PEVENT_ERRNO__BAD_FILTER_ARG;
919 }
920 return FILTER_VAL_NORM;
921}
922
923
924static int collapse_tree(struct filter_arg *arg,
925 struct filter_arg **arg_collapsed, char *error_str)
926{
927 int ret;
928
929 ret = test_arg(arg, arg, error_str);
930 switch (ret) {
931 case FILTER_VAL_NORM:
932 break;
933
934 case FILTER_VAL_TRUE:
935 case FILTER_VAL_FALSE:
936 free_arg(arg);
937 arg = allocate_arg();
938 if (arg) {
939 arg->type = FILTER_ARG_BOOLEAN;
940 arg->boolean.value = ret == FILTER_VAL_TRUE;
941 } else {
942 show_error(error_str, "Failed to allocate filter arg");
943 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
944 }
945 break;
946
947 default:
948
949 free_arg(arg);
950 arg = NULL;
951 break;
952 }
953
954 *arg_collapsed = arg;
955 return ret;
956}
957
958static enum pevent_errno
959process_filter(struct event_format *event, struct filter_arg **parg,
960 char *error_str, int not)
961{
962 enum event_type type;
963 char *token = NULL;
964 struct filter_arg *current_op = NULL;
965 struct filter_arg *current_exp = NULL;
966 struct filter_arg *left_item = NULL;
967 struct filter_arg *arg = NULL;
968 enum op_type op_type;
969 enum filter_op_type btype;
970 enum filter_exp_type etype;
971 enum filter_cmp_type ctype;
972 enum pevent_errno ret;
973
974 *parg = NULL;
975
976 do {
977 free(token);
978 type = read_token(&token);
979 switch (type) {
980 case EVENT_SQUOTE:
981 case EVENT_DQUOTE:
982 case EVENT_ITEM:
983 ret = create_arg_item(event, token, type, &arg, error_str);
984 if (ret < 0)
985 goto fail;
986 if (!left_item)
987 left_item = arg;
988 else if (current_exp) {
989 ret = add_right(current_exp, arg, error_str);
990 if (ret < 0)
991 goto fail;
992 left_item = NULL;
993
994 if (not) {
995 arg = NULL;
996 if (current_op)
997 goto fail_syntax;
998 free(token);
999 *parg = current_exp;
1000 return 0;
1001 }
1002 } else
1003 goto fail_syntax;
1004 arg = NULL;
1005 break;
1006
1007 case EVENT_DELIM:
1008 if (*token == ',') {
1009 show_error(error_str, "Illegal token ','");
1010 ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
1011 goto fail;
1012 }
1013
1014 if (*token == '(') {
1015 if (left_item) {
1016 show_error(error_str,
1017 "Open paren can not come after item");
1018 ret = PEVENT_ERRNO__INVALID_PAREN;
1019 goto fail;
1020 }
1021 if (current_exp) {
1022 show_error(error_str,
1023 "Open paren can not come after expression");
1024 ret = PEVENT_ERRNO__INVALID_PAREN;
1025 goto fail;
1026 }
1027
1028 ret = process_filter(event, &arg, error_str, 0);
1029 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
1030 if (ret == 0) {
1031 show_error(error_str,
1032 "Unbalanced number of '('");
1033 ret = PEVENT_ERRNO__UNBALANCED_PAREN;
1034 }
1035 goto fail;
1036 }
1037 ret = 0;
1038
1039
1040 if (not) {
1041 if (current_op)
1042 goto fail_syntax;
1043 *parg = arg;
1044 return 0;
1045 }
1046
1047 if (current_op)
1048 ret = add_right(current_op, arg, error_str);
1049 else
1050 current_exp = arg;
1051
1052 if (ret < 0)
1053 goto fail;
1054
1055 } else {
1056 if (!current_op && !current_exp)
1057 goto fail_syntax;
1058
1059
1060 if (current_exp && !check_op_done(current_exp))
1061 goto fail_syntax;
1062 if (current_op && !check_op_done(current_op))
1063 goto fail_syntax;
1064
1065 if (current_op)
1066 *parg = current_op;
1067 else
1068 *parg = current_exp;
1069 free(token);
1070 return PEVENT_ERRNO__UNBALANCED_PAREN;
1071 }
1072 break;
1073
1074 case EVENT_OP:
1075 op_type = process_op(token, &btype, &ctype, &etype);
1076
1077
1078 switch (op_type) {
1079 case OP_BOOL:
1080
1081 if (!current_exp && !current_op)
1082 goto fail_syntax;
1083
1084 case OP_NOT:
1085
1086 if (left_item)
1087 goto fail_syntax;
1088 break;
1089 case OP_EXP:
1090 case OP_CMP:
1091 if (!left_item)
1092 goto fail_syntax;
1093 break;
1094 case OP_NONE:
1095 show_error(error_str,
1096 "Unknown op token %s", token);
1097 ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
1098 goto fail;
1099 }
1100
1101 ret = 0;
1102 switch (op_type) {
1103 case OP_BOOL:
1104 arg = create_arg_op(btype);
1105 if (arg == NULL)
1106 goto fail_alloc;
1107 if (current_op)
1108 ret = add_left(arg, current_op);
1109 else
1110 ret = add_left(arg, current_exp);
1111 current_op = arg;
1112 current_exp = NULL;
1113 break;
1114
1115 case OP_NOT:
1116 arg = create_arg_op(btype);
1117 if (arg == NULL)
1118 goto fail_alloc;
1119 if (current_op)
1120 ret = add_right(current_op, arg, error_str);
1121 if (ret < 0)
1122 goto fail;
1123 current_exp = arg;
1124 ret = process_filter(event, &arg, error_str, 1);
1125 if (ret < 0)
1126 goto fail;
1127 ret = add_right(current_exp, arg, error_str);
1128 if (ret < 0)
1129 goto fail;
1130 break;
1131
1132 case OP_EXP:
1133 case OP_CMP:
1134 if (op_type == OP_EXP)
1135 arg = create_arg_exp(etype);
1136 else
1137 arg = create_arg_cmp(ctype);
1138 if (arg == NULL)
1139 goto fail_alloc;
1140
1141 if (current_op)
1142 ret = add_right(current_op, arg, error_str);
1143 if (ret < 0)
1144 goto fail;
1145 ret = add_left(arg, left_item);
1146 if (ret < 0) {
1147 arg = NULL;
1148 goto fail_syntax;
1149 }
1150 current_exp = arg;
1151 break;
1152 default:
1153 break;
1154 }
1155 arg = NULL;
1156 if (ret < 0)
1157 goto fail_syntax;
1158 break;
1159 case EVENT_NONE:
1160 break;
1161 case EVENT_ERROR:
1162 goto fail_alloc;
1163 default:
1164 goto fail_syntax;
1165 }
1166 } while (type != EVENT_NONE);
1167
1168 if (!current_op && !current_exp)
1169 goto fail_syntax;
1170
1171 if (!current_op)
1172 current_op = current_exp;
1173
1174 ret = collapse_tree(current_op, parg, error_str);
1175
1176 current_op = NULL;
1177 if (ret < 0)
1178 goto fail;
1179
1180 free(token);
1181 return 0;
1182
1183 fail_alloc:
1184 show_error(error_str, "failed to allocate filter arg");
1185 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
1186 goto fail;
1187 fail_syntax:
1188 show_error(error_str, "Syntax error");
1189 ret = PEVENT_ERRNO__SYNTAX_ERROR;
1190 fail:
1191 free_arg(current_op);
1192 free_arg(current_exp);
1193 free_arg(arg);
1194 free(token);
1195 return ret;
1196}
1197
1198static enum pevent_errno
1199process_event(struct event_format *event, const char *filter_str,
1200 struct filter_arg **parg, char *error_str)
1201{
1202 int ret;
1203
1204 pevent_buffer_init(filter_str, strlen(filter_str));
1205
1206 ret = process_filter(event, parg, error_str, 0);
1207 if (ret < 0)
1208 return ret;
1209
1210
1211 if (!*parg) {
1212 *parg = allocate_arg();
1213 if (*parg == NULL)
1214 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1215
1216 (*parg)->type = FILTER_ARG_BOOLEAN;
1217 (*parg)->boolean.value = FILTER_FALSE;
1218 }
1219
1220 return 0;
1221}
1222
1223static enum pevent_errno
1224filter_event(struct event_filter *filter, struct event_format *event,
1225 const char *filter_str, char *error_str)
1226{
1227 struct filter_type *filter_type;
1228 struct filter_arg *arg;
1229 enum pevent_errno ret;
1230
1231 if (filter_str) {
1232 ret = process_event(event, filter_str, &arg, error_str);
1233 if (ret < 0)
1234 return ret;
1235
1236 } else {
1237
1238 arg = allocate_arg();
1239 if (arg == NULL)
1240 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1241
1242 arg->type = FILTER_ARG_BOOLEAN;
1243 arg->boolean.value = FILTER_TRUE;
1244 }
1245
1246 filter_type = add_filter_type(filter, event->id);
1247 if (filter_type == NULL)
1248 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1249
1250 if (filter_type->filter)
1251 free_arg(filter_type->filter);
1252 filter_type->filter = arg;
1253
1254 return 0;
1255}
1256
1257static void filter_init_error_buf(struct event_filter *filter)
1258{
1259
1260 pevent_buffer_init("", 0);
1261 filter->error_buffer[0] = '\0';
1262}
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1274 const char *filter_str)
1275{
1276 struct pevent *pevent = filter->pevent;
1277 struct event_list *event;
1278 struct event_list *events = NULL;
1279 const char *filter_start;
1280 const char *next_event;
1281 char *this_event;
1282 char *event_name = NULL;
1283 char *sys_name = NULL;
1284 char *sp;
1285 enum pevent_errno rtn = 0;
1286 int len;
1287 int ret;
1288
1289 filter_init_error_buf(filter);
1290
1291 filter_start = strchr(filter_str, ':');
1292 if (filter_start)
1293 len = filter_start - filter_str;
1294 else
1295 len = strlen(filter_str);
1296
1297 do {
1298 next_event = strchr(filter_str, ',');
1299 if (next_event &&
1300 (!filter_start || next_event < filter_start))
1301 len = next_event - filter_str;
1302 else if (filter_start)
1303 len = filter_start - filter_str;
1304 else
1305 len = strlen(filter_str);
1306
1307 this_event = malloc(len + 1);
1308 if (this_event == NULL) {
1309
1310 free_events(events);
1311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1312 }
1313 memcpy(this_event, filter_str, len);
1314 this_event[len] = 0;
1315
1316 if (next_event)
1317 next_event++;
1318
1319 filter_str = next_event;
1320
1321 sys_name = strtok_r(this_event, "/", &sp);
1322 event_name = strtok_r(NULL, "/", &sp);
1323
1324 if (!sys_name) {
1325
1326 free_events(events);
1327 free(this_event);
1328 return PEVENT_ERRNO__FILTER_NOT_FOUND;
1329 }
1330
1331
1332 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1333 if (ret < 0) {
1334 free_events(events);
1335 free(this_event);
1336 return ret;
1337 }
1338 free(this_event);
1339 } while (filter_str);
1340
1341
1342 if (filter_start)
1343 filter_start++;
1344
1345
1346 for (event = events; event; event = event->next) {
1347 ret = filter_event(filter, event->event, filter_start,
1348 filter->error_buffer);
1349
1350 if (ret < 0)
1351 rtn = ret;
1352
1353 if (ret >= 0 && pevent->test_filters) {
1354 char *test;
1355 test = pevent_filter_make_string(filter, event->event->id);
1356 if (test) {
1357 printf(" '%s: %s'\n", event->event->name, test);
1358 free(test);
1359 }
1360 }
1361 }
1362
1363 free_events(events);
1364
1365 if (rtn >= 0 && pevent->test_filters)
1366 exit(0);
1367
1368 return rtn;
1369}
1370
1371static void free_filter_type(struct filter_type *filter_type)
1372{
1373 free_arg(filter_type->filter);
1374}
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
1386 char *buf, size_t buflen)
1387{
1388 if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
1389 return -1;
1390
1391 if (strlen(filter->error_buffer) > 0) {
1392 size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
1393
1394 if (len > buflen)
1395 return -1;
1396 return 0;
1397 }
1398
1399 return pevent_strerror(filter->pevent, err, buf, buflen);
1400}
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413int pevent_filter_remove_event(struct event_filter *filter,
1414 int event_id)
1415{
1416 struct filter_type *filter_type;
1417 unsigned long len;
1418
1419 if (!filter->filters)
1420 return 0;
1421
1422 filter_type = find_filter_type(filter, event_id);
1423
1424 if (!filter_type)
1425 return 0;
1426
1427 free_filter_type(filter_type);
1428
1429
1430 len = (unsigned long)(filter->event_filters + filter->filters) -
1431 (unsigned long)(filter_type + 1);
1432
1433 memmove(filter_type, filter_type + 1, len);
1434 filter->filters--;
1435
1436 memset(&filter->event_filters[filter->filters], 0,
1437 sizeof(*filter_type));
1438
1439 return 1;
1440}
1441
1442
1443
1444
1445
1446
1447
1448void pevent_filter_reset(struct event_filter *filter)
1449{
1450 int i;
1451
1452 for (i = 0; i < filter->filters; i++)
1453 free_filter_type(&filter->event_filters[i]);
1454
1455 free(filter->event_filters);
1456 filter->filters = 0;
1457 filter->event_filters = NULL;
1458}
1459
1460void pevent_filter_free(struct event_filter *filter)
1461{
1462 pevent_unref(filter->pevent);
1463
1464 pevent_filter_reset(filter);
1465
1466 free(filter);
1467}
1468
1469static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1470
1471static int copy_filter_type(struct event_filter *filter,
1472 struct event_filter *source,
1473 struct filter_type *filter_type)
1474{
1475 struct filter_arg *arg;
1476 struct event_format *event;
1477 const char *sys;
1478 const char *name;
1479 char *str;
1480
1481
1482 sys = filter_type->event->system;
1483 name = filter_type->event->name;
1484 event = pevent_find_event_by_name(filter->pevent, sys, name);
1485 if (!event)
1486 return -1;
1487
1488 str = arg_to_str(source, filter_type->filter);
1489 if (!str)
1490 return -1;
1491
1492 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1493
1494 arg = allocate_arg();
1495 if (arg == NULL)
1496 return -1;
1497
1498 arg->type = FILTER_ARG_BOOLEAN;
1499 if (strcmp(str, "TRUE") == 0)
1500 arg->boolean.value = 1;
1501 else
1502 arg->boolean.value = 0;
1503
1504 filter_type = add_filter_type(filter, event->id);
1505 if (filter_type == NULL)
1506 return -1;
1507
1508 filter_type->filter = arg;
1509
1510 free(str);
1511 return 0;
1512 }
1513
1514 filter_event(filter, event, str, NULL);
1515 free(str);
1516
1517 return 0;
1518}
1519
1520
1521
1522
1523
1524
1525
1526
1527int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1528{
1529 int ret = 0;
1530 int i;
1531
1532 pevent_filter_reset(dest);
1533
1534 for (i = 0; i < source->filters; i++) {
1535 if (copy_filter_type(dest, source, &source->event_filters[i]))
1536 ret = -1;
1537 }
1538 return ret;
1539}
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1554 enum filter_trivial_type type)
1555{
1556 struct pevent *src_pevent;
1557 struct pevent *dest_pevent;
1558 struct event_format *event;
1559 struct filter_type *filter_type;
1560 struct filter_arg *arg;
1561 char *str;
1562 int i;
1563
1564 src_pevent = source->pevent;
1565 dest_pevent = dest->pevent;
1566
1567
1568 if (!dest->filters || !source->filters)
1569 return 0;
1570
1571 for (i = 0; i < dest->filters; i++) {
1572 filter_type = &dest->event_filters[i];
1573 arg = filter_type->filter;
1574 if (arg->type != FILTER_ARG_BOOLEAN)
1575 continue;
1576 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1577 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
1578 continue;
1579
1580 event = filter_type->event;
1581
1582 if (src_pevent != dest_pevent) {
1583
1584 event = pevent_find_event_by_name(src_pevent,
1585 event->system,
1586 event->name);
1587 if (!event)
1588 return -1;
1589 }
1590
1591 str = pevent_filter_make_string(source, event->id);
1592 if (!str)
1593 continue;
1594
1595
1596 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1597 filter_event(dest, event, str, NULL);
1598 free(str);
1599 }
1600 return 0;
1601}
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612int pevent_filter_clear_trivial(struct event_filter *filter,
1613 enum filter_trivial_type type)
1614{
1615 struct filter_type *filter_type;
1616 int count = 0;
1617 int *ids = NULL;
1618 int i;
1619
1620 if (!filter->filters)
1621 return 0;
1622
1623
1624
1625
1626
1627 for (i = 0; i < filter->filters; i++) {
1628 int *new_ids;
1629
1630 filter_type = &filter->event_filters[i];
1631 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1632 continue;
1633 switch (type) {
1634 case FILTER_TRIVIAL_FALSE:
1635 if (filter_type->filter->boolean.value)
1636 continue;
1637 case FILTER_TRIVIAL_TRUE:
1638 if (!filter_type->filter->boolean.value)
1639 continue;
1640 default:
1641 break;
1642 }
1643
1644 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1645 if (!new_ids) {
1646 free(ids);
1647 return -1;
1648 }
1649
1650 ids = new_ids;
1651 ids[count++] = filter_type->event_id;
1652 }
1653
1654 if (!count)
1655 return 0;
1656
1657 for (i = 0; i < count; i++)
1658 pevent_filter_remove_event(filter, ids[i]);
1659
1660 free(ids);
1661 return 0;
1662}
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673int pevent_filter_event_has_trivial(struct event_filter *filter,
1674 int event_id,
1675 enum filter_trivial_type type)
1676{
1677 struct filter_type *filter_type;
1678
1679 if (!filter->filters)
1680 return 0;
1681
1682 filter_type = find_filter_type(filter, event_id);
1683
1684 if (!filter_type)
1685 return 0;
1686
1687 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1688 return 0;
1689
1690 switch (type) {
1691 case FILTER_TRIVIAL_FALSE:
1692 return !filter_type->filter->boolean.value;
1693
1694 case FILTER_TRIVIAL_TRUE:
1695 return filter_type->filter->boolean.value;
1696 default:
1697 return 1;
1698 }
1699}
1700
1701static int test_filter(struct event_format *event, struct filter_arg *arg,
1702 struct pevent_record *record, enum pevent_errno *err);
1703
1704static const char *
1705get_comm(struct event_format *event, struct pevent_record *record)
1706{
1707 const char *comm;
1708 int pid;
1709
1710 pid = pevent_data_pid(event->pevent, record);
1711 comm = pevent_data_comm_from_pid(event->pevent, pid);
1712 return comm;
1713}
1714
1715static unsigned long long
1716get_value(struct event_format *event,
1717 struct format_field *field, struct pevent_record *record)
1718{
1719 unsigned long long val;
1720
1721
1722 if (field == &comm) {
1723 const char *name;
1724
1725 name = get_comm(event, record);
1726 return (unsigned long)name;
1727 }
1728
1729
1730 if (field == &cpu)
1731 return record->cpu;
1732
1733 pevent_read_number_field(field, record->data, &val);
1734
1735 if (!(field->flags & FIELD_IS_SIGNED))
1736 return val;
1737
1738 switch (field->size) {
1739 case 1:
1740 return (char)val;
1741 case 2:
1742 return (short)val;
1743 case 4:
1744 return (int)val;
1745 case 8:
1746 return (long long)val;
1747 }
1748 return val;
1749}
1750
1751static unsigned long long
1752get_arg_value(struct event_format *event, struct filter_arg *arg,
1753 struct pevent_record *record, enum pevent_errno *err);
1754
1755static unsigned long long
1756get_exp_value(struct event_format *event, struct filter_arg *arg,
1757 struct pevent_record *record, enum pevent_errno *err)
1758{
1759 unsigned long long lval, rval;
1760
1761 lval = get_arg_value(event, arg->exp.left, record, err);
1762 rval = get_arg_value(event, arg->exp.right, record, err);
1763
1764 if (*err) {
1765
1766
1767
1768 return 0;
1769 }
1770
1771 switch (arg->exp.type) {
1772 case FILTER_EXP_ADD:
1773 return lval + rval;
1774
1775 case FILTER_EXP_SUB:
1776 return lval - rval;
1777
1778 case FILTER_EXP_MUL:
1779 return lval * rval;
1780
1781 case FILTER_EXP_DIV:
1782 return lval / rval;
1783
1784 case FILTER_EXP_MOD:
1785 return lval % rval;
1786
1787 case FILTER_EXP_RSHIFT:
1788 return lval >> rval;
1789
1790 case FILTER_EXP_LSHIFT:
1791 return lval << rval;
1792
1793 case FILTER_EXP_AND:
1794 return lval & rval;
1795
1796 case FILTER_EXP_OR:
1797 return lval | rval;
1798
1799 case FILTER_EXP_XOR:
1800 return lval ^ rval;
1801
1802 case FILTER_EXP_NOT:
1803 default:
1804 if (!*err)
1805 *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
1806 }
1807 return 0;
1808}
1809
1810static unsigned long long
1811get_arg_value(struct event_format *event, struct filter_arg *arg,
1812 struct pevent_record *record, enum pevent_errno *err)
1813{
1814 switch (arg->type) {
1815 case FILTER_ARG_FIELD:
1816 return get_value(event, arg->field.field, record);
1817
1818 case FILTER_ARG_VALUE:
1819 if (arg->value.type != FILTER_NUMBER) {
1820 if (!*err)
1821 *err = PEVENT_ERRNO__NOT_A_NUMBER;
1822 }
1823 return arg->value.val;
1824
1825 case FILTER_ARG_EXP:
1826 return get_exp_value(event, arg, record, err);
1827
1828 default:
1829 if (!*err)
1830 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
1831 }
1832 return 0;
1833}
1834
1835static int test_num(struct event_format *event, struct filter_arg *arg,
1836 struct pevent_record *record, enum pevent_errno *err)
1837{
1838 unsigned long long lval, rval;
1839
1840 lval = get_arg_value(event, arg->num.left, record, err);
1841 rval = get_arg_value(event, arg->num.right, record, err);
1842
1843 if (*err) {
1844
1845
1846
1847 return 0;
1848 }
1849
1850 switch (arg->num.type) {
1851 case FILTER_CMP_EQ:
1852 return lval == rval;
1853
1854 case FILTER_CMP_NE:
1855 return lval != rval;
1856
1857 case FILTER_CMP_GT:
1858 return lval > rval;
1859
1860 case FILTER_CMP_LT:
1861 return lval < rval;
1862
1863 case FILTER_CMP_GE:
1864 return lval >= rval;
1865
1866 case FILTER_CMP_LE:
1867 return lval <= rval;
1868
1869 default:
1870 if (!*err)
1871 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
1872 return 0;
1873 }
1874}
1875
1876static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
1877{
1878 struct event_format *event;
1879 struct pevent *pevent;
1880 unsigned long long addr;
1881 const char *val = NULL;
1882 char hex[64];
1883
1884
1885 if (arg->str.field->flags & FIELD_IS_STRING) {
1886 val = record->data + arg->str.field->offset;
1887
1888
1889
1890
1891
1892 if (*(val + arg->str.field->size - 1)) {
1893
1894 memcpy(arg->str.buffer, val, arg->str.field->size);
1895
1896 val = arg->str.buffer;
1897 }
1898
1899 } else {
1900 event = arg->str.field->event;
1901 pevent = event->pevent;
1902 addr = get_value(event, arg->str.field, record);
1903
1904 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1905
1906 val = pevent_find_function(pevent, addr);
1907
1908 if (val == NULL) {
1909
1910 snprintf(hex, 64, "0x%llx", addr);
1911 val = hex;
1912 }
1913 }
1914
1915 return val;
1916}
1917
1918static int test_str(struct event_format *event, struct filter_arg *arg,
1919 struct pevent_record *record, enum pevent_errno *err)
1920{
1921 const char *val;
1922
1923 if (arg->str.field == &comm)
1924 val = get_comm(event, record);
1925 else
1926 val = get_field_str(arg, record);
1927
1928 switch (arg->str.type) {
1929 case FILTER_CMP_MATCH:
1930 return strcmp(val, arg->str.val) == 0;
1931
1932 case FILTER_CMP_NOT_MATCH:
1933 return strcmp(val, arg->str.val) != 0;
1934
1935 case FILTER_CMP_REGEX:
1936
1937 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1938
1939 case FILTER_CMP_NOT_REGEX:
1940 return regexec(&arg->str.reg, val, 0, NULL, 0);
1941
1942 default:
1943 if (!*err)
1944 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
1945 return 0;
1946 }
1947}
1948
1949static int test_op(struct event_format *event, struct filter_arg *arg,
1950 struct pevent_record *record, enum pevent_errno *err)
1951{
1952 switch (arg->op.type) {
1953 case FILTER_OP_AND:
1954 return test_filter(event, arg->op.left, record, err) &&
1955 test_filter(event, arg->op.right, record, err);
1956
1957 case FILTER_OP_OR:
1958 return test_filter(event, arg->op.left, record, err) ||
1959 test_filter(event, arg->op.right, record, err);
1960
1961 case FILTER_OP_NOT:
1962 return !test_filter(event, arg->op.right, record, err);
1963
1964 default:
1965 if (!*err)
1966 *err = PEVENT_ERRNO__INVALID_OP_TYPE;
1967 return 0;
1968 }
1969}
1970
1971static int test_filter(struct event_format *event, struct filter_arg *arg,
1972 struct pevent_record *record, enum pevent_errno *err)
1973{
1974 if (*err) {
1975
1976
1977
1978 return 0;
1979 }
1980
1981 switch (arg->type) {
1982 case FILTER_ARG_BOOLEAN:
1983
1984 return arg->boolean.value;
1985
1986 case FILTER_ARG_OP:
1987 return test_op(event, arg, record, err);
1988
1989 case FILTER_ARG_NUM:
1990 return test_num(event, arg, record, err);
1991
1992 case FILTER_ARG_STR:
1993 return test_str(event, arg, record, err);
1994
1995 case FILTER_ARG_EXP:
1996 case FILTER_ARG_VALUE:
1997 case FILTER_ARG_FIELD:
1998
1999
2000
2001
2002 return !!get_arg_value(event, arg, record, err);
2003
2004 default:
2005 if (!*err)
2006 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
2007 return 0;
2008 }
2009}
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019int pevent_event_filtered(struct event_filter *filter, int event_id)
2020{
2021 struct filter_type *filter_type;
2022
2023 if (!filter->filters)
2024 return 0;
2025
2026 filter_type = find_filter_type(filter, event_id);
2027
2028 return filter_type ? 1 : 0;
2029}
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043enum pevent_errno pevent_filter_match(struct event_filter *filter,
2044 struct pevent_record *record)
2045{
2046 struct pevent *pevent = filter->pevent;
2047 struct filter_type *filter_type;
2048 int event_id;
2049 int ret;
2050 enum pevent_errno err = 0;
2051
2052 filter_init_error_buf(filter);
2053
2054 if (!filter->filters)
2055 return PEVENT_ERRNO__NO_FILTER;
2056
2057 event_id = pevent_data_type(pevent, record);
2058
2059 filter_type = find_filter_type(filter, event_id);
2060 if (!filter_type)
2061 return PEVENT_ERRNO__FILTER_NOT_FOUND;
2062
2063 ret = test_filter(filter_type->event, filter_type->filter, record, &err);
2064 if (err)
2065 return err;
2066
2067 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
2068}
2069
2070static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2071{
2072 char *str = NULL;
2073 char *left = NULL;
2074 char *right = NULL;
2075 char *op = NULL;
2076 int left_val = -1;
2077 int right_val = -1;
2078 int val;
2079
2080 switch (arg->op.type) {
2081 case FILTER_OP_AND:
2082 op = "&&";
2083
2084 case FILTER_OP_OR:
2085 if (!op)
2086 op = "||";
2087
2088 left = arg_to_str(filter, arg->op.left);
2089 right = arg_to_str(filter, arg->op.right);
2090 if (!left || !right)
2091 break;
2092
2093
2094 if (strcmp(left, "TRUE") == 0)
2095 left_val = 1;
2096 else if (strcmp(left, "FALSE") == 0)
2097 left_val = 0;
2098
2099 if (strcmp(right, "TRUE") == 0)
2100 right_val = 1;
2101 else if (strcmp(right, "FALSE") == 0)
2102 right_val = 0;
2103
2104 if (left_val >= 0) {
2105 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2106 (arg->op.type == FILTER_OP_OR && left_val)) {
2107
2108 str = left;
2109 left = NULL;
2110 break;
2111 }
2112 if (right_val >= 0) {
2113
2114 val = 0;
2115 switch (arg->op.type) {
2116 case FILTER_OP_AND:
2117 val = left_val && right_val;
2118 break;
2119 case FILTER_OP_OR:
2120 val = left_val || right_val;
2121 break;
2122 default:
2123 break;
2124 }
2125 asprintf(&str, val ? "TRUE" : "FALSE");
2126 break;
2127 }
2128 }
2129 if (right_val >= 0) {
2130 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2131 (arg->op.type == FILTER_OP_OR && right_val)) {
2132
2133 str = right;
2134 right = NULL;
2135 break;
2136 }
2137
2138 str = left;
2139 left = NULL;
2140 break;
2141 }
2142
2143 asprintf(&str, "(%s) %s (%s)", left, op, right);
2144 break;
2145
2146 case FILTER_OP_NOT:
2147 op = "!";
2148 right = arg_to_str(filter, arg->op.right);
2149 if (!right)
2150 break;
2151
2152
2153 if (strcmp(right, "TRUE") == 0)
2154 right_val = 1;
2155 else if (strcmp(right, "FALSE") == 0)
2156 right_val = 0;
2157 if (right_val >= 0) {
2158
2159 asprintf(&str, right_val ? "FALSE" : "TRUE");
2160 break;
2161 }
2162 asprintf(&str, "%s(%s)", op, right);
2163 break;
2164
2165 default:
2166
2167 break;
2168 }
2169 free(left);
2170 free(right);
2171 return str;
2172}
2173
2174static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2175{
2176 char *str = NULL;
2177
2178 asprintf(&str, "%lld", arg->value.val);
2179
2180 return str;
2181}
2182
2183static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2184{
2185 return strdup(arg->field.field->name);
2186}
2187
2188static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2189{
2190 char *lstr;
2191 char *rstr;
2192 char *op;
2193 char *str = NULL;
2194
2195 lstr = arg_to_str(filter, arg->exp.left);
2196 rstr = arg_to_str(filter, arg->exp.right);
2197 if (!lstr || !rstr)
2198 goto out;
2199
2200 switch (arg->exp.type) {
2201 case FILTER_EXP_ADD:
2202 op = "+";
2203 break;
2204 case FILTER_EXP_SUB:
2205 op = "-";
2206 break;
2207 case FILTER_EXP_MUL:
2208 op = "*";
2209 break;
2210 case FILTER_EXP_DIV:
2211 op = "/";
2212 break;
2213 case FILTER_EXP_MOD:
2214 op = "%";
2215 break;
2216 case FILTER_EXP_RSHIFT:
2217 op = ">>";
2218 break;
2219 case FILTER_EXP_LSHIFT:
2220 op = "<<";
2221 break;
2222 case FILTER_EXP_AND:
2223 op = "&";
2224 break;
2225 case FILTER_EXP_OR:
2226 op = "|";
2227 break;
2228 case FILTER_EXP_XOR:
2229 op = "^";
2230 break;
2231 default:
2232 op = "[ERROR IN EXPRESSION TYPE]";
2233 break;
2234 }
2235
2236 asprintf(&str, "%s %s %s", lstr, op, rstr);
2237out:
2238 free(lstr);
2239 free(rstr);
2240
2241 return str;
2242}
2243
2244static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2245{
2246 char *lstr;
2247 char *rstr;
2248 char *str = NULL;
2249 char *op = NULL;
2250
2251 lstr = arg_to_str(filter, arg->num.left);
2252 rstr = arg_to_str(filter, arg->num.right);
2253 if (!lstr || !rstr)
2254 goto out;
2255
2256 switch (arg->num.type) {
2257 case FILTER_CMP_EQ:
2258 op = "==";
2259
2260 case FILTER_CMP_NE:
2261 if (!op)
2262 op = "!=";
2263
2264 case FILTER_CMP_GT:
2265 if (!op)
2266 op = ">";
2267
2268 case FILTER_CMP_LT:
2269 if (!op)
2270 op = "<";
2271
2272 case FILTER_CMP_GE:
2273 if (!op)
2274 op = ">=";
2275
2276 case FILTER_CMP_LE:
2277 if (!op)
2278 op = "<=";
2279
2280 asprintf(&str, "%s %s %s", lstr, op, rstr);
2281 break;
2282
2283 default:
2284
2285 break;
2286 }
2287
2288out:
2289 free(lstr);
2290 free(rstr);
2291 return str;
2292}
2293
2294static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2295{
2296 char *str = NULL;
2297 char *op = NULL;
2298
2299 switch (arg->str.type) {
2300 case FILTER_CMP_MATCH:
2301 op = "==";
2302
2303 case FILTER_CMP_NOT_MATCH:
2304 if (!op)
2305 op = "!=";
2306
2307 case FILTER_CMP_REGEX:
2308 if (!op)
2309 op = "=~";
2310
2311 case FILTER_CMP_NOT_REGEX:
2312 if (!op)
2313 op = "!~";
2314
2315 asprintf(&str, "%s %s \"%s\"",
2316 arg->str.field->name, op, arg->str.val);
2317 break;
2318
2319 default:
2320
2321 break;
2322 }
2323 return str;
2324}
2325
2326static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2327{
2328 char *str = NULL;
2329
2330 switch (arg->type) {
2331 case FILTER_ARG_BOOLEAN:
2332 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
2333 return str;
2334
2335 case FILTER_ARG_OP:
2336 return op_to_str(filter, arg);
2337
2338 case FILTER_ARG_NUM:
2339 return num_to_str(filter, arg);
2340
2341 case FILTER_ARG_STR:
2342 return str_to_str(filter, arg);
2343
2344 case FILTER_ARG_VALUE:
2345 return val_to_str(filter, arg);
2346
2347 case FILTER_ARG_FIELD:
2348 return field_to_str(filter, arg);
2349
2350 case FILTER_ARG_EXP:
2351 return exp_to_str(filter, arg);
2352
2353 default:
2354
2355 return NULL;
2356 }
2357
2358}
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369char *
2370pevent_filter_make_string(struct event_filter *filter, int event_id)
2371{
2372 struct filter_type *filter_type;
2373
2374 if (!filter->filters)
2375 return NULL;
2376
2377 filter_type = find_filter_type(filter, event_id);
2378
2379 if (!filter_type)
2380 return NULL;
2381
2382 return arg_to_str(filter, filter_type->filter);
2383}
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2395{
2396 struct filter_type *filter_type1;
2397 struct filter_type *filter_type2;
2398 char *str1, *str2;
2399 int result;
2400 int i;
2401
2402
2403 if (filter1->filters != filter2->filters)
2404 return 0;
2405 if (!filter1->filters && !filter2->filters)
2406 return 1;
2407
2408
2409
2410
2411
2412 for (i = 0; i < filter1->filters; i++) {
2413 filter_type1 = &filter1->event_filters[i];
2414 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2415 if (!filter_type2)
2416 break;
2417 if (filter_type1->filter->type != filter_type2->filter->type)
2418 break;
2419 switch (filter_type1->filter->type) {
2420 case FILTER_TRIVIAL_FALSE:
2421 case FILTER_TRIVIAL_TRUE:
2422
2423 continue;
2424 default:
2425 break;
2426 }
2427
2428 str1 = arg_to_str(filter1, filter_type1->filter);
2429 str2 = arg_to_str(filter2, filter_type2->filter);
2430 if (str1 && str2)
2431 result = strcmp(str1, str2) != 0;
2432 else
2433
2434 result = 1;
2435
2436 free(str1);
2437 free(str2);
2438 if (result)
2439 break;
2440 }
2441
2442 if (i < filter1->filters)
2443 return 0;
2444 return 1;
2445}
2446
2447