~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/lib/traceevent/parse-filter.c

Version: ~ [ linux-5.5-rc1 ] ~ [ linux-5.4.2 ] ~ [ linux-5.3.15 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.88 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.158 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.206 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.206 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 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 
 78 static void free_token(char *token)
 79 {
 80         pevent_free_token(token);
 81 }
 82 
 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 
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 *
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 *
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  */
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 
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 
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 
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 
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
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 
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 *
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 *
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 *
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 *
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 
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 *
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 
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 
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 
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 
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 
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 */
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
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
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 
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  */
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 
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  */
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  */
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 
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 
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  */
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  */
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  */
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  */
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 *
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
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
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
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 
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 
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 
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 
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 
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  */
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  */
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 
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 
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 
2025 static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2026 {
2027         return strdup(arg->field.field->name);
2028 }
2029 
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 
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 
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 
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 *
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  */
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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp