Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[cascardo/linux.git] / tools / lib / traceevent / parse-filter.c
index dfcfe2c..ad17855 100644 (file)
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
            pevent_peek_char() == '~') {
                /* append it */
-               *tok = malloc(3);
+               *tok = malloc_or_die(3);
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
        if (filter_type)
                return filter_type;
 
-       if (!filter->filters)
-               filter->event_filters =
-                       malloc_or_die(sizeof(*filter->event_filters));
-       else {
-               filter->event_filters =
-                       realloc(filter->event_filters,
-                               sizeof(*filter->event_filters) *
-                               (filter->filters + 1));
-               if (!filter->event_filters)
-                       die("Could not allocate filter");
-       }
+       filter->event_filters = realloc(filter->event_filters,
+                                       sizeof(*filter->event_filters) *
+                                       (filter->filters + 1));
+       if (!filter->event_filters)
+               die("Could not allocate filter");
 
        for (i = 0; i < filter->filters; i++) {
                if (filter->event_filters[i].event_id > id)
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
 {
        struct filter_type *filter_type;
        int count = 0;
-       int *ids;
+       int *ids = NULL;
        int i;
 
        if (!filter->filters)
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
                default:
                        break;
                }
-               if (count)
-                       ids = realloc(ids, sizeof(*ids) * (count + 1));
-               else
-                       ids = malloc(sizeof(*ids));
+
+               ids = realloc(ids, sizeof(*ids) * (count + 1));
                if (!ids)
                        die("Can't allocate ids");
                ids[count++] = filter_type->event_id;
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
 
 static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
 {
-       const char *val = record->data + arg->str.field->offset;
+       struct event_format *event;
+       struct pevent *pevent;
+       unsigned long long addr;
+       const char *val = NULL;
+       char hex[64];
 
-       /*
-        * We need to copy the data since we can't be sure the field
-        * is null terminated.
-        */
-       if (*(val + arg->str.field->size - 1)) {
-               /* copy it */
-               memcpy(arg->str.buffer, val, arg->str.field->size);
-               /* the buffer is already NULL terminated */
-               val = arg->str.buffer;
+       /* If the field is not a string convert it */
+       if (arg->str.field->flags & FIELD_IS_STRING) {
+               val = record->data + arg->str.field->offset;
+
+               /*
+                * We need to copy the data since we can't be sure the field
+                * is null terminated.
+                */
+               if (*(val + arg->str.field->size - 1)) {
+                       /* copy it */
+                       memcpy(arg->str.buffer, val, arg->str.field->size);
+                       /* the buffer is already NULL terminated */
+                       val = arg->str.buffer;
+               }
+
+       } else {
+               event = arg->str.field->event;
+               pevent = event->pevent;
+               addr = get_value(event, arg->str.field, record);
+
+               if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
+                       /* convert to a kernel symbol */
+                       val = pevent_find_function(pevent, addr);
+
+               if (val == NULL) {
+                       /* just use the hex of the string name */
+                       snprintf(hex, 64, "0x%llx", addr);
+                       val = hex;
+               }
        }
+
        return val;
 }
 
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        char *lstr;
        char *rstr;
        char *op;
-       char *str;
+       char *str = NULL;
        int len;
 
        lstr = arg_to_str(filter, arg->exp.left);
        rstr = arg_to_str(filter, arg->exp.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->exp.type) {
        case FILTER_EXP_ADD:
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
        str = malloc_or_die(len);
        snprintf(str, len, "%s %s %s", lstr, op, rstr);
+out:
        free(lstr);
        free(rstr);
 
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
 
        lstr = arg_to_str(filter, arg->num.left);
        rstr = arg_to_str(filter, arg->num.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->num.type) {
        case FILTER_CMP_EQ:
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
                break;
        }
 
+out:
        free(lstr);
        free(rstr);
        return str;
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
                /* The best way to compare complex filters is with strings */
                str1 = arg_to_str(filter1, filter_type1->filter);
                str2 = arg_to_str(filter2, filter_type2->filter);
-               result = strcmp(str1, str2) != 0;
+               if (str1 && str2)
+                       result = strcmp(str1, str2) != 0;
+               else
+                       /* bail out if allocation fails */
+                       result = 1;
+
                free(str1);
                free(str2);
                if (result)