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