diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-08-15 03:48:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-08-15 03:48:17 -0400 |
commit | 58cea307432e3376293e6b2be88d1f6e6e99274a (patch) | |
tree | 4f1a04fccc12b6ff58b2a10e6ca9f2fcaac4adbe /tools/perf | |
parent | 0a3d23a2568ed5e73bd4fb532dc672fa9f03b1f1 (diff) | |
parent | 2ae3a312c0ccd8ff615372f00aab1700aac27474 (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.txt | 46 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-trace.txt | 4 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 5 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-inject.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-kvm.c | 25 | ||||
-rw-r--r-- | tools/perf/builtin-mem.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 94 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 35 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 5 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 52 | ||||
-rw-r--r-- | tools/perf/perf.h | 3 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 13 | ||||
-rw-r--r-- | tools/perf/tests/hists_link.c | 4 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 20 | ||||
-rw-r--r-- | tools/perf/util/event.h | 3 | ||||
-rw-r--r-- | tools/perf/util/header.c | 11 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 28 | ||||
-rw-r--r-- | tools/perf/util/machine.h | 5 | ||||
-rw-r--r-- | tools/perf/util/session.c | 40 | ||||
-rw-r--r-- | tools/perf/util/session.h | 8 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 5 | ||||
-rw-r--r-- | tools/perf/util/unwind.c | 6 |
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 | ||
17 | DESCRIPTION | 18 | DESCRIPTION |
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 | |||
53 | OPTIONS | 58 | OPTIONS |
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 | |||
104 | STAT 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 | ||
96 | SEE ALSO | 138 | SEE 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, | |||
473 | static bool handle_end_event(struct perf_kvm_stat *kvm, | 474 | static 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; | |||
14 | struct perf_mem { | 14 | struct 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 | ||
720 | static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, | 721 | static 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 | ||
827 | static 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 | |||
835 | static char sched_out_state(u64 prev_state) | 835 | static 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 | ||
1382 | static int process_sched_fork_event(struct perf_tool *tool, | 1382 | static 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 | ||
1395 | static 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 | ||
1448 | static int perf_sched__read_events(struct perf_sched *sched, bool destroy, | 1436 | static 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 { | |||
66 | static struct { | 66 | static 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) | |||
47 | struct syscall { | 48 | struct 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 | ||
129 | static inline unsigned long long rdclock(void) | 132 | static 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 | ||
305 | static void do_sort_something(void) | 305 | static 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, | |||
592 | void thread__find_addr_map(struct thread *self, | 592 | void 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 | ||
671 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 671 | void 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, | |||
683 | int perf_event__preprocess_sample(const union perf_event *event, | 683 | int 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; | |||
234 | int perf_event__preprocess_sample(const union perf_event *self, | 234 | int 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 | ||
240 | const char *perf_event__name(unsigned int id); | 239 | const 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 | ||
749 | try_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 | ||
100 | void machines__exit(struct machines *machines) | 103 | void 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 | ||
141 | void 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 | |||
136 | struct machine *machines__find(struct machines *machines, pid_t pid) | 156 | struct 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 | ||
34 | static inline | 35 | static inline |
@@ -51,6 +52,7 @@ typedef void (*machine__process_t)(struct machine *machine, void *data); | |||
51 | struct machines { | 52 | struct 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 | ||
56 | void machines__init(struct machines *machines); | 58 | void machines__init(struct machines *machines); |
@@ -68,6 +70,9 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid); | |||
68 | void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); | 70 | void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); |
69 | char *machine__mmap_name(struct machine *machine, char *bf, size_t size); | 71 | char *machine__mmap_name(struct machine *machine, char *bf, size_t size); |
70 | 72 | ||
73 | void machines__set_symbol_filter(struct machines *machines, | ||
74 | symbol_filter_t symbol_filter); | ||
75 | |||
71 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid); | 76 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid); |
72 | void machine__exit(struct machine *machine); | 77 | void machine__exit(struct machine *machine); |
73 | void machine__delete_dead_threads(struct machine *machine); | 78 | void 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 | ||
1402 | bool perf_session__has_traces(struct perf_session *session, const char *msg) | 1402 | bool 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 | ||
1412 | int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | 1415 | int 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 | ||
1490 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 1493 | void 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 | |||
44 | struct perf_tool; | 50 | struct perf_tool; |
45 | 51 | ||
46 | struct perf_session *perf_session__new(const char *filename, int mode, | 52 | struct 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 | ||
104 | void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | 110 | void 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 | ||
108 | int perf_session__cpu_bitmap(struct perf_session *session, | 114 | int 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 | ||
42 | void thread__find_addr_map(struct thread *thread, struct machine *machine, | 42 | void 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 | ||
46 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 46 | void 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 | ||
51 | static inline void *thread__priv(struct thread *thread) | 50 | static 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; |