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