aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c318
1 files changed, 215 insertions, 103 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index cf1fe01b7e89..70ffa41518f3 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1,4 +1,5 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <traceevent/event-parse.h>
2 3
3#include <byteswap.h> 4#include <byteswap.h>
4#include <unistd.h> 5#include <unistd.h>
@@ -12,7 +13,6 @@
12#include "sort.h" 13#include "sort.h"
13#include "util.h" 14#include "util.h"
14#include "cpumap.h" 15#include "cpumap.h"
15#include "event-parse.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "vdso.h" 17#include "vdso.h"
18 18
@@ -24,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force)
24 self->fd_pipe = true; 24 self->fd_pipe = true;
25 self->fd = STDIN_FILENO; 25 self->fd = STDIN_FILENO;
26 26
27 if (perf_session__read_header(self, self->fd) < 0) 27 if (perf_session__read_header(self) < 0)
28 pr_err("incompatible file format (rerun with -v to learn more)"); 28 pr_err("incompatible file format (rerun with -v to learn more)");
29 29
30 return 0; 30 return 0;
@@ -56,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force)
56 goto out_close; 56 goto out_close;
57 } 57 }
58 58
59 if (perf_session__read_header(self, self->fd) < 0) { 59 if (perf_session__read_header(self) < 0) {
60 pr_err("incompatible file format (rerun with -v to learn more)"); 60 pr_err("incompatible file format (rerun with -v to learn more)");
61 goto out_close; 61 goto out_close;
62 } 62 }
@@ -71,6 +71,11 @@ static int perf_session__open(struct perf_session *self, bool force)
71 goto out_close; 71 goto out_close;
72 } 72 }
73 73
74 if (!perf_evlist__valid_read_format(self->evlist)) {
75 pr_err("non matching read_format");
76 goto out_close;
77 }
78
74 self->size = input_stat.st_size; 79 self->size = input_stat.st_size;
75 return 0; 80 return 0;
76 81
@@ -193,7 +198,9 @@ void perf_session__delete(struct perf_session *self)
193 vdso__exit(); 198 vdso__exit();
194} 199}
195 200
196static int process_event_synth_tracing_data_stub(union perf_event *event 201static int process_event_synth_tracing_data_stub(struct perf_tool *tool
202 __maybe_unused,
203 union perf_event *event
197 __maybe_unused, 204 __maybe_unused,
198 struct perf_session *session 205 struct perf_session *session
199 __maybe_unused) 206 __maybe_unused)
@@ -202,7 +209,8 @@ static int process_event_synth_tracing_data_stub(union perf_event *event
202 return 0; 209 return 0;
203} 210}
204 211
205static int process_event_synth_attr_stub(union perf_event *event __maybe_unused, 212static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
213 union perf_event *event __maybe_unused,
206 struct perf_evlist **pevlist 214 struct perf_evlist **pevlist
207 __maybe_unused) 215 __maybe_unused)
208{ 216{
@@ -238,18 +246,11 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
238 return 0; 246 return 0;
239} 247}
240 248
241static int process_event_type_stub(struct perf_tool *tool __maybe_unused,
242 union perf_event *event __maybe_unused)
243{
244 dump_printf(": unhandled!\n");
245 return 0;
246}
247
248static int process_finished_round(struct perf_tool *tool, 249static int process_finished_round(struct perf_tool *tool,
249 union perf_event *event, 250 union perf_event *event,
250 struct perf_session *session); 251 struct perf_session *session);
251 252
252static void perf_tool__fill_defaults(struct perf_tool *tool) 253void perf_tool__fill_defaults(struct perf_tool *tool)
253{ 254{
254 if (tool->sample == NULL) 255 if (tool->sample == NULL)
255 tool->sample = process_event_sample_stub; 256 tool->sample = process_event_sample_stub;
@@ -271,8 +272,6 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)
271 tool->unthrottle = process_event_stub; 272 tool->unthrottle = process_event_stub;
272 if (tool->attr == NULL) 273 if (tool->attr == NULL)
273 tool->attr = process_event_synth_attr_stub; 274 tool->attr = process_event_synth_attr_stub;
274 if (tool->event_type == NULL)
275 tool->event_type = process_event_type_stub;
276 if (tool->tracing_data == NULL) 275 if (tool->tracing_data == NULL)
277 tool->tracing_data = process_event_synth_tracing_data_stub; 276 tool->tracing_data = process_event_synth_tracing_data_stub;
278 if (tool->build_id == NULL) 277 if (tool->build_id == NULL)
@@ -352,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event,
352 } 351 }
353} 352}
354 353
354static void perf_event__mmap2_swap(union perf_event *event,
355 bool sample_id_all)
356{
357 event->mmap2.pid = bswap_32(event->mmap2.pid);
358 event->mmap2.tid = bswap_32(event->mmap2.tid);
359 event->mmap2.start = bswap_64(event->mmap2.start);
360 event->mmap2.len = bswap_64(event->mmap2.len);
361 event->mmap2.pgoff = bswap_64(event->mmap2.pgoff);
362 event->mmap2.maj = bswap_32(event->mmap2.maj);
363 event->mmap2.min = bswap_32(event->mmap2.min);
364 event->mmap2.ino = bswap_64(event->mmap2.ino);
365
366 if (sample_id_all) {
367 void *data = &event->mmap2.filename;
368
369 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
370 swap_sample_id_all(event, data);
371 }
372}
355static void perf_event__task_swap(union perf_event *event, bool sample_id_all) 373static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
356{ 374{
357 event->fork.pid = bswap_32(event->fork.pid); 375 event->fork.pid = bswap_32(event->fork.pid);
@@ -456,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event,
456 474
457static perf_event__swap_op perf_event__swap_ops[] = { 475static perf_event__swap_op perf_event__swap_ops[] = {
458 [PERF_RECORD_MMAP] = perf_event__mmap_swap, 476 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
477 [PERF_RECORD_MMAP2] = perf_event__mmap2_swap,
459 [PERF_RECORD_COMM] = perf_event__comm_swap, 478 [PERF_RECORD_COMM] = perf_event__comm_swap,
460 [PERF_RECORD_FORK] = perf_event__task_swap, 479 [PERF_RECORD_FORK] = perf_event__task_swap,
461 [PERF_RECORD_EXIT] = perf_event__task_swap, 480 [PERF_RECORD_EXIT] = perf_event__task_swap,
@@ -496,7 +515,7 @@ static int perf_session_deliver_event(struct perf_session *session,
496 u64 file_offset); 515 u64 file_offset);
497 516
498static int flush_sample_queue(struct perf_session *s, 517static int flush_sample_queue(struct perf_session *s,
499 struct perf_tool *tool) 518 struct perf_tool *tool)
500{ 519{
501 struct ordered_samples *os = &s->ordered_samples; 520 struct ordered_samples *os = &s->ordered_samples;
502 struct list_head *head = &os->samples; 521 struct list_head *head = &os->samples;
@@ -505,12 +524,16 @@ static int flush_sample_queue(struct perf_session *s,
505 u64 limit = os->next_flush; 524 u64 limit = os->next_flush;
506 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 525 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
507 unsigned idx = 0, progress_next = os->nr_samples / 16; 526 unsigned idx = 0, progress_next = os->nr_samples / 16;
527 bool show_progress = limit == ULLONG_MAX;
508 int ret; 528 int ret;
509 529
510 if (!tool->ordered_samples || !limit) 530 if (!tool->ordered_samples || !limit)
511 return 0; 531 return 0;
512 532
513 list_for_each_entry_safe(iter, tmp, head, list) { 533 list_for_each_entry_safe(iter, tmp, head, list) {
534 if (session_done())
535 return 0;
536
514 if (iter->timestamp > limit) 537 if (iter->timestamp > limit)
515 break; 538 break;
516 539
@@ -527,7 +550,7 @@ static int flush_sample_queue(struct perf_session *s,
527 os->last_flush = iter->timestamp; 550 os->last_flush = iter->timestamp;
528 list_del(&iter->list); 551 list_del(&iter->list);
529 list_add(&iter->list, &os->sample_cache); 552 list_add(&iter->list, &os->sample_cache);
530 if (++idx >= progress_next) { 553 if (show_progress && (++idx >= progress_next)) {
531 progress_next += os->nr_samples / 16; 554 progress_next += os->nr_samples / 16;
532 ui_progress__update(idx, os->nr_samples, 555 ui_progress__update(idx, os->nr_samples,
533 "Processing time ordered events..."); 556 "Processing time ordered events...");
@@ -644,7 +667,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
644 667
645#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) 668#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
646 669
647static int perf_session_queue_event(struct perf_session *s, union perf_event *event, 670int perf_session_queue_event(struct perf_session *s, union perf_event *event,
648 struct perf_sample *sample, u64 file_offset) 671 struct perf_sample *sample, u64 file_offset)
649{ 672{
650 struct ordered_samples *os = &s->ordered_samples; 673 struct ordered_samples *os = &s->ordered_samples;
@@ -740,7 +763,7 @@ static void perf_session__print_tstamp(struct perf_session *session,
740 union perf_event *event, 763 union perf_event *event,
741 struct perf_sample *sample) 764 struct perf_sample *sample)
742{ 765{
743 u64 sample_type = perf_evlist__sample_type(session->evlist); 766 u64 sample_type = __perf_evlist__combined_sample_type(session->evlist);
744 767
745 if (event->header.type != PERF_RECORD_SAMPLE && 768 if (event->header.type != PERF_RECORD_SAMPLE &&
746 !perf_evlist__sample_id_all(session->evlist)) { 769 !perf_evlist__sample_id_all(session->evlist)) {
@@ -755,6 +778,36 @@ static void perf_session__print_tstamp(struct perf_session *session,
755 printf("%" PRIu64 " ", sample->time); 778 printf("%" PRIu64 " ", sample->time);
756} 779}
757 780
781static void sample_read__printf(struct perf_sample *sample, u64 read_format)
782{
783 printf("... sample_read:\n");
784
785 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
786 printf("...... time enabled %016" PRIx64 "\n",
787 sample->read.time_enabled);
788
789 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
790 printf("...... time running %016" PRIx64 "\n",
791 sample->read.time_running);
792
793 if (read_format & PERF_FORMAT_GROUP) {
794 u64 i;
795
796 printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
797
798 for (i = 0; i < sample->read.group.nr; i++) {
799 struct sample_read_value *value;
800
801 value = &sample->read.group.values[i];
802 printf("..... id %016" PRIx64
803 ", value %016" PRIx64 "\n",
804 value->id, value->value);
805 }
806 } else
807 printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
808 sample->read.one.id, sample->read.one.value);
809}
810
758static void dump_event(struct perf_session *session, union perf_event *event, 811static void dump_event(struct perf_session *session, union perf_event *event,
759 u64 file_offset, struct perf_sample *sample) 812 u64 file_offset, struct perf_sample *sample)
760{ 813{
@@ -804,11 +857,15 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
804 857
805 if (sample_type & PERF_SAMPLE_DATA_SRC) 858 if (sample_type & PERF_SAMPLE_DATA_SRC)
806 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 859 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
860
861 if (sample_type & PERF_SAMPLE_READ)
862 sample_read__printf(sample, evsel->attr.read_format);
807} 863}
808 864
809static struct machine * 865static struct machine *
810 perf_session__find_machine_for_cpumode(struct perf_session *session, 866 perf_session__find_machine_for_cpumode(struct perf_session *session,
811 union perf_event *event) 867 union perf_event *event,
868 struct perf_sample *sample)
812{ 869{
813 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 870 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
814 871
@@ -817,10 +874,11 @@ static struct machine *
817 (cpumode == PERF_RECORD_MISC_GUEST_USER))) { 874 (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
818 u32 pid; 875 u32 pid;
819 876
820 if (event->header.type == PERF_RECORD_MMAP) 877 if (event->header.type == PERF_RECORD_MMAP
878 || event->header.type == PERF_RECORD_MMAP2)
821 pid = event->mmap.pid; 879 pid = event->mmap.pid;
822 else 880 else
823 pid = event->ip.pid; 881 pid = sample->pid;
824 882
825 return perf_session__findnew_machine(session, pid); 883 return perf_session__findnew_machine(session, pid);
826 } 884 }
@@ -828,6 +886,75 @@ static struct machine *
828 return &session->machines.host; 886 return &session->machines.host;
829} 887}
830 888
889static int deliver_sample_value(struct perf_session *session,
890 struct perf_tool *tool,
891 union perf_event *event,
892 struct perf_sample *sample,
893 struct sample_read_value *v,
894 struct machine *machine)
895{
896 struct perf_sample_id *sid;
897
898 sid = perf_evlist__id2sid(session->evlist, v->id);
899 if (sid) {
900 sample->id = v->id;
901 sample->period = v->value - sid->period;
902 sid->period = v->value;
903 }
904
905 if (!sid || sid->evsel == NULL) {
906 ++session->stats.nr_unknown_id;
907 return 0;
908 }
909
910 return tool->sample(tool, event, sample, sid->evsel, machine);
911}
912
913static int deliver_sample_group(struct perf_session *session,
914 struct perf_tool *tool,
915 union perf_event *event,
916 struct perf_sample *sample,
917 struct machine *machine)
918{
919 int ret = -EINVAL;
920 u64 i;
921
922 for (i = 0; i < sample->read.group.nr; i++) {
923 ret = deliver_sample_value(session, tool, event, sample,
924 &sample->read.group.values[i],
925 machine);
926 if (ret)
927 break;
928 }
929
930 return ret;
931}
932
933static int
934perf_session__deliver_sample(struct perf_session *session,
935 struct perf_tool *tool,
936 union perf_event *event,
937 struct perf_sample *sample,
938 struct perf_evsel *evsel,
939 struct machine *machine)
940{
941 /* We know evsel != NULL. */
942 u64 sample_type = evsel->attr.sample_type;
943 u64 read_format = evsel->attr.read_format;
944
945 /* Standard sample delievery. */
946 if (!(sample_type & PERF_SAMPLE_READ))
947 return tool->sample(tool, event, sample, evsel, machine);
948
949 /* For PERF_SAMPLE_READ we have either single or group mode. */
950 if (read_format & PERF_FORMAT_GROUP)
951 return deliver_sample_group(session, tool, event, sample,
952 machine);
953 else
954 return deliver_sample_value(session, tool, event, sample,
955 &sample->read.one, machine);
956}
957
831static int perf_session_deliver_event(struct perf_session *session, 958static int perf_session_deliver_event(struct perf_session *session,
832 union perf_event *event, 959 union perf_event *event,
833 struct perf_sample *sample, 960 struct perf_sample *sample,
@@ -857,7 +984,8 @@ static int perf_session_deliver_event(struct perf_session *session,
857 hists__inc_nr_events(&evsel->hists, event->header.type); 984 hists__inc_nr_events(&evsel->hists, event->header.type);
858 } 985 }
859 986
860 machine = perf_session__find_machine_for_cpumode(session, event); 987 machine = perf_session__find_machine_for_cpumode(session, event,
988 sample);
861 989
862 switch (event->header.type) { 990 switch (event->header.type) {
863 case PERF_RECORD_SAMPLE: 991 case PERF_RECORD_SAMPLE:
@@ -870,9 +998,12 @@ static int perf_session_deliver_event(struct perf_session *session,
870 ++session->stats.nr_unprocessable_samples; 998 ++session->stats.nr_unprocessable_samples;
871 return 0; 999 return 0;
872 } 1000 }
873 return tool->sample(tool, event, sample, evsel, machine); 1001 return perf_session__deliver_sample(session, tool, event,
1002 sample, evsel, machine);
874 case PERF_RECORD_MMAP: 1003 case PERF_RECORD_MMAP:
875 return tool->mmap(tool, event, sample, machine); 1004 return tool->mmap(tool, event, sample, machine);
1005 case PERF_RECORD_MMAP2:
1006 return tool->mmap2(tool, event, sample, machine);
876 case PERF_RECORD_COMM: 1007 case PERF_RECORD_COMM:
877 return tool->comm(tool, event, sample, machine); 1008 return tool->comm(tool, event, sample, machine);
878 case PERF_RECORD_FORK: 1009 case PERF_RECORD_FORK:
@@ -895,22 +1026,6 @@ static int perf_session_deliver_event(struct perf_session *session,
895 } 1026 }
896} 1027}
897 1028
898static int perf_session__preprocess_sample(struct perf_session *session,
899 union perf_event *event, struct perf_sample *sample)
900{
901 if (event->header.type != PERF_RECORD_SAMPLE ||
902 !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))
903 return 0;
904
905 if (!ip_callchain__valid(sample->callchain, event)) {
906 pr_debug("call-chain problem with event, skipping it.\n");
907 ++session->stats.nr_invalid_chains;
908 session->stats.total_invalid_chains += sample->period;
909 return -EINVAL;
910 }
911 return 0;
912}
913
914static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 1029static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
915 struct perf_tool *tool, u64 file_offset) 1030 struct perf_tool *tool, u64 file_offset)
916{ 1031{
@@ -921,16 +1036,14 @@ static int perf_session__process_user_event(struct perf_session *session, union
921 /* These events are processed right away */ 1036 /* These events are processed right away */
922 switch (event->header.type) { 1037 switch (event->header.type) {
923 case PERF_RECORD_HEADER_ATTR: 1038 case PERF_RECORD_HEADER_ATTR:
924 err = tool->attr(event, &session->evlist); 1039 err = tool->attr(tool, event, &session->evlist);
925 if (err == 0) 1040 if (err == 0)
926 perf_session__set_id_hdr_size(session); 1041 perf_session__set_id_hdr_size(session);
927 return err; 1042 return err;
928 case PERF_RECORD_HEADER_EVENT_TYPE:
929 return tool->event_type(tool, event);
930 case PERF_RECORD_HEADER_TRACING_DATA: 1043 case PERF_RECORD_HEADER_TRACING_DATA:
931 /* setup for reading amidst mmap */ 1044 /* setup for reading amidst mmap */
932 lseek(session->fd, file_offset, SEEK_SET); 1045 lseek(session->fd, file_offset, SEEK_SET);
933 return tool->tracing_data(event, session); 1046 return tool->tracing_data(tool, event, session);
934 case PERF_RECORD_HEADER_BUILD_ID: 1047 case PERF_RECORD_HEADER_BUILD_ID:
935 return tool->build_id(tool, event, session); 1048 return tool->build_id(tool, event, session);
936 case PERF_RECORD_FINISHED_ROUND: 1049 case PERF_RECORD_FINISHED_ROUND:
@@ -975,10 +1088,6 @@ static int perf_session__process_event(struct perf_session *session,
975 if (ret) 1088 if (ret)
976 return ret; 1089 return ret;
977 1090
978 /* Preprocess sample records - precheck callchains */
979 if (perf_session__preprocess_sample(session, event, &sample))
980 return 0;
981
982 if (tool->ordered_samples) { 1091 if (tool->ordered_samples) {
983 ret = perf_session_queue_event(session, event, &sample, 1092 ret = perf_session_queue_event(session, event, &sample,
984 file_offset); 1093 file_offset);
@@ -999,7 +1108,7 @@ void perf_event_header__bswap(struct perf_event_header *self)
999 1108
1000struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 1109struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1001{ 1110{
1002 return machine__findnew_thread(&session->machines.host, pid); 1111 return machine__findnew_thread(&session->machines.host, 0, pid);
1003} 1112}
1004 1113
1005static struct thread *perf_session__register_idle_thread(struct perf_session *self) 1114static struct thread *perf_session__register_idle_thread(struct perf_session *self)
@@ -1054,7 +1163,6 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
1054 } 1163 }
1055} 1164}
1056 1165
1057#define session_done() (*(volatile int *)(&session_done))
1058volatile int session_done; 1166volatile int session_done;
1059 1167
1060static int __perf_session__process_pipe_events(struct perf_session *self, 1168static int __perf_session__process_pipe_events(struct perf_session *self,
@@ -1091,8 +1199,10 @@ more:
1091 perf_event_header__bswap(&event->header); 1199 perf_event_header__bswap(&event->header);
1092 1200
1093 size = event->header.size; 1201 size = event->header.size;
1094 if (size == 0) 1202 if (size < sizeof(struct perf_event_header)) {
1095 size = 8; 1203 pr_err("bad event header size\n");
1204 goto out_err;
1205 }
1096 1206
1097 if (size > cur_size) { 1207 if (size > cur_size) {
1098 void *new = realloc(buf, size); 1208 void *new = realloc(buf, size);
@@ -1161,8 +1271,12 @@ fetch_mmaped_event(struct perf_session *session,
1161 if (session->header.needs_swap) 1271 if (session->header.needs_swap)
1162 perf_event_header__bswap(&event->header); 1272 perf_event_header__bswap(&event->header);
1163 1273
1164 if (head + event->header.size > mmap_size) 1274 if (head + event->header.size > mmap_size) {
1275 /* We're not fetching the event so swap back again */
1276 if (session->header.needs_swap)
1277 perf_event_header__bswap(&event->header);
1165 return NULL; 1278 return NULL;
1279 }
1166 1280
1167 return event; 1281 return event;
1168} 1282}
@@ -1242,7 +1356,7 @@ more:
1242 1356
1243 size = event->header.size; 1357 size = event->header.size;
1244 1358
1245 if (size == 0 || 1359 if (size < sizeof(struct perf_event_header) ||
1246 perf_session__process_event(session, event, tool, file_pos) < 0) { 1360 perf_session__process_event(session, event, tool, file_pos) < 0) {
1247 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1361 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1248 file_offset + head, event->header.size, 1362 file_offset + head, event->header.size,
@@ -1260,10 +1374,13 @@ more:
1260 "Processing events..."); 1374 "Processing events...");
1261 } 1375 }
1262 1376
1377 err = 0;
1378 if (session_done())
1379 goto out_err;
1380
1263 if (file_pos < file_size) 1381 if (file_pos < file_size)
1264 goto more; 1382 goto more;
1265 1383
1266 err = 0;
1267 /* do the final flush for ordered samples */ 1384 /* do the final flush for ordered samples */
1268 session->ordered_samples.next_flush = ULLONG_MAX; 1385 session->ordered_samples.next_flush = ULLONG_MAX;
1269 err = flush_sample_queue(session, tool); 1386 err = flush_sample_queue(session, tool);
@@ -1295,12 +1412,15 @@ int perf_session__process_events(struct perf_session *self,
1295 1412
1296bool perf_session__has_traces(struct perf_session *session, const char *msg) 1413bool perf_session__has_traces(struct perf_session *session, const char *msg)
1297{ 1414{
1298 if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) { 1415 struct perf_evsel *evsel;
1299 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); 1416
1300 return false; 1417 list_for_each_entry(evsel, &session->evlist->entries, node) {
1418 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1419 return true;
1301 } 1420 }
1302 1421
1303 return true; 1422 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
1423 return false;
1304} 1424}
1305 1425
1306int maps__set_kallsyms_ref_reloc_sym(struct map **maps, 1426int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
@@ -1383,13 +1503,18 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1383 1503
1384void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 1504void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1385 struct perf_sample *sample, struct machine *machine, 1505 struct perf_sample *sample, struct machine *machine,
1386 int print_sym, int print_dso, int print_symoffset) 1506 unsigned int print_opts, unsigned int stack_depth)
1387{ 1507{
1388 struct addr_location al; 1508 struct addr_location al;
1389 struct callchain_cursor_node *node; 1509 struct callchain_cursor_node *node;
1390 1510 int print_ip = print_opts & PRINT_IP_OPT_IP;
1391 if (perf_event__preprocess_sample(event, machine, &al, sample, 1511 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1392 NULL) < 0) { 1512 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1513 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1514 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1515 char s = print_oneline ? ' ' : '\t';
1516
1517 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
1393 error("problem processing %d event, skipping it.\n", 1518 error("problem processing %d event, skipping it.\n",
1394 event->header.type); 1519 event->header.type);
1395 return; 1520 return;
@@ -1397,37 +1522,50 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1397 1522
1398 if (symbol_conf.use_callchain && sample->callchain) { 1523 if (symbol_conf.use_callchain && sample->callchain) {
1399 1524
1400
1401 if (machine__resolve_callchain(machine, evsel, al.thread, 1525 if (machine__resolve_callchain(machine, evsel, al.thread,
1402 sample, NULL) != 0) { 1526 sample, NULL, NULL) != 0) {
1403 if (verbose) 1527 if (verbose)
1404 error("Failed to resolve callchain. Skipping\n"); 1528 error("Failed to resolve callchain. Skipping\n");
1405 return; 1529 return;
1406 } 1530 }
1407 callchain_cursor_commit(&callchain_cursor); 1531 callchain_cursor_commit(&callchain_cursor);
1408 1532
1409 while (1) { 1533 while (stack_depth) {
1410 node = callchain_cursor_current(&callchain_cursor); 1534 node = callchain_cursor_current(&callchain_cursor);
1411 if (!node) 1535 if (!node)
1412 break; 1536 break;
1413 1537
1414 printf("\t%16" PRIx64, node->ip); 1538 if (print_ip)
1539 printf("%c%16" PRIx64, s, node->ip);
1540
1415 if (print_sym) { 1541 if (print_sym) {
1416 printf(" "); 1542 printf(" ");
1417 symbol__fprintf_symname(node->sym, stdout); 1543 if (print_symoffset) {
1544 al.addr = node->ip;
1545 al.map = node->map;
1546 symbol__fprintf_symname_offs(node->sym, &al, stdout);
1547 } else
1548 symbol__fprintf_symname(node->sym, stdout);
1418 } 1549 }
1550
1419 if (print_dso) { 1551 if (print_dso) {
1420 printf(" ("); 1552 printf(" (");
1421 map__fprintf_dsoname(node->map, stdout); 1553 map__fprintf_dsoname(node->map, stdout);
1422 printf(")"); 1554 printf(")");
1423 } 1555 }
1424 printf("\n"); 1556
1557 if (!print_oneline)
1558 printf("\n");
1425 1559
1426 callchain_cursor_advance(&callchain_cursor); 1560 callchain_cursor_advance(&callchain_cursor);
1561
1562 stack_depth--;
1427 } 1563 }
1428 1564
1429 } else { 1565 } else {
1430 printf("%16" PRIx64, sample->ip); 1566 if (print_ip)
1567 printf("%16" PRIx64, sample->ip);
1568
1431 if (print_sym) { 1569 if (print_sym) {
1432 printf(" "); 1570 printf(" ");
1433 if (print_symoffset) 1571 if (print_symoffset)
@@ -1510,52 +1648,26 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1510 const struct perf_evsel_str_handler *assocs, 1648 const struct perf_evsel_str_handler *assocs,
1511 size_t nr_assocs) 1649 size_t nr_assocs)
1512{ 1650{
1513 struct perf_evlist *evlist = session->evlist;
1514 struct event_format *format;
1515 struct perf_evsel *evsel; 1651 struct perf_evsel *evsel;
1516 char *tracepoint, *name;
1517 size_t i; 1652 size_t i;
1518 int err; 1653 int err;
1519 1654
1520 for (i = 0; i < nr_assocs; i++) { 1655 for (i = 0; i < nr_assocs; i++) {
1521 err = -ENOMEM; 1656 /*
1522 tracepoint = strdup(assocs[i].name); 1657 * Adding a handler for an event not in the session,
1523 if (tracepoint == NULL) 1658 * just ignore it.
1524 goto out; 1659 */
1525 1660 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, assocs[i].name);
1526 err = -ENOENT;
1527 name = strchr(tracepoint, ':');
1528 if (name == NULL)
1529 goto out_free;
1530
1531 *name++ = '\0';
1532 format = pevent_find_event_by_name(session->pevent,
1533 tracepoint, name);
1534 if (format == NULL) {
1535 /*
1536 * Adding a handler for an event not in the session,
1537 * just ignore it.
1538 */
1539 goto next;
1540 }
1541
1542 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1543 if (evsel == NULL) 1661 if (evsel == NULL)
1544 goto next; 1662 continue;
1545 1663
1546 err = -EEXIST; 1664 err = -EEXIST;
1547 if (evsel->handler.func != NULL) 1665 if (evsel->handler.func != NULL)
1548 goto out_free; 1666 goto out;
1549 evsel->handler.func = assocs[i].handler; 1667 evsel->handler.func = assocs[i].handler;
1550next:
1551 free(tracepoint);
1552 } 1668 }
1553 1669
1554 err = 0; 1670 err = 0;
1555out: 1671out:
1556 return err; 1672 return err;
1557
1558out_free:
1559 free(tracepoint);
1560 goto out;
1561} 1673}