aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-08-15 03:48:17 -0400
committerIngo Molnar <mingo@kernel.org>2013-08-15 03:48:17 -0400
commit58cea307432e3376293e6b2be88d1f6e6e99274a (patch)
tree4f1a04fccc12b6ff58b2a10e6ca9f2fcaac4adbe /tools/perf
parent0a3d23a2568ed5e73bd4fb532dc672fa9f03b1f1 (diff)
parent2ae3a312c0ccd8ff615372f00aab1700aac27474 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Allow specifying syscalls in 'perf trace', a la strace. * Simplify symbol filtering by doing it at machine class level, from Adrian Hunter. * Add option to 'perf kvm' to print only events that exceed a specified time duration, from David Ahern. * 'perf sched' improvements, including removing some tracepoints that provide the same information as the PERF_RECORD_{FORK,EXIT} events. * Improve stack trace printing, from David Ahern. * Update documentation with live command, from David Ahern * Fix 'perf test' compile failure on do_sort_something, from David Ahern. * Improve robustness of topology parsing code, from Stephane Eranian. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-kvm.txt46
-rw-r--r--tools/perf/Documentation/perf-trace.txt4
-rw-r--r--tools/perf/builtin-annotate.c5
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kvm.c25
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/builtin-sched.c94
-rw-r--r--tools/perf/builtin-script.c35
-rw-r--r--tools/perf/builtin-top.c5
-rw-r--r--tools/perf/builtin-trace.c52
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/tests/code-reading.c13
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/event.c20
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/header.c11
-rw-r--r--tools/perf/util/machine.c28
-rw-r--r--tools/perf/util/machine.h5
-rw-r--r--tools/perf/util/session.c40
-rw-r--r--tools/perf/util/session.h8
-rw-r--r--tools/perf/util/thread.h5
-rw-r--r--tools/perf/util/unwind.c6
25 files changed, 294 insertions, 135 deletions
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 326f2cb333cb..ac84db2d2334 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -13,6 +13,7 @@ SYNOPSIS
13 {top|record|report|diff|buildid-list} 13 {top|record|report|diff|buildid-list}
14'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path> 14'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path>
15 | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} 15 | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat}
16'perf kvm stat [record|report|live] [<options>]
16 17
17DESCRIPTION 18DESCRIPTION
18----------- 19-----------
@@ -50,6 +51,10 @@ There are a couple of variants of perf kvm:
50 'perf kvm stat report' reports statistical data which includes events 51 'perf kvm stat report' reports statistical data which includes events
51 handled time, samples, and so on. 52 handled time, samples, and so on.
52 53
54 'perf kvm stat live' reports statistical data in a live mode (similar to
55 record + report but with statistical data updated live at a given display
56 rate).
57
53OPTIONS 58OPTIONS
54------- 59-------
55-i:: 60-i::
@@ -85,13 +90,50 @@ STAT REPORT OPTIONS
85--vcpu=<value>:: 90--vcpu=<value>::
86 analyze events which occures on this vcpu. (default: all vcpus) 91 analyze events which occures on this vcpu. (default: all vcpus)
87 92
88--events=<value>:: 93--event=<value>::
89 events to be analyzed. Possible values: vmexit, mmio, ioport. 94 event to be analyzed. Possible values: vmexit, mmio, ioport.
90 (default: vmexit) 95 (default: vmexit)
91-k:: 96-k::
92--key=<value>:: 97--key=<value>::
93 Sorting key. Possible values: sample (default, sort by samples 98 Sorting key. Possible values: sample (default, sort by samples
94 number), time (sort by average time). 99 number), time (sort by average time).
100-p::
101--pid=::
102 Analyze events only for given process ID(s) (comma separated list).
103
104STAT LIVE OPTIONS
105-----------------
106-d::
107--display::
108 Time in seconds between display updates
109
110-m::
111--mmap-pages=::
112 Number of mmap data pages. Must be a power of two.
113
114-a::
115--all-cpus::
116 System-wide collection from all CPUs.
117
118-p::
119--pid=::
120 Analyze events only for given process ID(s) (comma separated list).
121
122--vcpu=<value>::
123 analyze events which occures on this vcpu. (default: all vcpus)
124
125
126--event=<value>::
127 event to be analyzed. Possible values: vmexit, mmio, ioport.
128 (default: vmexit)
129
130-k::
131--key=<value>::
132 Sorting key. Possible values: sample (default, sort by samples
133 number), time (sort by average time).
134
135--duration=<value>::
136 Show events other than HLT that take longer than duration usecs.
95 137
96SEE ALSO 138SEE ALSO
97-------- 139--------
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 68718ccdd178..3b3552a8959e 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -26,6 +26,10 @@ OPTIONS
26--all-cpus:: 26--all-cpus::
27 System-wide collection from all CPUs. 27 System-wide collection from all CPUs.
28 28
29-e::
30--expr::
31 List of events to show, currently only syscall names.
32
29-p:: 33-p::
30--pid=:: 34--pid=::
31 Record events on existing process ID (comma separated list). 35 Record events on existing process ID (comma separated list).
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index db491e9a812b..f988d380c52f 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -90,8 +90,7 @@ static int process_sample_event(struct perf_tool *tool,
90 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); 90 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
91 struct addr_location al; 91 struct addr_location al;
92 92
93 if (perf_event__preprocess_sample(event, machine, &al, sample, 93 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
94 symbol__annotate_init) < 0) {
95 pr_warning("problem processing %d event, skipping it.\n", 94 pr_warning("problem processing %d event, skipping it.\n",
96 event->header.type); 95 event->header.type);
97 return -1; 96 return -1;
@@ -195,6 +194,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
195 if (session == NULL) 194 if (session == NULL)
196 return -ENOMEM; 195 return -ENOMEM;
197 196
197 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
198
198 if (ann->cpu_list) { 199 if (ann->cpu_list) {
199 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 200 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
200 ann->cpu_bitmap); 201 ann->cpu_bitmap);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 93de3ac177c5..f28799e94f2a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -319,7 +319,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
319{ 319{
320 struct addr_location al; 320 struct addr_location al;
321 321
322 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { 322 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
323 pr_warning("problem processing %d event, skipping it.\n", 323 pr_warning("problem processing %d event, skipping it.\n",
324 event->header.type); 324 event->header.type);
325 return -1; 325 return -1;
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f012a98c726c..1d8de2e4a407 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -206,7 +206,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
206 } 206 }
207 207
208 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 208 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
209 event->ip.ip, &al, NULL); 209 event->ip.ip, &al);
210 210
211 if (al.map != NULL) { 211 if (al.map != NULL) {
212 if (!al.map->dso->hit) { 212 if (!al.map->dso->hit) {
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 2ceec817a2fb..fa2f3d79886a 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -106,6 +106,7 @@ struct perf_kvm_stat {
106 u64 total_time; 106 u64 total_time;
107 u64 total_count; 107 u64 total_count;
108 u64 lost_events; 108 u64 lost_events;
109 u64 duration;
109 110
110 const char *pid_str; 111 const char *pid_str;
111 struct intlist *pid_list; 112 struct intlist *pid_list;
@@ -473,7 +474,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
473static bool handle_end_event(struct perf_kvm_stat *kvm, 474static bool handle_end_event(struct perf_kvm_stat *kvm,
474 struct vcpu_event_record *vcpu_record, 475 struct vcpu_event_record *vcpu_record,
475 struct event_key *key, 476 struct event_key *key,
476 u64 timestamp) 477 struct perf_sample *sample)
477{ 478{
478 struct kvm_event *event; 479 struct kvm_event *event;
479 u64 time_begin, time_diff; 480 u64 time_begin, time_diff;
@@ -510,12 +511,24 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
510 vcpu_record->start_time = 0; 511 vcpu_record->start_time = 0;
511 512
512 /* seems to happen once in a while during live mode */ 513 /* seems to happen once in a while during live mode */
513 if (timestamp < time_begin) { 514 if (sample->time < time_begin) {
514 pr_debug("End time before begin time; skipping event.\n"); 515 pr_debug("End time before begin time; skipping event.\n");
515 return true; 516 return true;
516 } 517 }
517 518
518 time_diff = timestamp - time_begin; 519 time_diff = sample->time - time_begin;
520
521 if (kvm->duration && time_diff > kvm->duration) {
522 char decode[32];
523
524 kvm->events_ops->decode_key(kvm, &event->key, decode);
525 if (strcmp(decode, "HLT")) {
526 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
527 sample->time, sample->pid, vcpu_record->vcpu_id,
528 decode, time_diff/1000);
529 }
530 }
531
519 return update_kvm_event(event, vcpu, time_diff); 532 return update_kvm_event(event, vcpu, time_diff);
520} 533}
521 534
@@ -562,7 +575,7 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
562 return handle_begin_event(kvm, vcpu_record, &key, sample->time); 575 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
563 576
564 if (kvm->events_ops->is_end_event(evsel, sample, &key)) 577 if (kvm->events_ops->is_end_event(evsel, sample, &key))
565 return handle_end_event(kvm, vcpu_record, &key, sample->time); 578 return handle_end_event(kvm, vcpu_record, &key, sample);
566 579
567 return true; 580 return true;
568} 581}
@@ -1429,6 +1442,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1429 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1442 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1430 "key for sorting: sample(sort by samples number)" 1443 "key for sorting: sample(sort by samples number)"
1431 " time (sort by avg time)"), 1444 " time (sort by avg time)"),
1445 OPT_U64(0, "duration", &kvm->duration,
1446 "show events other than HALT that take longer than duration usecs"),
1432 OPT_END() 1447 OPT_END()
1433 }; 1448 };
1434 const char * const live_usage[] = { 1449 const char * const live_usage[] = {
@@ -1467,6 +1482,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1467 usage_with_options(live_usage, live_options); 1482 usage_with_options(live_usage, live_options);
1468 } 1483 }
1469 1484
1485 kvm->duration *= NSEC_PER_USEC; /* convert usec to nsec */
1486
1470 /* 1487 /*
1471 * target related setups 1488 * target related setups
1472 */ 1489 */
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index a8ff6d264e50..706a1faa9559 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -14,7 +14,6 @@ static const char *mem_operation = MEM_OPERATION_LOAD;
14struct perf_mem { 14struct perf_mem {
15 struct perf_tool tool; 15 struct perf_tool tool;
16 char const *input_name; 16 char const *input_name;
17 symbol_filter_t annotate_init;
18 bool hide_unresolved; 17 bool hide_unresolved;
19 bool dump_raw; 18 bool dump_raw;
20 const char *cpu_list; 19 const char *cpu_list;
@@ -69,8 +68,7 @@ dump_raw_samples(struct perf_tool *tool,
69 struct addr_location al; 68 struct addr_location al;
70 const char *fmt; 69 const char *fmt;
71 70
72 if (perf_event__preprocess_sample(event, machine, &al, sample, 71 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
73 mem->annotate_init) < 0) {
74 fprintf(stderr, "problem processing %d event, skipping it.\n", 72 fprintf(stderr, "problem processing %d event, skipping it.\n",
75 event->header.type); 73 event->header.type);
76 return -1; 74 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d785d89ed226..958a56a0e39e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -49,7 +49,6 @@ struct perf_report {
49 bool mem_mode; 49 bool mem_mode;
50 struct perf_read_values show_threads_values; 50 struct perf_read_values show_threads_values;
51 const char *pretty_printing_style; 51 const char *pretty_printing_style;
52 symbol_filter_t annotate_init;
53 const char *cpu_list; 52 const char *cpu_list;
54 const char *symbol_filter_str; 53 const char *symbol_filter_str;
55 float min_percent; 54 float min_percent;
@@ -305,8 +304,7 @@ static int process_sample_event(struct perf_tool *tool,
305 struct addr_location al; 304 struct addr_location al;
306 int ret; 305 int ret;
307 306
308 if (perf_event__preprocess_sample(event, machine, &al, sample, 307 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
309 rep->annotate_init) < 0) {
310 fprintf(stderr, "problem processing %d event, skipping it.\n", 308 fprintf(stderr, "problem processing %d event, skipping it.\n",
311 event->header.type); 309 event->header.type);
312 return -1; 310 return -1;
@@ -924,7 +922,8 @@ repeat:
924 */ 922 */
925 if (use_browser == 1 && sort__has_sym) { 923 if (use_browser == 1 && sort__has_sym) {
926 symbol_conf.priv_size = sizeof(struct annotation); 924 symbol_conf.priv_size = sizeof(struct annotation);
927 report.annotate_init = symbol__annotate_init; 925 machines__set_symbol_filter(&session->machines,
926 symbol__annotate_init);
928 /* 927 /*
929 * For searching by name on the "Browse map details". 928 * For searching by name on the "Browse map details".
930 * providing it only in verbose mode not to bloat too 929 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 948183adb6e5..f809cc7fb7d9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -109,8 +109,9 @@ struct trace_sched_handler {
109 int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, 109 int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel,
110 struct perf_sample *sample, struct machine *machine); 110 struct perf_sample *sample, struct machine *machine);
111 111
112 int (*fork_event)(struct perf_sched *sched, struct perf_evsel *evsel, 112 /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */
113 struct perf_sample *sample); 113 int (*fork_event)(struct perf_sched *sched, union perf_event *event,
114 struct machine *machine);
114 115
115 int (*migrate_task_event)(struct perf_sched *sched, 116 int (*migrate_task_event)(struct perf_sched *sched,
116 struct perf_evsel *evsel, 117 struct perf_evsel *evsel,
@@ -717,22 +718,29 @@ static int replay_switch_event(struct perf_sched *sched,
717 return 0; 718 return 0;
718} 719}
719 720
720static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, 721static int replay_fork_event(struct perf_sched *sched,
721 struct perf_sample *sample) 722 union perf_event *event,
723 struct machine *machine)
722{ 724{
723 const char *parent_comm = perf_evsel__strval(evsel, sample, "parent_comm"), 725 struct thread *child, *parent;
724 *child_comm = perf_evsel__strval(evsel, sample, "child_comm"); 726
725 const u32 parent_pid = perf_evsel__intval(evsel, sample, "parent_pid"), 727 child = machine__findnew_thread(machine, event->fork.tid);
726 child_pid = perf_evsel__intval(evsel, sample, "child_pid"); 728 parent = machine__findnew_thread(machine, event->fork.ptid);
729
730 if (child == NULL || parent == NULL) {
731 pr_debug("thread does not exist on fork event: child %p, parent %p\n",
732 child, parent);
733 return 0;
734 }
727 735
728 if (verbose) { 736 if (verbose) {
729 printf("sched_fork event %p\n", evsel); 737 printf("fork event\n");
730 printf("... parent: %s/%d\n", parent_comm, parent_pid); 738 printf("... parent: %s/%d\n", parent->comm, parent->tid);
731 printf("... child: %s/%d\n", child_comm, child_pid); 739 printf("... child: %s/%d\n", child->comm, child->tid);
732 } 740 }
733 741
734 register_pid(sched, parent_pid, parent_comm); 742 register_pid(sched, parent->tid, parent->comm);
735 register_pid(sched, child_pid, child_comm); 743 register_pid(sched, child->tid, child->comm);
736 return 0; 744 return 0;
737} 745}
738 746
@@ -824,14 +832,6 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
824 return 0; 832 return 0;
825} 833}
826 834
827static int latency_fork_event(struct perf_sched *sched __maybe_unused,
828 struct perf_evsel *evsel __maybe_unused,
829 struct perf_sample *sample __maybe_unused)
830{
831 /* should insert the newcomer */
832 return 0;
833}
834
835static char sched_out_state(u64 prev_state) 835static char sched_out_state(u64 prev_state)
836{ 836{
837 const char *str = TASK_STATE_TO_CHAR_STR; 837 const char *str = TASK_STATE_TO_CHAR_STR;
@@ -1379,25 +1379,20 @@ static int process_sched_runtime_event(struct perf_tool *tool,
1379 return 0; 1379 return 0;
1380} 1380}
1381 1381
1382static int process_sched_fork_event(struct perf_tool *tool, 1382static int perf_sched__process_fork_event(struct perf_tool *tool,
1383 struct perf_evsel *evsel, 1383 union perf_event *event,
1384 struct perf_sample *sample, 1384 struct perf_sample *sample,
1385 struct machine *machine __maybe_unused) 1385 struct machine *machine)
1386{ 1386{
1387 struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1387 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1388 1388
1389 if (sched->tp_handler->fork_event) 1389 /* run the fork event through the perf machineruy */
1390 return sched->tp_handler->fork_event(sched, evsel, sample); 1390 perf_event__process_fork(tool, event, sample, machine);
1391 1391
1392 return 0; 1392 /* and then run additional processing needed for this command */
1393} 1393 if (sched->tp_handler->fork_event)
1394 return sched->tp_handler->fork_event(sched, event, machine);
1394 1395
1395static int process_sched_exit_event(struct perf_tool *tool __maybe_unused,
1396 struct perf_evsel *evsel,
1397 struct perf_sample *sample __maybe_unused,
1398 struct machine *machine __maybe_unused)
1399{
1400 pr_debug("sched_exit event %p\n", evsel);
1401 return 0; 1396 return 0;
1402} 1397}
1403 1398
@@ -1425,15 +1420,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1425 struct perf_evsel *evsel, 1420 struct perf_evsel *evsel,
1426 struct machine *machine) 1421 struct machine *machine)
1427{ 1422{
1428 struct thread *thread = machine__findnew_thread(machine, sample->tid);
1429 int err = 0; 1423 int err = 0;
1430 1424
1431 if (thread == NULL) {
1432 pr_debug("problem processing %s event, skipping it.\n",
1433 perf_evsel__name(evsel));
1434 return -1;
1435 }
1436
1437 evsel->hists.stats.total_period += sample->period; 1425 evsel->hists.stats.total_period += sample->period;
1438 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 1426 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1439 1427
@@ -1445,7 +1433,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1445 return err; 1433 return err;
1446} 1434}
1447 1435
1448static int perf_sched__read_events(struct perf_sched *sched, bool destroy, 1436static int perf_sched__read_events(struct perf_sched *sched,
1449 struct perf_session **psession) 1437 struct perf_session **psession)
1450{ 1438{
1451 const struct perf_evsel_str_handler handlers[] = { 1439 const struct perf_evsel_str_handler handlers[] = {
@@ -1453,8 +1441,6 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1453 { "sched:sched_stat_runtime", process_sched_runtime_event, }, 1441 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1454 { "sched:sched_wakeup", process_sched_wakeup_event, }, 1442 { "sched:sched_wakeup", process_sched_wakeup_event, },
1455 { "sched:sched_wakeup_new", process_sched_wakeup_event, }, 1443 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1456 { "sched:sched_process_fork", process_sched_fork_event, },
1457 { "sched:sched_process_exit", process_sched_exit_event, },
1458 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1444 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1459 }; 1445 };
1460 struct perf_session *session; 1446 struct perf_session *session;
@@ -1480,11 +1466,10 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1480 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1466 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST];
1481 } 1467 }
1482 1468
1483 if (destroy)
1484 perf_session__delete(session);
1485
1486 if (psession) 1469 if (psession)
1487 *psession = session; 1470 *psession = session;
1471 else
1472 perf_session__delete(session);
1488 1473
1489 return 0; 1474 return 0;
1490 1475
@@ -1529,8 +1514,11 @@ static int perf_sched__lat(struct perf_sched *sched)
1529 struct perf_session *session; 1514 struct perf_session *session;
1530 1515
1531 setup_pager(); 1516 setup_pager();
1532 if (perf_sched__read_events(sched, false, &session)) 1517
1518 /* save session -- references to threads are held in work_list */
1519 if (perf_sched__read_events(sched, &session))
1533 return -1; 1520 return -1;
1521
1534 perf_sched__sort_lat(sched); 1522 perf_sched__sort_lat(sched);
1535 1523
1536 printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1524 printf("\n ---------------------------------------------------------------------------------------------------------------\n");
@@ -1565,7 +1553,7 @@ static int perf_sched__map(struct perf_sched *sched)
1565 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1553 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1566 1554
1567 setup_pager(); 1555 setup_pager();
1568 if (perf_sched__read_events(sched, true, NULL)) 1556 if (perf_sched__read_events(sched, NULL))
1569 return -1; 1557 return -1;
1570 print_bad_events(sched); 1558 print_bad_events(sched);
1571 return 0; 1559 return 0;
@@ -1580,7 +1568,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1580 1568
1581 test_calibrations(sched); 1569 test_calibrations(sched);
1582 1570
1583 if (perf_sched__read_events(sched, true, NULL)) 1571 if (perf_sched__read_events(sched, NULL))
1584 return -1; 1572 return -1;
1585 1573
1586 printf("nr_run_events: %ld\n", sched->nr_run_events); 1574 printf("nr_run_events: %ld\n", sched->nr_run_events);
@@ -1639,7 +1627,6 @@ static int __cmd_record(int argc, const char **argv)
1639 "-e", "sched:sched_stat_sleep", 1627 "-e", "sched:sched_stat_sleep",
1640 "-e", "sched:sched_stat_iowait", 1628 "-e", "sched:sched_stat_iowait",
1641 "-e", "sched:sched_stat_runtime", 1629 "-e", "sched:sched_stat_runtime",
1642 "-e", "sched:sched_process_exit",
1643 "-e", "sched:sched_process_fork", 1630 "-e", "sched:sched_process_fork",
1644 "-e", "sched:sched_wakeup", 1631 "-e", "sched:sched_wakeup",
1645 "-e", "sched:sched_migrate_task", 1632 "-e", "sched:sched_migrate_task",
@@ -1668,7 +1655,7 @@ static struct perf_sched sched = {
1668 .sample = perf_sched__process_tracepoint_sample, 1655 .sample = perf_sched__process_tracepoint_sample,
1669 .comm = perf_event__process_comm, 1656 .comm = perf_event__process_comm,
1670 .lost = perf_event__process_lost, 1657 .lost = perf_event__process_lost,
1671 .fork = perf_event__process_fork, 1658 .fork = perf_sched__process_fork_event,
1672 .ordered_samples = true, 1659 .ordered_samples = true,
1673 }, 1660 },
1674 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1661 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
@@ -1730,7 +1717,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1730 .wakeup_event = latency_wakeup_event, 1717 .wakeup_event = latency_wakeup_event,
1731 .switch_event = latency_switch_event, 1718 .switch_event = latency_switch_event,
1732 .runtime_event = latency_runtime_event, 1719 .runtime_event = latency_runtime_event,
1733 .fork_event = latency_fork_event,
1734 .migrate_task_event = latency_migrate_task_event, 1720 .migrate_task_event = latency_migrate_task_event,
1735 }; 1721 };
1736 struct trace_sched_handler map_ops = { 1722 struct trace_sched_handler map_ops = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index cd616ff5d221..2ad9d5b6fb3c 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -66,6 +66,7 @@ struct output_option {
66static struct { 66static struct {
67 bool user_set; 67 bool user_set;
68 bool wildcard_set; 68 bool wildcard_set;
69 unsigned int print_ip_opts;
69 u64 fields; 70 u64 fields;
70 u64 invalid_fields; 71 u64 invalid_fields;
71} output[PERF_TYPE_MAX] = { 72} output[PERF_TYPE_MAX] = {
@@ -235,6 +236,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
235{ 236{
236 int j; 237 int j;
237 struct perf_evsel *evsel; 238 struct perf_evsel *evsel;
239 struct perf_event_attr *attr;
238 240
239 for (j = 0; j < PERF_TYPE_MAX; ++j) { 241 for (j = 0; j < PERF_TYPE_MAX; ++j) {
240 evsel = perf_session__find_first_evtype(session, j); 242 evsel = perf_session__find_first_evtype(session, j);
@@ -253,6 +255,24 @@ static int perf_session__check_output_opt(struct perf_session *session)
253 if (evsel && output[j].fields && 255 if (evsel && output[j].fields &&
254 perf_evsel__check_attr(evsel, session)) 256 perf_evsel__check_attr(evsel, session))
255 return -1; 257 return -1;
258
259 if (evsel == NULL)
260 continue;
261
262 attr = &evsel->attr;
263
264 output[j].print_ip_opts = 0;
265 if (PRINT_FIELD(IP))
266 output[j].print_ip_opts |= PRINT_IP_OPT_IP;
267
268 if (PRINT_FIELD(SYM))
269 output[j].print_ip_opts |= PRINT_IP_OPT_SYM;
270
271 if (PRINT_FIELD(DSO))
272 output[j].print_ip_opts |= PRINT_IP_OPT_DSO;
273
274 if (PRINT_FIELD(SYMOFFSET))
275 output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
256 } 276 }
257 277
258 return 0; 278 return 0;
@@ -341,10 +361,10 @@ static void print_sample_addr(union perf_event *event,
341 return; 361 return;
342 362
343 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 363 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
344 sample->addr, &al, NULL); 364 sample->addr, &al);
345 if (!al.map) 365 if (!al.map)
346 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 366 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
347 sample->addr, &al, NULL); 367 sample->addr, &al);
348 368
349 al.cpu = sample->cpu; 369 al.cpu = sample->cpu;
350 al.sym = NULL; 370 al.sym = NULL;
@@ -382,8 +402,8 @@ static void print_sample_bts(union perf_event *event,
382 else 402 else
383 printf("\n"); 403 printf("\n");
384 perf_evsel__print_ip(evsel, event, sample, machine, 404 perf_evsel__print_ip(evsel, event, sample, machine,
385 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 405 output[attr->type].print_ip_opts,
386 PRINT_FIELD(SYMOFFSET)); 406 PERF_MAX_STACK_DEPTH);
387 } 407 }
388 408
389 printf(" => "); 409 printf(" => ");
@@ -423,9 +443,10 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
423 printf(" "); 443 printf(" ");
424 else 444 else
425 printf("\n"); 445 printf("\n");
446
426 perf_evsel__print_ip(evsel, event, sample, machine, 447 perf_evsel__print_ip(evsel, event, sample, machine,
427 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 448 output[attr->type].print_ip_opts,
428 PRINT_FIELD(SYMOFFSET)); 449 PERF_MAX_STACK_DEPTH);
429 } 450 }
430 451
431 printf("\n"); 452 printf("\n");
@@ -499,7 +520,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
499 return 0; 520 return 0;
500 } 521 }
501 522
502 if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) { 523 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
503 pr_err("problem processing %d event, skipping it.\n", 524 pr_err("problem processing %d event, skipping it.\n",
504 event->header.type); 525 event->header.type);
505 return -1; 526 return -1;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 440c3b371401..e37521fc715a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -716,8 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
716 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 716 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
717 top->exact_samples++; 717 top->exact_samples++;
718 718
719 if (perf_event__preprocess_sample(event, machine, &al, sample, 719 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0 ||
720 symbol_filter) < 0 ||
721 al.filtered) 720 al.filtered)
722 return; 721 return;
723 722
@@ -938,6 +937,8 @@ static int __cmd_top(struct perf_top *top)
938 if (top->session == NULL) 937 if (top->session == NULL)
939 return -ENOMEM; 938 return -ENOMEM;
940 939
940 machines__set_symbol_filter(&top->session->machines, symbol_filter);
941
941 if (!objdump_path) { 942 if (!objdump_path) {
942 ret = perf_session_env__lookup_objdump(&top->session->header.env); 943 ret = perf_session_env__lookup_objdump(&top->session->header.env);
943 if (ret) 944 if (ret)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index da7ae01c8394..120fdfb3d920 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -5,6 +5,7 @@
5#include "util/machine.h" 5#include "util/machine.h"
6#include "util/thread.h" 6#include "util/thread.h"
7#include "util/parse-options.h" 7#include "util/parse-options.h"
8#include "util/strlist.h"
8#include "util/thread_map.h" 9#include "util/thread_map.h"
9 10
10#include <libaudit.h> 11#include <libaudit.h>
@@ -47,6 +48,7 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
47struct syscall { 48struct syscall {
48 struct event_format *tp_format; 49 struct event_format *tp_format;
49 const char *name; 50 const char *name;
51 bool filtered;
50 struct syscall_fmt *fmt; 52 struct syscall_fmt *fmt;
51}; 53};
52 54
@@ -110,6 +112,7 @@ struct trace {
110 struct perf_record_opts opts; 112 struct perf_record_opts opts;
111 struct machine host; 113 struct machine host;
112 u64 base_time; 114 u64 base_time;
115 struct strlist *ev_qualifier;
113 unsigned long nr_events; 116 unsigned long nr_events;
114 bool sched; 117 bool sched;
115 bool multiple_threads; 118 bool multiple_threads;
@@ -226,6 +229,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
226 229
227 sc = trace->syscalls.table + id; 230 sc = trace->syscalls.table + id;
228 sc->name = name; 231 sc->name = name;
232
233 if (trace->ev_qualifier && !strlist__find(trace->ev_qualifier, name)) {
234 sc->filtered = true;
235 /*
236 * No need to do read tracepoint information since this will be
237 * filtered out.
238 */
239 return 0;
240 }
241
229 sc->fmt = syscall_fmt__find(sc->name); 242 sc->fmt = syscall_fmt__find(sc->name);
230 243
231 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 244 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
@@ -302,11 +315,19 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
302 char *msg; 315 char *msg;
303 void *args; 316 void *args;
304 size_t printed = 0; 317 size_t printed = 0;
305 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); 318 struct thread *thread;
306 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 319 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
307 struct thread_trace *ttrace = thread__trace(thread); 320 struct thread_trace *ttrace;
321
322 if (sc == NULL)
323 return -1;
308 324
309 if (ttrace == NULL || sc == NULL) 325 if (sc->filtered)
326 return 0;
327
328 thread = machine__findnew_thread(&trace->host, sample->tid);
329 ttrace = thread__trace(thread);
330 if (ttrace == NULL)
310 return -1; 331 return -1;
311 332
312 args = perf_evsel__rawptr(evsel, sample, "args"); 333 args = perf_evsel__rawptr(evsel, sample, "args");
@@ -345,11 +366,19 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
345{ 366{
346 int ret; 367 int ret;
347 u64 duration = 0; 368 u64 duration = 0;
348 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); 369 struct thread *thread;
349 struct thread_trace *ttrace = thread__trace(thread);
350 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 370 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
371 struct thread_trace *ttrace;
372
373 if (sc == NULL)
374 return -1;
351 375
352 if (ttrace == NULL || sc == NULL) 376 if (sc->filtered)
377 return 0;
378
379 thread = machine__findnew_thread(&trace->host, sample->tid);
380 ttrace = thread__trace(thread);
381 if (ttrace == NULL)
353 return -1; 382 return -1;
354 383
355 ret = perf_evsel__intval(evsel, sample, "ret"); 384 ret = perf_evsel__intval(evsel, sample, "ret");
@@ -634,7 +663,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
634 .mmap_pages = 1024, 663 .mmap_pages = 1024,
635 }, 664 },
636 }; 665 };
666 const char *ev_qualifier_str = NULL;
637 const struct option trace_options[] = { 667 const struct option trace_options[] = {
668 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
669 "list of events to trace"),
638 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 670 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
639 "trace events on existing process id"), 671 "trace events on existing process id"),
640 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", 672 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid",
@@ -660,6 +692,14 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
660 692
661 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 693 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
662 694
695 if (ev_qualifier_str != NULL) {
696 trace.ev_qualifier = strlist__new(true, ev_qualifier_str);
697 if (trace.ev_qualifier == NULL) {
698 puts("Not enough memory to parse event qualifier");
699 return -ENOMEM;
700 }
701 }
702
663 err = perf_target__validate(&trace.opts.target); 703 err = perf_target__validate(&trace.opts.target);
664 if (err) { 704 if (err) {
665 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); 705 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 32bd102c32b6..cf20187eee0a 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -125,6 +125,9 @@
125#ifndef NSEC_PER_SEC 125#ifndef NSEC_PER_SEC
126# define NSEC_PER_SEC 1000000000ULL 126# define NSEC_PER_SEC 1000000000ULL
127#endif 127#endif
128#ifndef NSEC_PER_USEC
129# define NSEC_PER_USEC 1000ULL
130#endif
128 131
129static inline unsigned long long rdclock(void) 132static inline unsigned long long rdclock(void)
130{ 133{
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 8e0943b966d7..df9afd9cab4c 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -147,7 +147,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
147 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 147 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
148 148
149 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, 149 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr,
150 &al, NULL); 150 &al);
151 if (!al.map || !al.map->dso) { 151 if (!al.map || !al.map->dso) {
152 pr_debug("thread__find_addr_map failed\n"); 152 pr_debug("thread__find_addr_map failed\n");
153 return -1; 153 return -1;
@@ -304,15 +304,14 @@ static int comp(const void *a, const void *b)
304 304
305static void do_sort_something(void) 305static void do_sort_something(void)
306{ 306{
307 size_t sz = 40960; 307 int buf[40960], i;
308 int buf[sz], i;
309 308
310 for (i = 0; i < (int)sz; i++) 309 for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
311 buf[i] = sz - i - 1; 310 buf[i] = ARRAY_SIZE(buf) - i - 1;
312 311
313 qsort(buf, sz, sizeof(int), comp); 312 qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
314 313
315 for (i = 0; i < (int)sz; i++) { 314 for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
316 if (buf[i] != i) { 315 if (buf[i] != i) {
317 pr_debug("qsort failed\n"); 316 pr_debug("qsort failed\n");
318 break; 317 break;
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 89085a9615e2..50bfb01183ea 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -220,7 +220,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
220 }; 220 };
221 221
222 if (perf_event__preprocess_sample(&event, machine, &al, 222 if (perf_event__preprocess_sample(&event, machine, &al,
223 &sample, 0) < 0) 223 &sample) < 0)
224 goto out; 224 goto out;
225 225
226 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 226 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);
@@ -244,7 +244,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
244 }; 244 };
245 245
246 if (perf_event__preprocess_sample(&event, machine, &al, 246 if (perf_event__preprocess_sample(&event, machine, &al,
247 &sample, 0) < 0) 247 &sample) < 0)
248 goto out; 248 goto out;
249 249
250 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 250 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 3a0f5089379c..5295625c0c00 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -33,7 +33,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
33 } 33 }
34 34
35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
36 event->ip.ip, &al, NULL); 36 event->ip.ip, &al);
37 37
38 if (al.map != NULL) 38 if (al.map != NULL)
39 al.map->dso->hit = 1; 39 al.map->dso->hit = 1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index cc7c0c9c9ea6..49713ae46551 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -592,7 +592,7 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
592void thread__find_addr_map(struct thread *self, 592void thread__find_addr_map(struct thread *self,
593 struct machine *machine, u8 cpumode, 593 struct machine *machine, u8 cpumode,
594 enum map_type type, u64 addr, 594 enum map_type type, u64 addr,
595 struct addr_location *al, symbol_filter_t filter) 595 struct addr_location *al)
596{ 596{
597 struct map_groups *mg = &self->mg; 597 struct map_groups *mg = &self->mg;
598 bool load_map = false; 598 bool load_map = false;
@@ -663,19 +663,19 @@ try_again:
663 * must be done prior to using kernel maps. 663 * must be done prior to using kernel maps.
664 */ 664 */
665 if (load_map) 665 if (load_map)
666 map__load(al->map, filter); 666 map__load(al->map, machine->symbol_filter);
667 al->addr = al->map->map_ip(al->map, al->addr); 667 al->addr = al->map->map_ip(al->map, al->addr);
668 } 668 }
669} 669}
670 670
671void thread__find_addr_location(struct thread *thread, struct machine *machine, 671void thread__find_addr_location(struct thread *thread, struct machine *machine,
672 u8 cpumode, enum map_type type, u64 addr, 672 u8 cpumode, enum map_type type, u64 addr,
673 struct addr_location *al, 673 struct addr_location *al)
674 symbol_filter_t filter)
675{ 674{
676 thread__find_addr_map(thread, machine, cpumode, type, addr, al, filter); 675 thread__find_addr_map(thread, machine, cpumode, type, addr, al);
677 if (al->map != NULL) 676 if (al->map != NULL)
678 al->sym = map__find_symbol(al->map, al->addr, filter); 677 al->sym = map__find_symbol(al->map, al->addr,
678 machine->symbol_filter);
679 else 679 else
680 al->sym = NULL; 680 al->sym = NULL;
681} 681}
@@ -683,8 +683,7 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
683int perf_event__preprocess_sample(const union perf_event *event, 683int perf_event__preprocess_sample(const union perf_event *event,
684 struct machine *machine, 684 struct machine *machine,
685 struct addr_location *al, 685 struct addr_location *al,
686 struct perf_sample *sample, 686 struct perf_sample *sample)
687 symbol_filter_t filter)
688{ 687{
689 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 688 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
690 struct thread *thread = machine__findnew_thread(machine, event->ip.pid); 689 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
@@ -709,7 +708,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
709 machine__create_kernel_maps(machine); 708 machine__create_kernel_maps(machine);
710 709
711 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 710 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
712 event->ip.ip, al, filter); 711 event->ip.ip, al);
713 dump_printf(" ...... dso: %s\n", 712 dump_printf(" ...... dso: %s\n",
714 al->map ? al->map->dso->long_name : 713 al->map ? al->map->dso->long_name :
715 al->level == 'H' ? "[hypervisor]" : "<not found>"); 714 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -727,7 +726,8 @@ int perf_event__preprocess_sample(const union perf_event *event,
727 dso->long_name))))) 726 dso->long_name)))))
728 goto out_filtered; 727 goto out_filtered;
729 728
730 al->sym = map__find_symbol(al->map, al->addr, filter); 729 al->sym = map__find_symbol(al->map, al->addr,
730 machine->symbol_filter);
731 } 731 }
732 732
733 if (symbol_conf.sym_list && 733 if (symbol_conf.sym_list &&
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 6119a649d861..15db071d96b5 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -234,8 +234,7 @@ struct addr_location;
234int perf_event__preprocess_sample(const union perf_event *self, 234int perf_event__preprocess_sample(const union perf_event *self,
235 struct machine *machine, 235 struct machine *machine,
236 struct addr_location *al, 236 struct addr_location *al,
237 struct perf_sample *sample, 237 struct perf_sample *sample);
238 symbol_filter_t filter);
239 238
240const char *perf_event__name(unsigned int id); 239const char *perf_event__name(unsigned int id);
241 240
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index f558f83769af..a33197a4fd21 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -716,18 +716,19 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu)
716 char filename[MAXPATHLEN]; 716 char filename[MAXPATHLEN];
717 char *buf = NULL, *p; 717 char *buf = NULL, *p;
718 size_t len = 0; 718 size_t len = 0;
719 ssize_t sret;
719 u32 i = 0; 720 u32 i = 0;
720 int ret = -1; 721 int ret = -1;
721 722
722 sprintf(filename, CORE_SIB_FMT, cpu); 723 sprintf(filename, CORE_SIB_FMT, cpu);
723 fp = fopen(filename, "r"); 724 fp = fopen(filename, "r");
724 if (!fp) 725 if (!fp)
725 return -1; 726 goto try_threads;
726
727 if (getline(&buf, &len, fp) <= 0)
728 goto done;
729 727
728 sret = getline(&buf, &len, fp);
730 fclose(fp); 729 fclose(fp);
730 if (sret <= 0)
731 goto try_threads;
731 732
732 p = strchr(buf, '\n'); 733 p = strchr(buf, '\n');
733 if (p) 734 if (p)
@@ -743,7 +744,9 @@ static int build_cpu_topo(struct cpu_topo *tp, int cpu)
743 buf = NULL; 744 buf = NULL;
744 len = 0; 745 len = 0;
745 } 746 }
747 ret = 0;
746 748
749try_threads:
747 sprintf(filename, THRD_SIB_FMT, cpu); 750 sprintf(filename, THRD_SIB_FMT, cpu);
748 fp = fopen(filename, "r"); 751 fp = fopen(filename, "r");
749 if (!fp) 752 if (!fp)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6fcc358138ae..4514e7e9b659 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -25,6 +25,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
25 machine->kmaps.machine = machine; 25 machine->kmaps.machine = machine;
26 machine->pid = pid; 26 machine->pid = pid;
27 27
28 machine->symbol_filter = NULL;
29
28 machine->root_dir = strdup(root_dir); 30 machine->root_dir = strdup(root_dir);
29 if (machine->root_dir == NULL) 31 if (machine->root_dir == NULL)
30 return -ENOMEM; 32 return -ENOMEM;
@@ -95,6 +97,7 @@ void machines__init(struct machines *machines)
95{ 97{
96 machine__init(&machines->host, "", HOST_KERNEL_ID); 98 machine__init(&machines->host, "", HOST_KERNEL_ID);
97 machines->guests = RB_ROOT; 99 machines->guests = RB_ROOT;
100 machines->symbol_filter = NULL;
98} 101}
99 102
100void machines__exit(struct machines *machines) 103void machines__exit(struct machines *machines)
@@ -118,6 +121,8 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
118 return NULL; 121 return NULL;
119 } 122 }
120 123
124 machine->symbol_filter = machines->symbol_filter;
125
121 while (*p != NULL) { 126 while (*p != NULL) {
122 parent = *p; 127 parent = *p;
123 pos = rb_entry(parent, struct machine, rb_node); 128 pos = rb_entry(parent, struct machine, rb_node);
@@ -133,6 +138,21 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
133 return machine; 138 return machine;
134} 139}
135 140
141void machines__set_symbol_filter(struct machines *machines,
142 symbol_filter_t symbol_filter)
143{
144 struct rb_node *nd;
145
146 machines->symbol_filter = symbol_filter;
147 machines->host.symbol_filter = symbol_filter;
148
149 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
150 struct machine *machine = rb_entry(nd, struct machine, rb_node);
151
152 machine->symbol_filter = symbol_filter;
153 }
154}
155
136struct machine *machines__find(struct machines *machines, pid_t pid) 156struct machine *machines__find(struct machines *machines, pid_t pid)
137{ 157{
138 struct rb_node **p = &machines->guests.rb_node; 158 struct rb_node **p = &machines->guests.rb_node;
@@ -1110,7 +1130,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1110 * or else, the symbol is unknown 1130 * or else, the symbol is unknown
1111 */ 1131 */
1112 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, 1132 thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
1113 ip, &al, NULL); 1133 ip, &al);
1114 if (al.sym) 1134 if (al.sym)
1115 goto found; 1135 goto found;
1116 } 1136 }
@@ -1128,8 +1148,8 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1128 1148
1129 memset(&al, 0, sizeof(al)); 1149 memset(&al, 0, sizeof(al));
1130 1150
1131 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, &al, 1151 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
1132 NULL); 1152 &al);
1133 ams->addr = addr; 1153 ams->addr = addr;
1134 ams->al_addr = al.addr; 1154 ams->al_addr = al.addr;
1135 ams->sym = al.sym; 1155 ams->sym = al.sym;
@@ -1224,7 +1244,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1224 1244
1225 al.filtered = false; 1245 al.filtered = false;
1226 thread__find_addr_location(thread, machine, cpumode, 1246 thread__find_addr_location(thread, machine, cpumode,
1227 MAP__FUNCTION, ip, &al, NULL); 1247 MAP__FUNCTION, ip, &al);
1228 if (al.sym != NULL) { 1248 if (al.sym != NULL) {
1229 if (sort__has_parent && !*parent && 1249 if (sort__has_parent && !*parent &&
1230 symbol__match_regex(al.sym, &parent_regex)) 1250 symbol__match_regex(al.sym, &parent_regex))
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 5bb6244194d5..603ffba999d9 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -29,6 +29,7 @@ struct machine {
29 struct list_head kernel_dsos; 29 struct list_head kernel_dsos;
30 struct map_groups kmaps; 30 struct map_groups kmaps;
31 struct map *vmlinux_maps[MAP__NR_TYPES]; 31 struct map *vmlinux_maps[MAP__NR_TYPES];
32 symbol_filter_t symbol_filter;
32}; 33};
33 34
34static inline 35static inline
@@ -51,6 +52,7 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);
51struct machines { 52struct machines {
52 struct machine host; 53 struct machine host;
53 struct rb_root guests; 54 struct rb_root guests;
55 symbol_filter_t symbol_filter;
54}; 56};
55 57
56void machines__init(struct machines *machines); 58void machines__init(struct machines *machines);
@@ -68,6 +70,9 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid);
68void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 70void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
69char *machine__mmap_name(struct machine *machine, char *bf, size_t size); 71char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
70 72
73void machines__set_symbol_filter(struct machines *machines,
74 symbol_filter_t symbol_filter);
75
71int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 76int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
72void machine__exit(struct machine *machine); 77void machine__exit(struct machine *machine);
73void machine__delete_dead_threads(struct machine *machine); 78void machine__delete_dead_threads(struct machine *machine);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index dedaeb22b7b9..de16a7736859 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1401,12 +1401,15 @@ int perf_session__process_events(struct perf_session *self,
1401 1401
1402bool perf_session__has_traces(struct perf_session *session, const char *msg) 1402bool perf_session__has_traces(struct perf_session *session, const char *msg)
1403{ 1403{
1404 if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) { 1404 struct perf_evsel *evsel;
1405 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); 1405
1406 return false; 1406 list_for_each_entry(evsel, &session->evlist->entries, node) {
1407 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1408 return true;
1407 } 1409 }
1408 1410
1409 return true; 1411 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
1412 return false;
1410} 1413}
1411 1414
1412int maps__set_kallsyms_ref_reloc_sym(struct map **maps, 1415int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
@@ -1489,13 +1492,18 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1489 1492
1490void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 1493void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1491 struct perf_sample *sample, struct machine *machine, 1494 struct perf_sample *sample, struct machine *machine,
1492 int print_sym, int print_dso, int print_symoffset) 1495 unsigned int print_opts, unsigned int stack_depth)
1493{ 1496{
1494 struct addr_location al; 1497 struct addr_location al;
1495 struct callchain_cursor_node *node; 1498 struct callchain_cursor_node *node;
1496 1499 int print_ip = print_opts & PRINT_IP_OPT_IP;
1497 if (perf_event__preprocess_sample(event, machine, &al, sample, 1500 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1498 NULL) < 0) { 1501 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1502 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1503 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1504 char s = print_oneline ? ' ' : '\t';
1505
1506 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
1499 error("problem processing %d event, skipping it.\n", 1507 error("problem processing %d event, skipping it.\n",
1500 event->header.type); 1508 event->header.type);
1501 return; 1509 return;
@@ -1511,12 +1519,14 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1511 } 1519 }
1512 callchain_cursor_commit(&callchain_cursor); 1520 callchain_cursor_commit(&callchain_cursor);
1513 1521
1514 while (1) { 1522 while (stack_depth) {
1515 node = callchain_cursor_current(&callchain_cursor); 1523 node = callchain_cursor_current(&callchain_cursor);
1516 if (!node) 1524 if (!node)
1517 break; 1525 break;
1518 1526
1519 printf("\t%16" PRIx64, node->ip); 1527 if (print_ip)
1528 printf("%c%16" PRIx64, s, node->ip);
1529
1520 if (print_sym) { 1530 if (print_sym) {
1521 printf(" "); 1531 printf(" ");
1522 if (print_symoffset) { 1532 if (print_symoffset) {
@@ -1531,13 +1541,19 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1531 map__fprintf_dsoname(node->map, stdout); 1541 map__fprintf_dsoname(node->map, stdout);
1532 printf(")"); 1542 printf(")");
1533 } 1543 }
1534 printf("\n"); 1544
1545 if (!print_oneline)
1546 printf("\n");
1535 1547
1536 callchain_cursor_advance(&callchain_cursor); 1548 callchain_cursor_advance(&callchain_cursor);
1549
1550 stack_depth--;
1537 } 1551 }
1538 1552
1539 } else { 1553 } else {
1540 printf("%16" PRIx64, sample->ip); 1554 if (print_ip)
1555 printf("%16" PRIx64, sample->ip);
1556
1541 if (print_sym) { 1557 if (print_sym) {
1542 printf(" "); 1558 printf(" ");
1543 if (print_symoffset) 1559 if (print_symoffset)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 8bed17e64a96..3aa75fb2225f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -41,6 +41,12 @@ struct perf_session {
41 char filename[1]; 41 char filename[1];
42}; 42};
43 43
44#define PRINT_IP_OPT_IP (1<<0)
45#define PRINT_IP_OPT_SYM (1<<1)
46#define PRINT_IP_OPT_DSO (1<<2)
47#define PRINT_IP_OPT_SYMOFFSET (1<<3)
48#define PRINT_IP_OPT_ONELINE (1<<4)
49
44struct perf_tool; 50struct perf_tool;
45 51
46struct perf_session *perf_session__new(const char *filename, int mode, 52struct perf_session *perf_session__new(const char *filename, int mode,
@@ -103,7 +109,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
103 109
104void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 110void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
105 struct perf_sample *sample, struct machine *machine, 111 struct perf_sample *sample, struct machine *machine,
106 int print_sym, int print_dso, int print_symoffset); 112 unsigned int print_opts, unsigned int stack_depth);
107 113
108int perf_session__cpu_bitmap(struct perf_session *session, 114int perf_session__cpu_bitmap(struct perf_session *session,
109 const char *cpu_list, unsigned long *cpu_bitmap); 115 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index f98d1d983547..13c62c909392 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -41,12 +41,11 @@ static inline struct map *thread__find_map(struct thread *self,
41 41
42void thread__find_addr_map(struct thread *thread, struct machine *machine, 42void thread__find_addr_map(struct thread *thread, struct machine *machine,
43 u8 cpumode, enum map_type type, u64 addr, 43 u8 cpumode, enum map_type type, u64 addr,
44 struct addr_location *al, symbol_filter_t filter); 44 struct addr_location *al);
45 45
46void thread__find_addr_location(struct thread *thread, struct machine *machine, 46void thread__find_addr_location(struct thread *thread, struct machine *machine,
47 u8 cpumode, enum map_type type, u64 addr, 47 u8 cpumode, enum map_type type, u64 addr,
48 struct addr_location *al, 48 struct addr_location *al);
49 symbol_filter_t filter);
50 49
51static inline void *thread__priv(struct thread *thread) 50static inline void *thread__priv(struct thread *thread)
52{ 51{
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
index 5bbd4947c27d..2f891f7e70bf 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind.c
@@ -272,7 +272,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
272 struct addr_location al; 272 struct addr_location al;
273 273
274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
275 MAP__FUNCTION, ip, &al, NULL); 275 MAP__FUNCTION, ip, &al);
276 return al.map; 276 return al.map;
277} 277}
278 278
@@ -349,7 +349,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
349 ssize_t size; 349 ssize_t size;
350 350
351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
352 MAP__FUNCTION, addr, &al, NULL); 352 MAP__FUNCTION, addr, &al);
353 if (!al.map) { 353 if (!al.map) {
354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
355 return -1; 355 return -1;
@@ -473,7 +473,7 @@ static int entry(u64 ip, struct thread *thread, struct machine *machine,
473 473
474 thread__find_addr_location(thread, machine, 474 thread__find_addr_location(thread, machine,
475 PERF_RECORD_MISC_USER, 475 PERF_RECORD_MISC_USER,
476 MAP__FUNCTION, ip, &al, NULL); 476 MAP__FUNCTION, ip, &al);
477 477
478 e.ip = ip; 478 e.ip = ip;
479 e.map = al.map; 479 e.map = al.map;