diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/build-id.c | 1 | ||||
-rw-r--r-- | tools/perf/util/header.c | 57 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 1 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-perl.c | 1 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 1 | ||||
-rw-r--r-- | tools/perf/util/session.c | 25 | ||||
-rw-r--r-- | tools/perf/util/session.h | 7 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 25 | ||||
-rw-r--r-- | tools/perf/util/trace-event-scripting.c | 1 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 1 |
10 files changed, 103 insertions, 17 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 31f934af9861..a91cd99f26ea 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | static int build_id__mark_dso_hit(union perf_event *event, | 17 | static int build_id__mark_dso_hit(union perf_event *event, |
18 | struct perf_sample *sample __used, | 18 | struct perf_sample *sample __used, |
19 | struct perf_evsel *evsel __used, | ||
19 | struct perf_session *session) | 20 | struct perf_session *session) |
20 | { | 21 | { |
21 | struct addr_location al; | 22 | struct addr_location al; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e5230c0ef95b..93862a8027ea 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -695,13 +695,50 @@ out: | |||
695 | return err; | 695 | return err; |
696 | } | 696 | } |
697 | 697 | ||
698 | static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, | ||
699 | int input, u64 offset, u64 size) | ||
700 | { | ||
701 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
702 | struct { | ||
703 | struct perf_event_header header; | ||
704 | u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; | ||
705 | char filename[0]; | ||
706 | } old_bev; | ||
707 | struct build_id_event bev; | ||
708 | char filename[PATH_MAX]; | ||
709 | u64 limit = offset + size; | ||
710 | |||
711 | while (offset < limit) { | ||
712 | ssize_t len; | ||
713 | |||
714 | if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) | ||
715 | return -1; | ||
716 | |||
717 | if (header->needs_swap) | ||
718 | perf_event_header__bswap(&old_bev.header); | ||
719 | |||
720 | len = old_bev.header.size - sizeof(old_bev); | ||
721 | if (read(input, filename, len) != len) | ||
722 | return -1; | ||
723 | |||
724 | bev.header = old_bev.header; | ||
725 | bev.pid = 0; | ||
726 | memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); | ||
727 | __event_process_build_id(&bev, filename, session); | ||
728 | |||
729 | offset += bev.header.size; | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
698 | static int perf_header__read_build_ids(struct perf_header *header, | 735 | static int perf_header__read_build_ids(struct perf_header *header, |
699 | int input, u64 offset, u64 size) | 736 | int input, u64 offset, u64 size) |
700 | { | 737 | { |
701 | struct perf_session *session = container_of(header, struct perf_session, header); | 738 | struct perf_session *session = container_of(header, struct perf_session, header); |
702 | struct build_id_event bev; | 739 | struct build_id_event bev; |
703 | char filename[PATH_MAX]; | 740 | char filename[PATH_MAX]; |
704 | u64 limit = offset + size; | 741 | u64 limit = offset + size, orig_offset = offset; |
705 | int err = -1; | 742 | int err = -1; |
706 | 743 | ||
707 | while (offset < limit) { | 744 | while (offset < limit) { |
@@ -716,6 +753,24 @@ static int perf_header__read_build_ids(struct perf_header *header, | |||
716 | len = bev.header.size - sizeof(bev); | 753 | len = bev.header.size - sizeof(bev); |
717 | if (read(input, filename, len) != len) | 754 | if (read(input, filename, len) != len) |
718 | goto out; | 755 | goto out; |
756 | /* | ||
757 | * The a1645ce1 changeset: | ||
758 | * | ||
759 | * "perf: 'perf kvm' tool for monitoring guest performance from host" | ||
760 | * | ||
761 | * Added a field to struct build_id_event that broke the file | ||
762 | * format. | ||
763 | * | ||
764 | * Since the kernel build-id is the first entry, process the | ||
765 | * table using the old format if the well known | ||
766 | * '[kernel.kallsyms]' string for the kernel build-id has the | ||
767 | * first 4 characters chopped off (where the pid_t sits). | ||
768 | */ | ||
769 | if (memcmp(filename, "nel.kallsyms]", 13) == 0) { | ||
770 | if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) | ||
771 | return -1; | ||
772 | return perf_header__read_build_ids_abi_quirk(header, input, offset, size); | ||
773 | } | ||
719 | 774 | ||
720 | __event_process_build_id(&bev, filename, session); | 775 | __event_process_build_id(&bev, filename, session); |
721 | 776 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index cb6858a2f9a3..3beb97c4d822 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -29,6 +29,7 @@ struct events_stats { | |||
29 | u32 nr_events[PERF_RECORD_HEADER_MAX]; | 29 | u32 nr_events[PERF_RECORD_HEADER_MAX]; |
30 | u32 nr_unknown_events; | 30 | u32 nr_unknown_events; |
31 | u32 nr_invalid_chains; | 31 | u32 nr_invalid_chains; |
32 | u32 nr_unknown_id; | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | enum hist_column { | 35 | enum hist_column { |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 621427212e86..74350ffb57fe 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -247,6 +247,7 @@ static inline struct event *find_cache_event(int type) | |||
247 | 247 | ||
248 | static void perl_process_event(union perf_event *pevent __unused, | 248 | static void perl_process_event(union perf_event *pevent __unused, |
249 | struct perf_sample *sample, | 249 | struct perf_sample *sample, |
250 | struct perf_evsel *evsel, | ||
250 | struct perf_session *session __unused, | 251 | struct perf_session *session __unused, |
251 | struct thread *thread) | 252 | struct thread *thread) |
252 | { | 253 | { |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1b85d6055159..6ccf70e8d8f2 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -206,6 +206,7 @@ static inline struct event *find_cache_event(int type) | |||
206 | 206 | ||
207 | static void python_process_event(union perf_event *pevent __unused, | 207 | static void python_process_event(union perf_event *pevent __unused, |
208 | struct perf_sample *sample, | 208 | struct perf_sample *sample, |
209 | struct perf_evsel *evsel __unused, | ||
209 | struct perf_session *session __unused, | 210 | struct perf_session *session __unused, |
210 | struct thread *thread) | 211 | struct thread *thread) |
211 | { | 212 | { |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c68cf40764f9..caa224522fea 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -280,6 +280,15 @@ static int process_event_synth_stub(union perf_event *event __used, | |||
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int process_event_sample_stub(union perf_event *event __used, | ||
284 | struct perf_sample *sample __used, | ||
285 | struct perf_evsel *evsel __used, | ||
286 | struct perf_session *session __used) | ||
287 | { | ||
288 | dump_printf(": unhandled!\n"); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
283 | static int process_event_stub(union perf_event *event __used, | 292 | static int process_event_stub(union perf_event *event __used, |
284 | struct perf_sample *sample __used, | 293 | struct perf_sample *sample __used, |
285 | struct perf_session *session __used) | 294 | struct perf_session *session __used) |
@@ -303,7 +312,7 @@ static int process_finished_round(union perf_event *event, | |||
303 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) | 312 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) |
304 | { | 313 | { |
305 | if (handler->sample == NULL) | 314 | if (handler->sample == NULL) |
306 | handler->sample = process_event_stub; | 315 | handler->sample = process_event_sample_stub; |
307 | if (handler->mmap == NULL) | 316 | if (handler->mmap == NULL) |
308 | handler->mmap = process_event_stub; | 317 | handler->mmap = process_event_stub; |
309 | if (handler->comm == NULL) | 318 | if (handler->comm == NULL) |
@@ -698,12 +707,19 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
698 | struct perf_event_ops *ops, | 707 | struct perf_event_ops *ops, |
699 | u64 file_offset) | 708 | u64 file_offset) |
700 | { | 709 | { |
710 | struct perf_evsel *evsel; | ||
711 | |||
701 | dump_event(session, event, file_offset, sample); | 712 | dump_event(session, event, file_offset, sample); |
702 | 713 | ||
703 | switch (event->header.type) { | 714 | switch (event->header.type) { |
704 | case PERF_RECORD_SAMPLE: | 715 | case PERF_RECORD_SAMPLE: |
705 | dump_sample(session, event, sample); | 716 | dump_sample(session, event, sample); |
706 | return ops->sample(event, sample, session); | 717 | evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
718 | if (evsel == NULL) { | ||
719 | ++session->hists.stats.nr_unknown_id; | ||
720 | return -1; | ||
721 | } | ||
722 | return ops->sample(event, sample, evsel, session); | ||
707 | case PERF_RECORD_MMAP: | 723 | case PERF_RECORD_MMAP: |
708 | return ops->mmap(event, sample, session); | 724 | return ops->mmap(event, sample, session); |
709 | case PERF_RECORD_COMM: | 725 | case PERF_RECORD_COMM: |
@@ -845,6 +861,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
845 | session->hists.stats.nr_unknown_events); | 861 | session->hists.stats.nr_unknown_events); |
846 | } | 862 | } |
847 | 863 | ||
864 | if (session->hists.stats.nr_unknown_id != 0) { | ||
865 | ui__warning("%u samples with id not present in the header\n", | ||
866 | session->hists.stats.nr_unknown_id); | ||
867 | } | ||
868 | |||
848 | if (session->hists.stats.nr_invalid_chains != 0) { | 869 | if (session->hists.stats.nr_invalid_chains != 0) { |
849 | ui__warning("Found invalid callchains!\n\n" | 870 | ui__warning("Found invalid callchains!\n\n" |
850 | "%u out of %u events were discarded for this reason.\n\n" | 871 | "%u out of %u events were discarded for this reason.\n\n" |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0b3c9afecaa9..1ac481fc1100 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -55,8 +55,11 @@ struct perf_session { | |||
55 | char filename[0]; | 55 | char filename[0]; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct perf_evsel; | ||
58 | struct perf_event_ops; | 59 | struct perf_event_ops; |
59 | 60 | ||
61 | typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample, | ||
62 | struct perf_evsel *evsel, struct perf_session *session); | ||
60 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, | 63 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, |
61 | struct perf_session *session); | 64 | struct perf_session *session); |
62 | typedef int (*event_synth_op)(union perf_event *self, | 65 | typedef int (*event_synth_op)(union perf_event *self, |
@@ -65,8 +68,8 @@ typedef int (*event_op2)(union perf_event *self, struct perf_session *session, | |||
65 | struct perf_event_ops *ops); | 68 | struct perf_event_ops *ops); |
66 | 69 | ||
67 | struct perf_event_ops { | 70 | struct perf_event_ops { |
68 | event_op sample, | 71 | event_sample sample; |
69 | mmap, | 72 | event_op mmap, |
70 | comm, | 73 | comm, |
71 | fork, | 74 | fork, |
72 | exit, | 75 | exit, |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 651dbfe7f4f3..17df793c8924 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1486,7 +1486,9 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1486 | * On the first pass, only load images if they have a full symtab. | 1486 | * On the first pass, only load images if they have a full symtab. |
1487 | * Failing that, do a second pass where we accept .dynsym also | 1487 | * Failing that, do a second pass where we accept .dynsym also |
1488 | */ | 1488 | */ |
1489 | for (self->symtab_type = SYMTAB__BUILD_ID_CACHE, want_symtab = 1; | 1489 | want_symtab = 1; |
1490 | restart: | ||
1491 | for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; | ||
1490 | self->symtab_type != SYMTAB__NOT_FOUND; | 1492 | self->symtab_type != SYMTAB__NOT_FOUND; |
1491 | self->symtab_type++) { | 1493 | self->symtab_type++) { |
1492 | switch (self->symtab_type) { | 1494 | switch (self->symtab_type) { |
@@ -1536,17 +1538,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1536 | snprintf(name, size, "%s%s", symbol_conf.symfs, | 1538 | snprintf(name, size, "%s%s", symbol_conf.symfs, |
1537 | self->long_name); | 1539 | self->long_name); |
1538 | break; | 1540 | break; |
1539 | 1541 | default:; | |
1540 | default: | ||
1541 | /* | ||
1542 | * If we wanted a full symtab but no image had one, | ||
1543 | * relax our requirements and repeat the search. | ||
1544 | */ | ||
1545 | if (want_symtab) { | ||
1546 | want_symtab = 0; | ||
1547 | self->symtab_type = SYMTAB__BUILD_ID_CACHE; | ||
1548 | } else | ||
1549 | continue; | ||
1550 | } | 1542 | } |
1551 | 1543 | ||
1552 | /* Name is now the name of the next image to try */ | 1544 | /* Name is now the name of the next image to try */ |
@@ -1573,6 +1565,15 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1573 | } | 1565 | } |
1574 | } | 1566 | } |
1575 | 1567 | ||
1568 | /* | ||
1569 | * If we wanted a full symtab but no image had one, | ||
1570 | * relax our requirements and repeat the search. | ||
1571 | */ | ||
1572 | if (ret <= 0 && want_symtab) { | ||
1573 | want_symtab = 0; | ||
1574 | goto restart; | ||
1575 | } | ||
1576 | |||
1576 | free(name); | 1577 | free(name); |
1577 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) | 1578 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) |
1578 | return 0; | 1579 | return 0; |
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 66f4b78737ab..c9dcbec7d800 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c | |||
@@ -38,6 +38,7 @@ static int stop_script_unsupported(void) | |||
38 | 38 | ||
39 | static void process_event_unsupported(union perf_event *event __unused, | 39 | static void process_event_unsupported(union perf_event *event __unused, |
40 | struct perf_sample *sample __unused, | 40 | struct perf_sample *sample __unused, |
41 | struct perf_evsel *evsel __unused, | ||
41 | struct perf_session *session __unused, | 42 | struct perf_session *session __unused, |
42 | struct thread *thread __unused) | 43 | struct thread *thread __unused) |
43 | { | 44 | { |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index b04da5722437..f674dda3363b 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -280,6 +280,7 @@ struct scripting_ops { | |||
280 | int (*stop_script) (void); | 280 | int (*stop_script) (void); |
281 | void (*process_event) (union perf_event *event, | 281 | void (*process_event) (union perf_event *event, |
282 | struct perf_sample *sample, | 282 | struct perf_sample *sample, |
283 | struct perf_evsel *evsel, | ||
283 | struct perf_session *session, | 284 | struct perf_session *session, |
284 | struct thread *thread); | 285 | struct thread *thread); |
285 | int (*generate_script) (const char *outfile); | 286 | int (*generate_script) (const char *outfile); |