Merge branch 'stable/bug.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / tools / perf / util / session.c
index caa2245..f5a8fbd 100644 (file)
@@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force)
                goto out_close;
        }
 
+       if (!perf_evlist__valid_sample_type(self->evlist)) {
+               pr_err("non matching sample_type");
+               goto out_close;
+       }
+
+       if (!perf_evlist__valid_sample_id_all(self->evlist)) {
+               pr_err("non matching sample_id_all");
+               goto out_close;
+       }
+
        self->size = input_stat.st_size;
        return 0;
 
@@ -97,6 +107,7 @@ out:
 void perf_session__update_sample_type(struct perf_session *self)
 {
        self->sample_type = perf_evlist__sample_type(self->evlist);
+       self->sample_size = __perf_evsel__sample_size(self->sample_type);
        self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
        perf_session__id_header_size(self);
 }
@@ -479,6 +490,7 @@ static void flush_sample_queue(struct perf_session *s,
        struct perf_sample sample;
        u64 limit = os->next_flush;
        u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
+       int ret;
 
        if (!ops->ordered_samples || !limit)
                return;
@@ -487,9 +499,12 @@ static void flush_sample_queue(struct perf_session *s,
                if (iter->timestamp > limit)
                        break;
 
-               perf_session__parse_sample(s, iter->event, &sample);
-               perf_session_deliver_event(s, iter->event, &sample, ops,
-                                          iter->file_offset);
+               ret = perf_session__parse_sample(s, iter->event, &sample);
+               if (ret)
+                       pr_err("Can't parse sample, err = %d\n", ret);
+               else
+                       perf_session_deliver_event(s, iter->event, &sample, ops,
+                                                  iter->file_offset);
 
                os->last_flush = iter->timestamp;
                list_del(&iter->list);
@@ -805,7 +820,9 @@ static int perf_session__process_event(struct perf_session *session,
        /*
         * For all kernel events we get the sample data
         */
-       perf_session__parse_sample(session, event, &sample);
+       ret = perf_session__parse_sample(session, event, &sample);
+       if (ret)
+               return ret;
 
        /* Preprocess sample records - precheck callchains */
        if (perf_session__preprocess_sample(session, event, &sample))
@@ -953,6 +970,30 @@ out_err:
        return err;
 }
 
+static union perf_event *
+fetch_mmaped_event(struct perf_session *session,
+                  u64 head, size_t mmap_size, char *buf)
+{
+       union perf_event *event;
+
+       /*
+        * Ensure we have enough space remaining to read
+        * the size of the event in the headers.
+        */
+       if (head + sizeof(event->header) > mmap_size)
+               return NULL;
+
+       event = (union perf_event *)(buf + head);
+
+       if (session->header.needs_swap)
+               perf_event_header__bswap(&event->header);
+
+       if (head + event->header.size > mmap_size)
+               return NULL;
+
+       return event;
+}
+
 int __perf_session__process_events(struct perf_session *session,
                                   u64 data_offset, u64 data_size,
                                   u64 file_size, struct perf_event_ops *ops)
@@ -1007,15 +1048,8 @@ remap:
        file_pos = file_offset + head;
 
 more:
-       event = (union perf_event *)(buf + head);
-
-       if (session->header.needs_swap)
-               perf_event_header__bswap(&event->header);
-       size = event->header.size;
-       if (size == 0)
-               size = 8;
-
-       if (head + event->header.size > mmap_size) {
+       event = fetch_mmaped_event(session, head, mmap_size, buf);
+       if (!event) {
                if (mmaps[map_idx]) {
                        munmap(mmaps[map_idx], mmap_size);
                        mmaps[map_idx] = NULL;
@@ -1156,6 +1190,18 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
        return ret;
 }
 
+struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
+                                             unsigned int type)
+{
+       struct perf_evsel *pos;
+
+       list_for_each_entry(pos, &session->evlist->entries, node) {
+               if (pos->attr.type == type)
+                       return pos;
+       }
+       return NULL;
+}
+
 void perf_session__print_symbols(union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_session *session)