aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2018-08-20 12:05:17 -0400
committerJiri Kosina <jkosina@suse.cz>2018-08-20 12:05:17 -0400
commit415d2b3392d7a80903e0f97f051201aa02bf20e9 (patch)
tree47492d2386a0e7f00ef645313cb44ae4960b7e7e /tools/perf
parent4f65245f2d178b9cba48350620d76faa4a098841 (diff)
parentb8e759b8f6dab1c473c30ac12709095d0b81078e (diff)
Merge branch 'for-4.19/cougar' into for-linus
New device support for hid-cougar
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-list.txt6
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/Documentation/perf-script-python.txt26
-rw-r--r--tools/perf/Documentation/perf-stat.txt43
-rw-r--r--tools/perf/arch/common.c4
-rw-r--r--tools/perf/arch/common.h4
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c2
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl2
-rw-r--r--tools/perf/bench/numa.c5
-rw-r--r--tools/perf/builtin-annotate.c47
-rw-r--r--tools/perf/builtin-c2c.c12
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/builtin-probe.c3
-rw-r--r--tools/perf/builtin-report.c42
-rw-r--r--tools/perf/builtin-sched.c14
-rw-r--r--tools/perf/builtin-script.c54
-rw-r--r--tools/perf/builtin-stat.c76
-rw-r--r--tools/perf/builtin-top.c48
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/scripts/python/bin/powerpc-hcalls-record2
-rw-r--r--tools/perf/scripts/python/bin/powerpc-hcalls-report2
-rw-r--r--tools/perf/scripts/python/powerpc-hcalls.py200
-rw-r--r--tools/perf/tests/code-reading.c1
-rw-r--r--tools/perf/tests/kmod-path.c16
-rw-r--r--tools/perf/tests/parse-events.c29
-rw-r--r--tools/perf/tests/python-use.c3
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh2
-rw-r--r--tools/perf/tests/topology.c1
-rw-r--r--tools/perf/ui/browsers/annotate.c21
-rw-r--r--tools/perf/ui/browsers/hists.c43
-rw-r--r--tools/perf/ui/browsers/hists.h3
-rw-r--r--tools/perf/ui/gtk/annotate.c2
-rw-r--r--tools/perf/ui/gtk/hists.c5
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/ui/stdio/hist.c4
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c165
-rw-r--r--tools/perf/util/annotate.h53
-rw-r--r--tools/perf/util/bpf-prologue.c2
-rw-r--r--tools/perf/util/c++/clang.cpp11
-rw-r--r--tools/perf/util/cgroup.c9
-rw-r--r--tools/perf/util/dso.c2
-rw-r--r--tools/perf/util/evsel.c4
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/header.c36
-rw-r--r--tools/perf/util/hist.c27
-rw-r--r--tools/perf/util/hist.h26
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c23
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h9
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt.c5
-rw-r--r--tools/perf/util/map.c26
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/parse-events.l18
-rw-r--r--tools/perf/util/parse-events.y19
-rw-r--r--tools/perf/util/pmu.c99
-rw-r--r--tools/perf/util/probe-event.c3
-rw-r--r--tools/perf/util/quote.c62
-rw-r--r--tools/perf/util/quote.h31
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c250
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/sort.c81
-rw-r--r--tools/perf/util/sort.h9
-rw-r--r--tools/perf/util/symbol.c3
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/top.h3
67 files changed, 1245 insertions, 477 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 2549c34a7895..11300dbe35c5 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -124,7 +124,11 @@ The available PMUs and their raw parameters can be listed with
124For example the raw event "LSD.UOPS" core pmu event above could 124For example the raw event "LSD.UOPS" core pmu event above could
125be specified as 125be specified as
126 126
127 perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=1/ ... 127 perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=0x1/ ...
128
129 or using extended name syntax
130
131 perf stat -e cpu/event=0xa8,umask=0x1,cmask=0x1,name=\'LSD.UOPS_CYCLES:cmask=0x1\'/ ...
128 132
129PER SOCKET PMUS 133PER SOCKET PMUS
130--------------- 134---------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index cc37b3a4be76..04168da4268e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -57,6 +57,9 @@ OPTIONS
57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and 57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and
58 "no" for disable callgraph. 58 "no" for disable callgraph.
59 - 'stack-size': user stack size for dwarf mode 59 - 'stack-size': user stack size for dwarf mode
60 - 'name' : User defined event name. Single quotes (') may be used to
61 escape symbols in the name from parsing by shell and tool
62 like this: name=\'CPU_CLK_UNHALTED.THREAD:cmask=0x1\'.
60 63
61 See the linkperf:perf-list[1] man page for more parameters. 64 See the linkperf:perf-list[1] man page for more parameters.
62 65
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 51ec2d20068a..0fb9eda3cbca 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -610,6 +610,32 @@ Various utility functions for use with perf script:
610 nsecs_str(nsecs) - returns printable string in the form secs.nsecs 610 nsecs_str(nsecs) - returns printable string in the form secs.nsecs
611 avg(total, n) - returns average given a sum and a total number of values 611 avg(total, n) - returns average given a sum and a total number of values
612 612
613SUPPORTED FIELDS
614----------------
615
616Currently supported fields:
617
618ev_name, comm, pid, tid, cpu, ip, time, period, phys_addr, addr,
619symbol, dso, time_enabled, time_running, values, callchain,
620brstack, brstacksym, datasrc, datasrc_decode, iregs, uregs,
621weight, transaction, raw_buf, attr.
622
623Some fields have sub items:
624
625brstack:
626 from, to, from_dsoname, to_dsoname, mispred,
627 predicted, in_tx, abort, cycles.
628
629brstacksym:
630 items: from, to, pred, in_tx, abort (converted string)
631
632For example,
633We can use this code to print brstack "from", "to", "cycles".
634
635if 'brstack' in dict:
636 for entry in dict['brstack']:
637 print "from %s, to %s, cycles %s" % (entry["from"], entry["to"], entry["cycles"])
638
613SEE ALSO 639SEE ALSO
614-------- 640--------
615linkperf:perf-script[1] 641linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 3a822f308e6d..b10a90b6a718 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -178,6 +178,9 @@ Print count deltas for fixed number of times.
178This option should be used together with "-I" option. 178This option should be used together with "-I" option.
179 example: 'perf stat -I 1000 --interval-count 2 -e cycles -a' 179 example: 'perf stat -I 1000 --interval-count 2 -e cycles -a'
180 180
181--interval-clear::
182Clear the screen before next interval.
183
181--timeout msecs:: 184--timeout msecs::
182Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms). 185Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms).
183This option is not supported with the "-I" option. 186This option is not supported with the "-I" option.
@@ -310,20 +313,38 @@ Users who wants to get the actual value can apply --no-metric-only.
310EXAMPLES 313EXAMPLES
311-------- 314--------
312 315
313$ perf stat -- make -j 316$ perf stat -- make
317
318 Performance counter stats for 'make':
319
320 83723.452481 task-clock:u (msec) # 1.004 CPUs utilized
321 0 context-switches:u # 0.000 K/sec
322 0 cpu-migrations:u # 0.000 K/sec
323 3,228,188 page-faults:u # 0.039 M/sec
324 229,570,665,834 cycles:u # 2.742 GHz
325 313,163,853,778 instructions:u # 1.36 insn per cycle
326 69,704,684,856 branches:u # 832.559 M/sec
327 2,078,861,393 branch-misses:u # 2.98% of all branches
328
329 83.409183620 seconds time elapsed
330
331 74.684747000 seconds user
332 8.739217000 seconds sys
333
334TIMINGS
335-------
336As displayed in the example above we can display 3 types of timings.
337We always display the time the counters were enabled/alive:
338
339 83.409183620 seconds time elapsed
314 340
315 Performance counter stats for 'make -j': 341For workload sessions we also display time the workloads spent in
342user/system lands:
316 343
317 8117.370256 task clock ticks # 11.281 CPU utilization factor 344 74.684747000 seconds user
318 678 context switches # 0.000 M/sec 345 8.739217000 seconds sys
319 133 CPU migrations # 0.000 M/sec
320 235724 pagefaults # 0.029 M/sec
321 24821162526 CPU cycles # 3057.784 M/sec
322 18687303457 instructions # 2302.138 M/sec
323 172158895 cache references # 21.209 M/sec
324 27075259 cache misses # 3.335 M/sec
325 346
326 Wall-clock time elapsed: 719.554352 msecs 347Those times are the very same as displayed by the 'time' tool.
327 348
328CSV FORMAT 349CSV FORMAT
329---------- 350----------
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index c6f373508a4f..82657c01a3b8 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -189,7 +189,7 @@ out_error:
189 return -1; 189 return -1;
190} 190}
191 191
192int perf_env__lookup_objdump(struct perf_env *env) 192int perf_env__lookup_objdump(struct perf_env *env, const char **path)
193{ 193{
194 /* 194 /*
195 * For live mode, env->arch will be NULL and we can use 195 * For live mode, env->arch will be NULL and we can use
@@ -198,5 +198,5 @@ int perf_env__lookup_objdump(struct perf_env *env)
198 if (env->arch == NULL) 198 if (env->arch == NULL)
199 return 0; 199 return 0;
200 200
201 return perf_env__lookup_binutils_path(env, "objdump", &objdump_path); 201 return perf_env__lookup_binutils_path(env, "objdump", path);
202} 202}
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index 2d875baa92e6..2167001b18c5 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -4,8 +4,6 @@
4 4
5#include "../util/env.h" 5#include "../util/env.h"
6 6
7extern const char *objdump_path; 7int perf_env__lookup_objdump(struct perf_env *env, const char **path);
8
9int perf_env__lookup_objdump(struct perf_env *env);
10 8
11#endif /* ARCH_PERF_COMMON_H */ 9#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index 3598b8b75d27..ef5d59a5742e 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -243,7 +243,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
243 u64 ip; 243 u64 ip;
244 u64 skip_slot = -1; 244 u64 skip_slot = -1;
245 245
246 if (chain->nr < 3) 246 if (!chain || chain->nr < 3)
247 return skip_slot; 247 return skip_slot;
248 248
249 ip = chain->ips[2]; 249 ip = chain->ips[2];
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 4dfe42666d0c..f0b1709a5ffb 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -341,6 +341,8 @@
341330 common pkey_alloc __x64_sys_pkey_alloc 341330 common pkey_alloc __x64_sys_pkey_alloc
342331 common pkey_free __x64_sys_pkey_free 342331 common pkey_free __x64_sys_pkey_free
343332 common statx __x64_sys_statx 343332 common statx __x64_sys_statx
344333 common io_pgetevents __x64_sys_io_pgetevents
345334 common rseq __x64_sys_rseq
344 346
345# 347#
346# x32-specific system call numbers start at 512 to avoid cache impact 348# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 63eb49082774..44195514b19e 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1098,7 +1098,7 @@ static void *worker_thread(void *__tdata)
1098 u8 *global_data; 1098 u8 *global_data;
1099 u8 *process_data; 1099 u8 *process_data;
1100 u8 *thread_data; 1100 u8 *thread_data;
1101 u64 bytes_done; 1101 u64 bytes_done, secs;
1102 long work_done; 1102 long work_done;
1103 u32 l; 1103 u32 l;
1104 struct rusage rusage; 1104 struct rusage rusage;
@@ -1254,7 +1254,8 @@ static void *worker_thread(void *__tdata)
1254 timersub(&stop, &start0, &diff); 1254 timersub(&stop, &start0, &diff);
1255 td->runtime_ns = diff.tv_sec * NSEC_PER_SEC; 1255 td->runtime_ns = diff.tv_sec * NSEC_PER_SEC;
1256 td->runtime_ns += diff.tv_usec * NSEC_PER_USEC; 1256 td->runtime_ns += diff.tv_usec * NSEC_PER_USEC;
1257 td->speed_gbs = bytes_done / (td->runtime_ns / NSEC_PER_SEC) / 1e9; 1257 secs = td->runtime_ns / NSEC_PER_SEC;
1258 td->speed_gbs = secs ? bytes_done / secs / 1e9 : 0;
1258 1259
1259 getrusage(RUSAGE_THREAD, &rusage); 1260 getrusage(RUSAGE_THREAD, &rusage);
1260 td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC; 1261 td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC;
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index da5704240239..8180319285af 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,9 +40,8 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 struct annotation_options opts;
43 bool use_tui, use_stdio, use_stdio2, use_gtk; 44 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths;
45 bool print_line;
46 bool skip_missing; 45 bool skip_missing;
47 bool has_br_stack; 46 bool has_br_stack;
48 bool group_set; 47 bool group_set;
@@ -162,12 +161,12 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
162 hist__account_cycles(sample->branch_stack, al, sample, false); 161 hist__account_cycles(sample->branch_stack, al, sample, false);
163 162
164 bi = he->branch_info; 163 bi = he->branch_info;
165 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx); 164 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
166 165
167 if (err) 166 if (err)
168 goto out; 167 goto out;
169 168
170 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx); 169 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
171 170
172out: 171out:
173 return err; 172 return err;
@@ -249,7 +248,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
249 if (he == NULL) 248 if (he == NULL)
250 return -ENOMEM; 249 return -ENOMEM;
251 250
252 ret = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr); 251 ret = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
253 hists__inc_nr_samples(hists, true); 252 hists__inc_nr_samples(hists, true);
254 return ret; 253 return ret;
255} 254}
@@ -284,15 +283,23 @@ out_put:
284 return ret; 283 return ret;
285} 284}
286 285
286static int process_feature_event(struct perf_tool *tool,
287 union perf_event *event,
288 struct perf_session *session)
289{
290 if (event->feat.feat_id < HEADER_LAST_FEATURE)
291 return perf_event__process_feature(tool, event, session);
292 return 0;
293}
294
287static int hist_entry__tty_annotate(struct hist_entry *he, 295static int hist_entry__tty_annotate(struct hist_entry *he,
288 struct perf_evsel *evsel, 296 struct perf_evsel *evsel,
289 struct perf_annotate *ann) 297 struct perf_annotate *ann)
290{ 298{
291 if (!ann->use_stdio2) 299 if (!ann->use_stdio2)
292 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 300 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, &ann->opts);
293 ann->print_line, ann->full_paths, 0, 0); 301
294 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, 302 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, &ann->opts);
295 ann->print_line, ann->full_paths);
296} 303}
297 304
298static void hists__find_annotations(struct hists *hists, 305static void hists__find_annotations(struct hists *hists,
@@ -343,7 +350,7 @@ find_next:
343 /* skip missing symbols */ 350 /* skip missing symbols */
344 nd = rb_next(nd); 351 nd = rb_next(nd);
345 } else if (use_browser == 1) { 352 } else if (use_browser == 1) {
346 key = hist_entry__tui_annotate(he, evsel, NULL); 353 key = hist_entry__tui_annotate(he, evsel, NULL, &ann->opts);
347 354
348 switch (key) { 355 switch (key) {
349 case -1: 356 case -1:
@@ -390,8 +397,9 @@ static int __cmd_annotate(struct perf_annotate *ann)
390 goto out; 397 goto out;
391 } 398 }
392 399
393 if (!objdump_path) { 400 if (!ann->opts.objdump_path) {
394 ret = perf_env__lookup_objdump(&session->header.env); 401 ret = perf_env__lookup_objdump(&session->header.env,
402 &ann->opts.objdump_path);
395 if (ret) 403 if (ret)
396 goto out; 404 goto out;
397 } 405 }
@@ -472,10 +480,11 @@ int cmd_annotate(int argc, const char **argv)
472 .attr = perf_event__process_attr, 480 .attr = perf_event__process_attr,
473 .build_id = perf_event__process_build_id, 481 .build_id = perf_event__process_build_id,
474 .tracing_data = perf_event__process_tracing_data, 482 .tracing_data = perf_event__process_tracing_data,
475 .feature = perf_event__process_feature, 483 .feature = process_feature_event,
476 .ordered_events = true, 484 .ordered_events = true,
477 .ordering_requires_timestamps = true, 485 .ordering_requires_timestamps = true,
478 }, 486 },
487 .opts = annotation__default_options,
479 }; 488 };
480 struct perf_data data = { 489 struct perf_data data = {
481 .mode = PERF_DATA_MODE_READ, 490 .mode = PERF_DATA_MODE_READ,
@@ -503,9 +512,9 @@ int cmd_annotate(int argc, const char **argv)
503 "file", "vmlinux pathname"), 512 "file", "vmlinux pathname"),
504 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 513 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
505 "load module symbols - WARNING: use only with -k and LIVE kernel"), 514 "load module symbols - WARNING: use only with -k and LIVE kernel"),
506 OPT_BOOLEAN('l', "print-line", &annotate.print_line, 515 OPT_BOOLEAN('l', "print-line", &annotate.opts.print_lines,
507 "print matching source lines (may be slow)"), 516 "print matching source lines (may be slow)"),
508 OPT_BOOLEAN('P', "full-paths", &annotate.full_paths, 517 OPT_BOOLEAN('P', "full-paths", &annotate.opts.full_path,
509 "Don't shorten the displayed pathnames"), 518 "Don't shorten the displayed pathnames"),
510 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 519 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
511 "Skip symbols that cannot be annotated"), 520 "Skip symbols that cannot be annotated"),
@@ -516,13 +525,13 @@ int cmd_annotate(int argc, const char **argv)
516 OPT_CALLBACK(0, "symfs", NULL, "directory", 525 OPT_CALLBACK(0, "symfs", NULL, "directory",
517 "Look for files with symbols relative to this directory", 526 "Look for files with symbols relative to this directory",
518 symbol__config_symfs), 527 symbol__config_symfs),
519 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 528 OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src,
520 "Interleave source code with assembly code (default)"), 529 "Interleave source code with assembly code (default)"),
521 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 530 OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw,
522 "Display raw encoding of assembly instructions (default)"), 531 "Display raw encoding of assembly instructions (default)"),
523 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 532 OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style",
524 "Specify disassembler style (e.g. -M intel for intel syntax)"), 533 "Specify disassembler style (e.g. -M intel for intel syntax)"),
525 OPT_STRING(0, "objdump", &objdump_path, "path", 534 OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path",
526 "objdump binary to use for disassembly and annotations"), 535 "objdump binary to use for disassembly and annotations"),
527 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 536 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
528 "Show event group information together"), 537 "Show event group information together"),
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 2126bfbcb385..6a8738f7ead3 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -56,16 +56,16 @@ struct c2c_hist_entry {
56 56
57 struct compute_stats cstats; 57 struct compute_stats cstats;
58 58
59 unsigned long paddr;
60 unsigned long paddr_cnt;
61 bool paddr_zero;
62 char *nodestr;
63
59 /* 64 /*
60 * must be at the end, 65 * must be at the end,
61 * because of its callchain dynamic entry 66 * because of its callchain dynamic entry
62 */ 67 */
63 struct hist_entry he; 68 struct hist_entry he;
64
65 unsigned long paddr;
66 unsigned long paddr_cnt;
67 bool paddr_zero;
68 char *nodestr;
69}; 69};
70 70
71static char const *coalesce_default = "pid,iaddr"; 71static char const *coalesce_default = "pid,iaddr";
@@ -1976,7 +1976,7 @@ static int filter_cb(struct hist_entry *he)
1976 c2c_he = container_of(he, struct c2c_hist_entry, he); 1976 c2c_he = container_of(he, struct c2c_hist_entry, he);
1977 1977
1978 if (c2c.show_src && !he->srcline) 1978 if (c2c.show_src && !he->srcline)
1979 he->srcline = hist_entry__get_srcline(he); 1979 he->srcline = hist_entry__srcline(he);
1980 1980
1981 calc_width(c2c_he); 1981 calc_width(c2c_he);
1982 1982
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 72e2ca096bf5..2b1ef704169f 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1438,8 +1438,6 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1438 goto out; 1438 goto out;
1439 } 1439 }
1440 1440
1441 symbol_conf.nr_events = kvm->evlist->nr_entries;
1442
1443 if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0) 1441 if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
1444 usage_with_options(live_usage, live_options); 1442 usage_with_options(live_usage, live_options);
1445 1443
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c0065923a525..99de91698de1 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -81,8 +81,7 @@ static int parse_probe_event(const char *str)
81 params.target_used = true; 81 params.target_used = true;
82 } 82 }
83 83
84 if (params.nsi) 84 pev->nsi = nsinfo__get(params.nsi);
85 pev->nsi = nsinfo__get(params.nsi);
86 85
87 /* Parse a perf-probe command into event */ 86 /* Parse a perf-probe command into event */
88 ret = parse_perf_probe_command(str, pev); 87 ret = parse_perf_probe_command(str, pev);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ad978e3ee2b8..c04dc7b53797 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -71,6 +71,7 @@ struct report {
71 bool group_set; 71 bool group_set;
72 int max_stack; 72 int max_stack;
73 struct perf_read_values show_threads_values; 73 struct perf_read_values show_threads_values;
74 struct annotation_options annotation_opts;
74 const char *pretty_printing_style; 75 const char *pretty_printing_style;
75 const char *cpu_list; 76 const char *cpu_list;
76 const char *symbol_filter_str; 77 const char *symbol_filter_str;
@@ -136,26 +137,25 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
136 137
137 if (sort__mode == SORT_MODE__BRANCH) { 138 if (sort__mode == SORT_MODE__BRANCH) {
138 bi = he->branch_info; 139 bi = he->branch_info;
139 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx); 140 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
140 if (err) 141 if (err)
141 goto out; 142 goto out;
142 143
143 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx); 144 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
144 145
145 } else if (rep->mem_mode) { 146 } else if (rep->mem_mode) {
146 mi = he->mem_info; 147 mi = he->mem_info;
147 err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel->idx); 148 err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel);
148 if (err) 149 if (err)
149 goto out; 150 goto out;
150 151
151 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr); 152 err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
152 153
153 } else if (symbol_conf.cumulate_callchain) { 154 } else if (symbol_conf.cumulate_callchain) {
154 if (single) 155 if (single)
155 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, 156 err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
156 al->addr);
157 } else { 157 } else {
158 err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr); 158 err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
159 } 159 }
160 160
161out: 161out:
@@ -181,11 +181,11 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
181 rep->nonany_branch_mode); 181 rep->nonany_branch_mode);
182 182
183 bi = he->branch_info; 183 bi = he->branch_info;
184 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx); 184 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
185 if (err) 185 if (err)
186 goto out; 186 goto out;
187 187
188 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx); 188 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
189 189
190 branch_type_count(&rep->brtype_stat, &bi->flags, 190 branch_type_count(&rep->brtype_stat, &bi->flags,
191 bi->from.addr, bi->to.addr); 191 bi->from.addr, bi->to.addr);
@@ -217,7 +217,8 @@ static int process_feature_event(struct perf_tool *tool,
217 } 217 }
218 218
219 /* 219 /*
220 * All features are received, we can force the 220 * (feat_id = HEADER_LAST_FEATURE) is the end marker which
221 * means all features are received, now we can force the
221 * group if needed. 222 * group if needed.
222 */ 223 */
223 setup_forced_leader(rep, session->evlist); 224 setup_forced_leader(rep, session->evlist);
@@ -561,7 +562,7 @@ static int report__browse_hists(struct report *rep)
561 ret = perf_evlist__tui_browse_hists(evlist, help, NULL, 562 ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
562 rep->min_percent, 563 rep->min_percent,
563 &session->header.env, 564 &session->header.env,
564 true); 565 true, &rep->annotation_opts);
565 /* 566 /*
566 * Usually "ret" is the last pressed key, and we only 567 * Usually "ret" is the last pressed key, and we only
567 * care if the key notifies us to switch data file. 568 * care if the key notifies us to switch data file.
@@ -946,12 +947,6 @@ parse_percent_limit(const struct option *opt, const char *str,
946 return 0; 947 return 0;
947} 948}
948 949
949#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
950
951const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
952 CALLCHAIN_REPORT_HELP
953 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
954
955int cmd_report(int argc, const char **argv) 950int cmd_report(int argc, const char **argv)
956{ 951{
957 struct perf_session *session; 952 struct perf_session *session;
@@ -960,6 +955,10 @@ int cmd_report(int argc, const char **argv)
960 bool has_br_stack = false; 955 bool has_br_stack = false;
961 int branch_mode = -1; 956 int branch_mode = -1;
962 bool branch_call_mode = false; 957 bool branch_call_mode = false;
958#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
959 const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
960 CALLCHAIN_REPORT_HELP
961 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
963 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 962 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
964 const char * const report_usage[] = { 963 const char * const report_usage[] = {
965 "perf report [<options>]", 964 "perf report [<options>]",
@@ -989,6 +988,7 @@ int cmd_report(int argc, const char **argv)
989 .max_stack = PERF_MAX_STACK_DEPTH, 988 .max_stack = PERF_MAX_STACK_DEPTH,
990 .pretty_printing_style = "normal", 989 .pretty_printing_style = "normal",
991 .socket_filter = -1, 990 .socket_filter = -1,
991 .annotation_opts = annotation__default_options,
992 }; 992 };
993 const struct option options[] = { 993 const struct option options[] = {
994 OPT_STRING('i', "input", &input_name, "file", 994 OPT_STRING('i', "input", &input_name, "file",
@@ -1078,11 +1078,11 @@ int cmd_report(int argc, const char **argv)
1078 "list of cpus to profile"), 1078 "list of cpus to profile"),
1079 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 1079 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
1080 "Display extended information about perf.data file"), 1080 "Display extended information about perf.data file"),
1081 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 1081 OPT_BOOLEAN(0, "source", &report.annotation_opts.annotate_src,
1082 "Interleave source code with assembly code (default)"), 1082 "Interleave source code with assembly code (default)"),
1083 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1083 OPT_BOOLEAN(0, "asm-raw", &report.annotation_opts.show_asm_raw,
1084 "Display raw encoding of assembly instructions (default)"), 1084 "Display raw encoding of assembly instructions (default)"),
1085 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1085 OPT_STRING('M', "disassembler-style", &report.annotation_opts.disassembler_style, "disassembler style",
1086 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1086 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1087 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1087 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1088 "Show a column with the sum of periods"), 1088 "Show a column with the sum of periods"),
@@ -1093,7 +1093,7 @@ int cmd_report(int argc, const char **argv)
1093 parse_branch_mode), 1093 parse_branch_mode),
1094 OPT_BOOLEAN(0, "branch-history", &branch_call_mode, 1094 OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
1095 "add last branch records to call history"), 1095 "add last branch records to call history"),
1096 OPT_STRING(0, "objdump", &objdump_path, "path", 1096 OPT_STRING(0, "objdump", &report.annotation_opts.objdump_path, "path",
1097 "objdump binary to use for disassembly and annotations"), 1097 "objdump binary to use for disassembly and annotations"),
1098 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 1098 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
1099 "Disable symbol demangling"), 1099 "Disable symbol demangling"),
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 4dfdee668b0c..cbf39dab19c1 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2143,7 +2143,7 @@ static void save_task_callchain(struct perf_sched *sched,
2143 return; 2143 return;
2144 } 2144 }
2145 2145
2146 if (!symbol_conf.use_callchain || sample->callchain == NULL) 2146 if (!sched->show_callchain || sample->callchain == NULL)
2147 return; 2147 return;
2148 2148
2149 if (thread__resolve_callchain(thread, cursor, evsel, sample, 2149 if (thread__resolve_callchain(thread, cursor, evsel, sample,
@@ -2271,10 +2271,11 @@ static struct thread *get_idle_thread(int cpu)
2271 return idle_threads[cpu]; 2271 return idle_threads[cpu];
2272} 2272}
2273 2273
2274static void save_idle_callchain(struct idle_thread_runtime *itr, 2274static void save_idle_callchain(struct perf_sched *sched,
2275 struct idle_thread_runtime *itr,
2275 struct perf_sample *sample) 2276 struct perf_sample *sample)
2276{ 2277{
2277 if (!symbol_conf.use_callchain || sample->callchain == NULL) 2278 if (!sched->show_callchain || sample->callchain == NULL)
2278 return; 2279 return;
2279 2280
2280 callchain_cursor__copy(&itr->cursor, &callchain_cursor); 2281 callchain_cursor__copy(&itr->cursor, &callchain_cursor);
@@ -2320,7 +2321,7 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
2320 2321
2321 /* copy task callchain when entering to idle */ 2322 /* copy task callchain when entering to idle */
2322 if (perf_evsel__intval(evsel, sample, "next_pid") == 0) 2323 if (perf_evsel__intval(evsel, sample, "next_pid") == 0)
2323 save_idle_callchain(itr, sample); 2324 save_idle_callchain(sched, itr, sample);
2324 } 2325 }
2325 } 2326 }
2326 2327
@@ -2849,7 +2850,7 @@ static void timehist_print_summary(struct perf_sched *sched,
2849 printf(" CPU %2d idle entire time window\n", i); 2850 printf(" CPU %2d idle entire time window\n", i);
2850 } 2851 }
2851 2852
2852 if (sched->idle_hist && symbol_conf.use_callchain) { 2853 if (sched->idle_hist && sched->show_callchain) {
2853 callchain_param.mode = CHAIN_FOLDED; 2854 callchain_param.mode = CHAIN_FOLDED;
2854 callchain_param.value = CCVAL_PERIOD; 2855 callchain_param.value = CCVAL_PERIOD;
2855 2856
@@ -2933,8 +2934,7 @@ static int timehist_check_attr(struct perf_sched *sched,
2933 return -1; 2934 return -1;
2934 } 2935 }
2935 2936
2936 if (sched->show_callchain && 2937 if (sched->show_callchain && !evsel__has_callchain(evsel)) {
2937 !(evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN)) {
2938 pr_info("Samples do not have callchains.\n"); 2938 pr_info("Samples do not have callchains.\n");
2939 sched->show_callchain = 0; 2939 sched->show_callchain = 0;
2940 symbol_conf.use_callchain = 0; 2940 symbol_conf.use_callchain = 0;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index cefc8813e91e..568ddfac3213 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -180,6 +180,18 @@ static struct {
180 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE 180 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE
181 }, 181 },
182 182
183 [PERF_TYPE_HW_CACHE] = {
184 .user_set = false,
185
186 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
187 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
188 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
189 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
190 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
191
192 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
193 },
194
183 [PERF_TYPE_RAW] = { 195 [PERF_TYPE_RAW] = {
184 .user_set = false, 196 .user_set = false,
185 197
@@ -517,7 +529,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
517 529
518 evlist__for_each_entry(session->evlist, evsel) { 530 evlist__for_each_entry(session->evlist, evsel) {
519 not_pipe = true; 531 not_pipe = true;
520 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { 532 if (evsel__has_callchain(evsel)) {
521 use_callchain = true; 533 use_callchain = true;
522 break; 534 break;
523 } 535 }
@@ -532,22 +544,18 @@ static int perf_session__check_output_opt(struct perf_session *session)
532 */ 544 */
533 if (symbol_conf.use_callchain && 545 if (symbol_conf.use_callchain &&
534 !output[PERF_TYPE_TRACEPOINT].user_set) { 546 !output[PERF_TYPE_TRACEPOINT].user_set) {
535 struct perf_event_attr *attr;
536
537 j = PERF_TYPE_TRACEPOINT; 547 j = PERF_TYPE_TRACEPOINT;
538 548
539 evlist__for_each_entry(session->evlist, evsel) { 549 evlist__for_each_entry(session->evlist, evsel) {
540 if (evsel->attr.type != j) 550 if (evsel->attr.type != j)
541 continue; 551 continue;
542 552
543 attr = &evsel->attr; 553 if (evsel__has_callchain(evsel)) {
544
545 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
546 output[j].fields |= PERF_OUTPUT_IP; 554 output[j].fields |= PERF_OUTPUT_IP;
547 output[j].fields |= PERF_OUTPUT_SYM; 555 output[j].fields |= PERF_OUTPUT_SYM;
548 output[j].fields |= PERF_OUTPUT_SYMOFFSET; 556 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
549 output[j].fields |= PERF_OUTPUT_DSO; 557 output[j].fields |= PERF_OUTPUT_DSO;
550 set_print_ip_opts(attr); 558 set_print_ip_opts(&evsel->attr);
551 goto out; 559 goto out;
552 } 560 }
553 } 561 }
@@ -610,7 +618,7 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
610 if (PRINT_FIELD(COMM)) { 618 if (PRINT_FIELD(COMM)) {
611 if (latency_format) 619 if (latency_format)
612 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread)); 620 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
613 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 621 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
614 printed += fprintf(fp, "%s ", thread__comm_str(thread)); 622 printed += fprintf(fp, "%s ", thread__comm_str(thread));
615 else 623 else
616 printed += fprintf(fp, "%16s ", thread__comm_str(thread)); 624 printed += fprintf(fp, "%16s ", thread__comm_str(thread));
@@ -1826,6 +1834,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
1826 struct perf_evlist *evlist; 1834 struct perf_evlist *evlist;
1827 struct perf_evsel *evsel, *pos; 1835 struct perf_evsel *evsel, *pos;
1828 int err; 1836 int err;
1837 static struct perf_evsel_script *es;
1829 1838
1830 err = perf_event__process_attr(tool, event, pevlist); 1839 err = perf_event__process_attr(tool, event, pevlist);
1831 if (err) 1840 if (err)
@@ -1834,6 +1843,19 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
1834 evlist = *pevlist; 1843 evlist = *pevlist;
1835 evsel = perf_evlist__last(*pevlist); 1844 evsel = perf_evlist__last(*pevlist);
1836 1845
1846 if (!evsel->priv) {
1847 if (scr->per_event_dump) {
1848 evsel->priv = perf_evsel_script__new(evsel,
1849 scr->session->data);
1850 } else {
1851 es = zalloc(sizeof(*es));
1852 if (!es)
1853 return -ENOMEM;
1854 es->fp = stdout;
1855 evsel->priv = es;
1856 }
1857 }
1858
1837 if (evsel->attr.type >= PERF_TYPE_MAX && 1859 if (evsel->attr.type >= PERF_TYPE_MAX &&
1838 evsel->attr.type != PERF_TYPE_SYNTH) 1860 evsel->attr.type != PERF_TYPE_SYNTH)
1839 return 0; 1861 return 0;
@@ -3022,6 +3044,15 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
3022 return set_maps(script); 3044 return set_maps(script);
3023} 3045}
3024 3046
3047static int process_feature_event(struct perf_tool *tool,
3048 union perf_event *event,
3049 struct perf_session *session)
3050{
3051 if (event->feat.feat_id < HEADER_LAST_FEATURE)
3052 return perf_event__process_feature(tool, event, session);
3053 return 0;
3054}
3055
3025#ifdef HAVE_AUXTRACE_SUPPORT 3056#ifdef HAVE_AUXTRACE_SUPPORT
3026static int perf_script__process_auxtrace_info(struct perf_tool *tool, 3057static int perf_script__process_auxtrace_info(struct perf_tool *tool,
3027 union perf_event *event, 3058 union perf_event *event,
@@ -3066,7 +3097,7 @@ int cmd_script(int argc, const char **argv)
3066 .attr = process_attr, 3097 .attr = process_attr,
3067 .event_update = perf_event__process_event_update, 3098 .event_update = perf_event__process_event_update,
3068 .tracing_data = perf_event__process_tracing_data, 3099 .tracing_data = perf_event__process_tracing_data,
3069 .feature = perf_event__process_feature, 3100 .feature = process_feature_event,
3070 .build_id = perf_event__process_build_id, 3101 .build_id = perf_event__process_build_id,
3071 .id_index = perf_event__process_id_index, 3102 .id_index = perf_event__process_id_index,
3072 .auxtrace_info = perf_script__process_auxtrace_info, 3103 .auxtrace_info = perf_script__process_auxtrace_info,
@@ -3117,8 +3148,9 @@ int cmd_script(int argc, const char **argv)
3117 "+field to add and -field to remove." 3148 "+field to add and -field to remove."
3118 "Valid types: hw,sw,trace,raw,synth. " 3149 "Valid types: hw,sw,trace,raw,synth. "
3119 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 3150 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
3120 "addr,symoff,period,iregs,uregs,brstack,brstacksym,flags," 3151 "addr,symoff,srcline,period,iregs,uregs,brstack,"
3121 "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr", 3152 "brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
3153 "callindent,insn,insnlen,synth,phys_addr,metric,misc",
3122 parse_output_fields), 3154 parse_output_fields),
3123 OPT_BOOLEAN('a', "all-cpus", &system_wide, 3155 OPT_BOOLEAN('a', "all-cpus", &system_wide,
3124 "system-wide collection from all CPUs"), 3156 "system-wide collection from all CPUs"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a4f662a462c6..22547a490e1f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -65,6 +65,7 @@
65#include "util/tool.h" 65#include "util/tool.h"
66#include "util/string2.h" 66#include "util/string2.h"
67#include "util/metricgroup.h" 67#include "util/metricgroup.h"
68#include "util/top.h"
68#include "asm/bug.h" 69#include "asm/bug.h"
69 70
70#include <linux/time64.h> 71#include <linux/time64.h>
@@ -80,6 +81,9 @@
80#include <sys/stat.h> 81#include <sys/stat.h>
81#include <sys/wait.h> 82#include <sys/wait.h>
82#include <unistd.h> 83#include <unistd.h>
84#include <sys/time.h>
85#include <sys/resource.h>
86#include <sys/wait.h>
83 87
84#include "sane_ctype.h" 88#include "sane_ctype.h"
85 89
@@ -141,6 +145,8 @@ static struct target target = {
141 145
142typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); 146typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
143 147
148#define METRIC_ONLY_LEN 20
149
144static int run_count = 1; 150static int run_count = 1;
145static bool no_inherit = false; 151static bool no_inherit = false;
146static volatile pid_t child_pid = -1; 152static volatile pid_t child_pid = -1;
@@ -170,11 +176,15 @@ static struct cpu_map *aggr_map;
170static aggr_get_id_t aggr_get_id; 176static aggr_get_id_t aggr_get_id;
171static bool append_file; 177static bool append_file;
172static bool interval_count; 178static bool interval_count;
179static bool interval_clear;
173static const char *output_name; 180static const char *output_name;
174static int output_fd; 181static int output_fd;
175static int print_free_counters_hint; 182static int print_free_counters_hint;
176static int print_mixed_hw_group_error; 183static int print_mixed_hw_group_error;
177static u64 *walltime_run; 184static u64 *walltime_run;
185static bool ru_display = false;
186static struct rusage ru_data;
187static unsigned int metric_only_len = METRIC_ONLY_LEN;
178 188
179struct perf_stat { 189struct perf_stat {
180 bool record; 190 bool record;
@@ -726,7 +736,7 @@ try_again:
726 break; 736 break;
727 } 737 }
728 } 738 }
729 waitpid(child_pid, &status, 0); 739 wait4(child_pid, &status, 0, &ru_data);
730 740
731 if (workload_exec_errno) { 741 if (workload_exec_errno) {
732 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 742 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -962,8 +972,6 @@ static void print_metric_csv(void *ctx,
962 fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit); 972 fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
963} 973}
964 974
965#define METRIC_ONLY_LEN 20
966
967/* Filter out some columns that don't work well in metrics only mode */ 975/* Filter out some columns that don't work well in metrics only mode */
968 976
969static bool valid_only_metric(const char *unit) 977static bool valid_only_metric(const char *unit)
@@ -994,22 +1002,20 @@ static void print_metric_only(void *ctx, const char *color, const char *fmt,
994{ 1002{
995 struct outstate *os = ctx; 1003 struct outstate *os = ctx;
996 FILE *out = os->fh; 1004 FILE *out = os->fh;
997 int n; 1005 char buf[1024], str[1024];
998 char buf[1024]; 1006 unsigned mlen = metric_only_len;
999 unsigned mlen = METRIC_ONLY_LEN;
1000 1007
1001 if (!valid_only_metric(unit)) 1008 if (!valid_only_metric(unit))
1002 return; 1009 return;
1003 unit = fixunit(buf, os->evsel, unit); 1010 unit = fixunit(buf, os->evsel, unit);
1004 if (color)
1005 n = color_fprintf(out, color, fmt, val);
1006 else
1007 n = fprintf(out, fmt, val);
1008 if (n > METRIC_ONLY_LEN)
1009 n = METRIC_ONLY_LEN;
1010 if (mlen < strlen(unit)) 1011 if (mlen < strlen(unit))
1011 mlen = strlen(unit) + 1; 1012 mlen = strlen(unit) + 1;
1012 fprintf(out, "%*s", mlen - n, ""); 1013
1014 if (color)
1015 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
1016
1017 color_snprintf(str, sizeof(str), color ?: "", fmt, val);
1018 fprintf(out, "%*s ", mlen, str);
1013} 1019}
1014 1020
1015static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, 1021static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
@@ -1049,7 +1055,7 @@ static void print_metric_header(void *ctx, const char *color __maybe_unused,
1049 if (csv_output) 1055 if (csv_output)
1050 fprintf(os->fh, "%s%s", unit, csv_sep); 1056 fprintf(os->fh, "%s%s", unit, csv_sep);
1051 else 1057 else
1052 fprintf(os->fh, "%-*s ", METRIC_ONLY_LEN, unit); 1058 fprintf(os->fh, "%*s ", metric_only_len, unit);
1053} 1059}
1054 1060
1055static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg) 1061static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
@@ -1699,9 +1705,12 @@ static void print_interval(char *prefix, struct timespec *ts)
1699 FILE *output = stat_config.output; 1705 FILE *output = stat_config.output;
1700 static int num_print_interval; 1706 static int num_print_interval;
1701 1707
1708 if (interval_clear)
1709 puts(CONSOLE_CLEAR);
1710
1702 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); 1711 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1703 1712
1704 if (num_print_interval == 0 && !csv_output) { 1713 if ((num_print_interval == 0 && !csv_output) || interval_clear) {
1705 switch (stat_config.aggr_mode) { 1714 switch (stat_config.aggr_mode) {
1706 case AGGR_SOCKET: 1715 case AGGR_SOCKET:
1707 fprintf(output, "# time socket cpus"); 1716 fprintf(output, "# time socket cpus");
@@ -1714,7 +1723,7 @@ static void print_interval(char *prefix, struct timespec *ts)
1714 fprintf(output, " counts %*s events\n", unit_width, "unit"); 1723 fprintf(output, " counts %*s events\n", unit_width, "unit");
1715 break; 1724 break;
1716 case AGGR_NONE: 1725 case AGGR_NONE:
1717 fprintf(output, "# time CPU"); 1726 fprintf(output, "# time CPU ");
1718 if (!metric_only) 1727 if (!metric_only)
1719 fprintf(output, " counts %*s events\n", unit_width, "unit"); 1728 fprintf(output, " counts %*s events\n", unit_width, "unit");
1720 break; 1729 break;
@@ -1733,7 +1742,7 @@ static void print_interval(char *prefix, struct timespec *ts)
1733 } 1742 }
1734 } 1743 }
1735 1744
1736 if (num_print_interval == 0 && metric_only) 1745 if ((num_print_interval == 0 && metric_only) || interval_clear)
1737 print_metric_headers(" ", true); 1746 print_metric_headers(" ", true);
1738 if (++num_print_interval == 25) 1747 if (++num_print_interval == 25)
1739 num_print_interval = 0; 1748 num_print_interval = 0;
@@ -1804,6 +1813,11 @@ static void print_table(FILE *output, int precision, double avg)
1804 fprintf(output, "\n%*s# Final result:\n", indent, ""); 1813 fprintf(output, "\n%*s# Final result:\n", indent, "");
1805} 1814}
1806 1815
1816static double timeval2double(struct timeval *t)
1817{
1818 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1819}
1820
1807static void print_footer(void) 1821static void print_footer(void)
1808{ 1822{
1809 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 1823 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
@@ -1815,6 +1829,15 @@ static void print_footer(void)
1815 1829
1816 if (run_count == 1) { 1830 if (run_count == 1) {
1817 fprintf(output, " %17.9f seconds time elapsed", avg); 1831 fprintf(output, " %17.9f seconds time elapsed", avg);
1832
1833 if (ru_display) {
1834 double ru_utime = timeval2double(&ru_data.ru_utime);
1835 double ru_stime = timeval2double(&ru_data.ru_stime);
1836
1837 fprintf(output, "\n\n");
1838 fprintf(output, " %17.9f seconds user\n", ru_utime);
1839 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1840 }
1818 } else { 1841 } else {
1819 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 1842 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1820 /* 1843 /*
@@ -2038,6 +2061,8 @@ static const struct option stat_options[] = {
2038 "(overhead is possible for values <= 100ms)"), 2061 "(overhead is possible for values <= 100ms)"),
2039 OPT_INTEGER(0, "interval-count", &stat_config.times, 2062 OPT_INTEGER(0, "interval-count", &stat_config.times,
2040 "print counts for fixed number of times"), 2063 "print counts for fixed number of times"),
2064 OPT_BOOLEAN(0, "interval-clear", &interval_clear,
2065 "clear screen in between new interval"),
2041 OPT_UINTEGER(0, "timeout", &stat_config.timeout, 2066 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
2042 "stop workload and print counts after a timeout period in ms (>= 10ms)"), 2067 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
2043 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 2068 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
@@ -2417,14 +2442,13 @@ static int add_default_attributes(void)
2417 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 2442 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
2418 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2443 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
2419}; 2444};
2445 struct parse_events_error errinfo;
2420 2446
2421 /* Set attrs if no event is selected and !null_run: */ 2447 /* Set attrs if no event is selected and !null_run: */
2422 if (null_run) 2448 if (null_run)
2423 return 0; 2449 return 0;
2424 2450
2425 if (transaction_run) { 2451 if (transaction_run) {
2426 struct parse_events_error errinfo;
2427
2428 if (pmu_have_event("cpu", "cycles-ct") && 2452 if (pmu_have_event("cpu", "cycles-ct") &&
2429 pmu_have_event("cpu", "el-start")) 2453 pmu_have_event("cpu", "el-start"))
2430 err = parse_events(evsel_list, transaction_attrs, 2454 err = parse_events(evsel_list, transaction_attrs,
@@ -2435,6 +2459,7 @@ static int add_default_attributes(void)
2435 &errinfo); 2459 &errinfo);
2436 if (err) { 2460 if (err) {
2437 fprintf(stderr, "Cannot set up transaction events\n"); 2461 fprintf(stderr, "Cannot set up transaction events\n");
2462 parse_events_print_error(&errinfo, transaction_attrs);
2438 return -1; 2463 return -1;
2439 } 2464 }
2440 return 0; 2465 return 0;
@@ -2460,10 +2485,11 @@ static int add_default_attributes(void)
2460 pmu_have_event("msr", "smi")) { 2485 pmu_have_event("msr", "smi")) {
2461 if (!force_metric_only) 2486 if (!force_metric_only)
2462 metric_only = true; 2487 metric_only = true;
2463 err = parse_events(evsel_list, smi_cost_attrs, NULL); 2488 err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
2464 } else { 2489 } else {
2465 fprintf(stderr, "To measure SMI cost, it needs " 2490 fprintf(stderr, "To measure SMI cost, it needs "
2466 "msr/aperf/, msr/smi/ and cpu/cycles/ support\n"); 2491 "msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
2492 parse_events_print_error(&errinfo, smi_cost_attrs);
2467 return -1; 2493 return -1;
2468 } 2494 }
2469 if (err) { 2495 if (err) {
@@ -2498,12 +2524,13 @@ static int add_default_attributes(void)
2498 if (topdown_attrs[0] && str) { 2524 if (topdown_attrs[0] && str) {
2499 if (warn) 2525 if (warn)
2500 arch_topdown_group_warn(); 2526 arch_topdown_group_warn();
2501 err = parse_events(evsel_list, str, NULL); 2527 err = parse_events(evsel_list, str, &errinfo);
2502 if (err) { 2528 if (err) {
2503 fprintf(stderr, 2529 fprintf(stderr,
2504 "Cannot set up top down events %s: %d\n", 2530 "Cannot set up top down events %s: %d\n",
2505 str, err); 2531 str, err);
2506 free(str); 2532 free(str);
2533 parse_events_print_error(&errinfo, str);
2507 return -1; 2534 return -1;
2508 } 2535 }
2509 } else { 2536 } else {
@@ -2950,6 +2977,13 @@ int cmd_stat(int argc, const char **argv)
2950 2977
2951 setup_system_wide(argc); 2978 setup_system_wide(argc);
2952 2979
2980 /*
2981 * Display user/system times only for single
2982 * run and when there's specified tracee.
2983 */
2984 if ((run_count == 1) && target__none(&target))
2985 ru_display = true;
2986
2953 if (run_count < 0) { 2987 if (run_count < 0) {
2954 pr_err("Run count must be a positive number\n"); 2988 pr_err("Run count must be a positive number\n");
2955 parse_options_usage(stat_usage, stat_options, "r", 1); 2989 parse_options_usage(stat_usage, stat_options, "r", 1);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7a349fcd3864..ffdc2769ff9f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -123,14 +123,9 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
123 } 123 }
124 124
125 notes = symbol__annotation(sym); 125 notes = symbol__annotation(sym);
126 if (notes->src != NULL) {
127 pthread_mutex_lock(&notes->lock);
128 goto out_assign;
129 }
130
131 pthread_mutex_lock(&notes->lock); 126 pthread_mutex_lock(&notes->lock);
132 127
133 if (symbol__alloc_hist(sym) < 0) { 128 if (!symbol__hists(sym, top->evlist->nr_entries)) {
134 pthread_mutex_unlock(&notes->lock); 129 pthread_mutex_unlock(&notes->lock);
135 pr_err("Not enough memory for annotating '%s' symbol!\n", 130 pr_err("Not enough memory for annotating '%s' symbol!\n",
136 sym->name); 131 sym->name);
@@ -138,9 +133,8 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
138 return err; 133 return err;
139 } 134 }
140 135
141 err = symbol__annotate(sym, map, evsel, 0, NULL); 136 err = symbol__annotate(sym, map, evsel, 0, &top->annotation_opts, NULL);
142 if (err == 0) { 137 if (err == 0) {
143out_assign:
144 top->sym_filter_entry = he; 138 top->sym_filter_entry = he;
145 } else { 139 } else {
146 char msg[BUFSIZ]; 140 char msg[BUFSIZ];
@@ -188,7 +182,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
188static void perf_top__record_precise_ip(struct perf_top *top, 182static void perf_top__record_precise_ip(struct perf_top *top,
189 struct hist_entry *he, 183 struct hist_entry *he,
190 struct perf_sample *sample, 184 struct perf_sample *sample,
191 int counter, u64 ip) 185 struct perf_evsel *evsel, u64 ip)
192{ 186{
193 struct annotation *notes; 187 struct annotation *notes;
194 struct symbol *sym = he->ms.sym; 188 struct symbol *sym = he->ms.sym;
@@ -204,7 +198,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
204 if (pthread_mutex_trylock(&notes->lock)) 198 if (pthread_mutex_trylock(&notes->lock))
205 return; 199 return;
206 200
207 err = hist_entry__inc_addr_samples(he, sample, counter, ip); 201 err = hist_entry__inc_addr_samples(he, sample, evsel, ip);
208 202
209 pthread_mutex_unlock(&notes->lock); 203 pthread_mutex_unlock(&notes->lock);
210 204
@@ -249,10 +243,9 @@ static void perf_top__show_details(struct perf_top *top)
249 goto out_unlock; 243 goto out_unlock;
250 244
251 printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name); 245 printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
252 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter); 246 printf(" Events Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt);
253 247
254 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, 248 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, &top->annotation_opts);
255 0, top->sym_pcnt_filter, top->print_entries, 4);
256 249
257 if (top->evlist->enabled) { 250 if (top->evlist->enabled) {
258 if (top->zero) 251 if (top->zero)
@@ -412,7 +405,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
412 405
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter); 406 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 407
415 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", top->sym_pcnt_filter); 408 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", top->annotation_opts.min_pcnt);
416 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 409 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
417 fprintf(stdout, "\t[S] stop annotation.\n"); 410 fprintf(stdout, "\t[S] stop annotation.\n");
418 411
@@ -515,7 +508,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
515 prompt_integer(&top->count_filter, "Enter display event count filter"); 508 prompt_integer(&top->count_filter, "Enter display event count filter");
516 break; 509 break;
517 case 'F': 510 case 'F':
518 prompt_percent(&top->sym_pcnt_filter, 511 prompt_percent(&top->annotation_opts.min_pcnt,
519 "Enter details display event filter (percent)"); 512 "Enter details display event filter (percent)");
520 break; 513 break;
521 case 'K': 514 case 'K':
@@ -613,7 +606,8 @@ static void *display_thread_tui(void *arg)
613 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, 606 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
614 top->min_percent, 607 top->min_percent,
615 &top->session->header.env, 608 &top->session->header.env,
616 !top->record_opts.overwrite); 609 !top->record_opts.overwrite,
610 &top->annotation_opts);
617 611
618 done = 1; 612 done = 1;
619 return NULL; 613 return NULL;
@@ -691,7 +685,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
691 struct perf_evsel *evsel = iter->evsel; 685 struct perf_evsel *evsel = iter->evsel;
692 686
693 if (perf_hpp_list.sym && single) 687 if (perf_hpp_list.sym && single)
694 perf_top__record_precise_ip(top, he, iter->sample, evsel->idx, al->addr); 688 perf_top__record_precise_ip(top, he, iter->sample, evsel, al->addr);
695 689
696 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 690 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
697 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY)); 691 !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY));
@@ -1083,8 +1077,9 @@ static int __cmd_top(struct perf_top *top)
1083 if (top->session == NULL) 1077 if (top->session == NULL)
1084 return -1; 1078 return -1;
1085 1079
1086 if (!objdump_path) { 1080 if (!top->annotation_opts.objdump_path) {
1087 ret = perf_env__lookup_objdump(&top->session->header.env); 1081 ret = perf_env__lookup_objdump(&top->session->header.env,
1082 &top->annotation_opts.objdump_path);
1088 if (ret) 1083 if (ret)
1089 goto out_delete; 1084 goto out_delete;
1090 } 1085 }
@@ -1265,7 +1260,7 @@ int cmd_top(int argc, const char **argv)
1265 .overwrite = 1, 1260 .overwrite = 1,
1266 }, 1261 },
1267 .max_stack = sysctl__max_stack(), 1262 .max_stack = sysctl__max_stack(),
1268 .sym_pcnt_filter = 5, 1263 .annotation_opts = annotation__default_options,
1269 .nr_threads_synthesize = UINT_MAX, 1264 .nr_threads_synthesize = UINT_MAX,
1270 }; 1265 };
1271 struct record_opts *opts = &top.record_opts; 1266 struct record_opts *opts = &top.record_opts;
@@ -1347,15 +1342,15 @@ int cmd_top(int argc, const char **argv)
1347 "only consider symbols in these comms"), 1342 "only consider symbols in these comms"),
1348 OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1343 OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1349 "only consider these symbols"), 1344 "only consider these symbols"),
1350 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 1345 OPT_BOOLEAN(0, "source", &top.annotation_opts.annotate_src,
1351 "Interleave source code with assembly code (default)"), 1346 "Interleave source code with assembly code (default)"),
1352 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1347 OPT_BOOLEAN(0, "asm-raw", &top.annotation_opts.show_asm_raw,
1353 "Display raw encoding of assembly instructions (default)"), 1348 "Display raw encoding of assembly instructions (default)"),
1354 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 1349 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1355 "Enable kernel symbol demangling"), 1350 "Enable kernel symbol demangling"),
1356 OPT_STRING(0, "objdump", &objdump_path, "path", 1351 OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path",
1357 "objdump binary to use for disassembly and annotations"), 1352 "objdump binary to use for disassembly and annotations"),
1358 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1353 OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style",
1359 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1354 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1360 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), 1355 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
1361 OPT_CALLBACK(0, "percent-limit", &top, "percent", 1356 OPT_CALLBACK(0, "percent-limit", &top, "percent",
@@ -1391,6 +1386,9 @@ int cmd_top(int argc, const char **argv)
1391 if (status < 0) 1386 if (status < 0)
1392 return status; 1387 return status;
1393 1388
1389 top.annotation_opts.min_pcnt = 5;
1390 top.annotation_opts.context = 4;
1391
1394 top.evlist = perf_evlist__new(); 1392 top.evlist = perf_evlist__new();
1395 if (top.evlist == NULL) 1393 if (top.evlist == NULL)
1396 return -ENOMEM; 1394 return -ENOMEM;
@@ -1468,8 +1466,6 @@ int cmd_top(int argc, const char **argv)
1468 goto out_delete_evlist; 1466 goto out_delete_evlist;
1469 } 1467 }
1470 1468
1471 symbol_conf.nr_events = top.evlist->nr_entries;
1472
1473 if (top.delay_secs < 1) 1469 if (top.delay_secs < 1)
1474 top.delay_secs = 1; 1470 top.delay_secs = 1;
1475 1471
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 560aed7da36a..6a748eca2edb 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2491,7 +2491,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2491 * to override an explicitely set --max-stack global setting. 2491 * to override an explicitely set --max-stack global setting.
2492 */ 2492 */
2493 evlist__for_each_entry(evlist, evsel) { 2493 evlist__for_each_entry(evlist, evsel) {
2494 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) && 2494 if (evsel__has_callchain(evsel) &&
2495 evsel->attr.sample_max_stack == 0) 2495 evsel->attr.sample_max_stack == 0)
2496 evsel->attr.sample_max_stack = trace->max_stack; 2496 evsel->attr.sample_max_stack = trace->max_stack;
2497 } 2497 }
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 51c81509a315..a11cb006f968 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -12,7 +12,6 @@
12#include "util/env.h" 12#include "util/env.h"
13#include <subcmd/exec-cmd.h> 13#include <subcmd/exec-cmd.h>
14#include "util/config.h" 14#include "util/config.h"
15#include "util/quote.h"
16#include <subcmd/run-command.h> 15#include <subcmd/run-command.h>
17#include "util/parse-events.h" 16#include "util/parse-events.h"
18#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
diff --git a/tools/perf/scripts/python/bin/powerpc-hcalls-record b/tools/perf/scripts/python/bin/powerpc-hcalls-record
new file mode 100644
index 000000000000..b7402aa9147d
--- /dev/null
+++ b/tools/perf/scripts/python/bin/powerpc-hcalls-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e "{powerpc:hcall_entry,powerpc:hcall_exit}" $@
diff --git a/tools/perf/scripts/python/bin/powerpc-hcalls-report b/tools/perf/scripts/python/bin/powerpc-hcalls-report
new file mode 100644
index 000000000000..dd32ad7465f6
--- /dev/null
+++ b/tools/perf/scripts/python/bin/powerpc-hcalls-report
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/powerpc-hcalls.py
diff --git a/tools/perf/scripts/python/powerpc-hcalls.py b/tools/perf/scripts/python/powerpc-hcalls.py
new file mode 100644
index 000000000000..00e0e7476e55
--- /dev/null
+++ b/tools/perf/scripts/python/powerpc-hcalls.py
@@ -0,0 +1,200 @@
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (C) 2018 Ravi Bangoria, IBM Corporation
4#
5# Hypervisor call statisics
6
7import os
8import sys
9
10sys.path.append(os.environ['PERF_EXEC_PATH'] + \
11 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
12
13from perf_trace_context import *
14from Core import *
15from Util import *
16
17# output: {
18# opcode: {
19# 'min': minimum time nsec
20# 'max': maximum time nsec
21# 'time': average time nsec
22# 'cnt': counter
23# } ...
24# }
25output = {}
26
27# d_enter: {
28# cpu: {
29# opcode: nsec
30# } ...
31# }
32d_enter = {}
33
34hcall_table = {
35 4: 'H_REMOVE',
36 8: 'H_ENTER',
37 12: 'H_READ',
38 16: 'H_CLEAR_MOD',
39 20: 'H_CLEAR_REF',
40 24: 'H_PROTECT',
41 28: 'H_GET_TCE',
42 32: 'H_PUT_TCE',
43 36: 'H_SET_SPRG0',
44 40: 'H_SET_DABR',
45 44: 'H_PAGE_INIT',
46 48: 'H_SET_ASR',
47 52: 'H_ASR_ON',
48 56: 'H_ASR_OFF',
49 60: 'H_LOGICAL_CI_LOAD',
50 64: 'H_LOGICAL_CI_STORE',
51 68: 'H_LOGICAL_CACHE_LOAD',
52 72: 'H_LOGICAL_CACHE_STORE',
53 76: 'H_LOGICAL_ICBI',
54 80: 'H_LOGICAL_DCBF',
55 84: 'H_GET_TERM_CHAR',
56 88: 'H_PUT_TERM_CHAR',
57 92: 'H_REAL_TO_LOGICAL',
58 96: 'H_HYPERVISOR_DATA',
59 100: 'H_EOI',
60 104: 'H_CPPR',
61 108: 'H_IPI',
62 112: 'H_IPOLL',
63 116: 'H_XIRR',
64 120: 'H_MIGRATE_DMA',
65 124: 'H_PERFMON',
66 220: 'H_REGISTER_VPA',
67 224: 'H_CEDE',
68 228: 'H_CONFER',
69 232: 'H_PROD',
70 236: 'H_GET_PPP',
71 240: 'H_SET_PPP',
72 244: 'H_PURR',
73 248: 'H_PIC',
74 252: 'H_REG_CRQ',
75 256: 'H_FREE_CRQ',
76 260: 'H_VIO_SIGNAL',
77 264: 'H_SEND_CRQ',
78 272: 'H_COPY_RDMA',
79 276: 'H_REGISTER_LOGICAL_LAN',
80 280: 'H_FREE_LOGICAL_LAN',
81 284: 'H_ADD_LOGICAL_LAN_BUFFER',
82 288: 'H_SEND_LOGICAL_LAN',
83 292: 'H_BULK_REMOVE',
84 304: 'H_MULTICAST_CTRL',
85 308: 'H_SET_XDABR',
86 312: 'H_STUFF_TCE',
87 316: 'H_PUT_TCE_INDIRECT',
88 332: 'H_CHANGE_LOGICAL_LAN_MAC',
89 336: 'H_VTERM_PARTNER_INFO',
90 340: 'H_REGISTER_VTERM',
91 344: 'H_FREE_VTERM',
92 348: 'H_RESET_EVENTS',
93 352: 'H_ALLOC_RESOURCE',
94 356: 'H_FREE_RESOURCE',
95 360: 'H_MODIFY_QP',
96 364: 'H_QUERY_QP',
97 368: 'H_REREGISTER_PMR',
98 372: 'H_REGISTER_SMR',
99 376: 'H_QUERY_MR',
100 380: 'H_QUERY_MW',
101 384: 'H_QUERY_HCA',
102 388: 'H_QUERY_PORT',
103 392: 'H_MODIFY_PORT',
104 396: 'H_DEFINE_AQP1',
105 400: 'H_GET_TRACE_BUFFER',
106 404: 'H_DEFINE_AQP0',
107 408: 'H_RESIZE_MR',
108 412: 'H_ATTACH_MCQP',
109 416: 'H_DETACH_MCQP',
110 420: 'H_CREATE_RPT',
111 424: 'H_REMOVE_RPT',
112 428: 'H_REGISTER_RPAGES',
113 432: 'H_DISABLE_AND_GETC',
114 436: 'H_ERROR_DATA',
115 440: 'H_GET_HCA_INFO',
116 444: 'H_GET_PERF_COUNT',
117 448: 'H_MANAGE_TRACE',
118 468: 'H_FREE_LOGICAL_LAN_BUFFER',
119 472: 'H_POLL_PENDING',
120 484: 'H_QUERY_INT_STATE',
121 580: 'H_ILLAN_ATTRIBUTES',
122 592: 'H_MODIFY_HEA_QP',
123 596: 'H_QUERY_HEA_QP',
124 600: 'H_QUERY_HEA',
125 604: 'H_QUERY_HEA_PORT',
126 608: 'H_MODIFY_HEA_PORT',
127 612: 'H_REG_BCMC',
128 616: 'H_DEREG_BCMC',
129 620: 'H_REGISTER_HEA_RPAGES',
130 624: 'H_DISABLE_AND_GET_HEA',
131 628: 'H_GET_HEA_INFO',
132 632: 'H_ALLOC_HEA_RESOURCE',
133 644: 'H_ADD_CONN',
134 648: 'H_DEL_CONN',
135 664: 'H_JOIN',
136 676: 'H_VASI_STATE',
137 688: 'H_ENABLE_CRQ',
138 696: 'H_GET_EM_PARMS',
139 720: 'H_SET_MPP',
140 724: 'H_GET_MPP',
141 748: 'H_HOME_NODE_ASSOCIATIVITY',
142 756: 'H_BEST_ENERGY',
143 764: 'H_XIRR_X',
144 768: 'H_RANDOM',
145 772: 'H_COP',
146 788: 'H_GET_MPP_X',
147 796: 'H_SET_MODE',
148 61440: 'H_RTAS',
149}
150
151def hcall_table_lookup(opcode):
152 if (hcall_table.has_key(opcode)):
153 return hcall_table[opcode]
154 else:
155 return opcode
156
157print_ptrn = '%-28s%10s%10s%10s%10s'
158
159def trace_end():
160 print print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)')
161 print '-' * 68
162 for opcode in output:
163 h_name = hcall_table_lookup(opcode)
164 time = output[opcode]['time']
165 cnt = output[opcode]['cnt']
166 min_t = output[opcode]['min']
167 max_t = output[opcode]['max']
168
169 print print_ptrn % (h_name, cnt, min_t, max_t, time/cnt)
170
171def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
172 opcode, retval):
173 if (d_enter.has_key(cpu) and d_enter[cpu].has_key(opcode)):
174 diff = nsecs(sec, nsec) - d_enter[cpu][opcode]
175
176 if (output.has_key(opcode)):
177 output[opcode]['time'] += diff
178 output[opcode]['cnt'] += 1
179 if (output[opcode]['min'] > diff):
180 output[opcode]['min'] = diff
181 if (output[opcode]['max'] < diff):
182 output[opcode]['max'] = diff
183 else:
184 output[opcode] = {
185 'time': diff,
186 'cnt': 1,
187 'min': diff,
188 'max': diff,
189 }
190
191 del d_enter[cpu][opcode]
192# else:
193# print "Can't find matching hcall_enter event. Ignoring sample"
194
195def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm,
196 callchain, opcode):
197 if (d_enter.has_key(cpu)):
198 d_enter[cpu][opcode] = nsecs(sec, nsec)
199 else:
200 d_enter[cpu] = {opcode: nsecs(sec, nsec)}
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index afa4ce21ba7c..4892bd2dc33e 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -560,6 +560,7 @@ static int do_test_code_reading(bool try_kcore)
560 pid = getpid(); 560 pid = getpid();
561 561
562 machine = machine__new_host(); 562 machine = machine__new_host();
563 machine->env = &perf_env;
563 564
564 ret = machine__create_kernel_maps(machine); 565 ret = machine__create_kernel_maps(machine);
565 if (ret < 0) { 566 if (ret < 0) {
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 8e57d46109de..148dd31cc201 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -127,6 +127,22 @@ int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_un
127 M("[vdso]", PERF_RECORD_MISC_KERNEL, false); 127 M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
128 M("[vdso]", PERF_RECORD_MISC_USER, false); 128 M("[vdso]", PERF_RECORD_MISC_USER, false);
129 129
130 T("[vdso32]", true , true , false, false, "[vdso32]", NULL);
131 T("[vdso32]", false , true , false, false, NULL , NULL);
132 T("[vdso32]", true , false , false, false, "[vdso32]", NULL);
133 T("[vdso32]", false , false , false, false, NULL , NULL);
134 M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
135 M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
136 M("[vdso32]", PERF_RECORD_MISC_USER, false);
137
138 T("[vdsox32]", true , true , false, false, "[vdsox32]", NULL);
139 T("[vdsox32]", false , true , false, false, NULL , NULL);
140 T("[vdsox32]", true , false , false, false, "[vdsox32]", NULL);
141 T("[vdsox32]", false , false , false, false, NULL , NULL);
142 M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
143 M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
144 M("[vdsox32]", PERF_RECORD_MISC_USER, false);
145
130 /* path alloc_name alloc_ext kmod comp name ext */ 146 /* path alloc_name alloc_ext kmod comp name ext */
131 T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL); 147 T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL);
132 T("[vsyscall]", false , true , false, false, NULL , NULL); 148 T("[vsyscall]", false , true , false, false, NULL , NULL);
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index b9ebe15afb13..61211918bfba 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -499,7 +499,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlis
499 * while this test executes only parse events method. 499 * while this test executes only parse events method.
500 */ 500 */
501 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); 501 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
502 TEST_ASSERT_VAL("wrong callgraph", !(PERF_SAMPLE_CALLCHAIN & evsel->attr.sample_type)); 502 TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel));
503 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type)); 503 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
504 504
505 /* cpu/config=2,call-graph=no,time=0,period=2000/ */ 505 /* cpu/config=2,call-graph=no,time=0,period=2000/ */
@@ -512,7 +512,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlis
512 * while this test executes only parse events method. 512 * while this test executes only parse events method.
513 */ 513 */
514 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period); 514 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
515 TEST_ASSERT_VAL("wrong callgraph", !(PERF_SAMPLE_CALLCHAIN & evsel->attr.sample_type)); 515 TEST_ASSERT_VAL("wrong callgraph", !evsel__has_callchain(evsel));
516 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type)); 516 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
517 517
518 return 0; 518 return 0;
@@ -1309,6 +1309,11 @@ static int test__checkevent_config_cache(struct perf_evlist *evlist)
1309 return 0; 1309 return 0;
1310} 1310}
1311 1311
1312static bool test__intel_pt_valid(void)
1313{
1314 return !!perf_pmu__find("intel_pt");
1315}
1316
1312static int test__intel_pt(struct perf_evlist *evlist) 1317static int test__intel_pt(struct perf_evlist *evlist)
1313{ 1318{
1314 struct perf_evsel *evsel = perf_evlist__first(evlist); 1319 struct perf_evsel *evsel = perf_evlist__first(evlist);
@@ -1375,6 +1380,7 @@ struct evlist_test {
1375 const char *name; 1380 const char *name;
1376 __u32 type; 1381 __u32 type;
1377 const int id; 1382 const int id;
1383 bool (*valid)(void);
1378 int (*check)(struct perf_evlist *evlist); 1384 int (*check)(struct perf_evlist *evlist);
1379}; 1385};
1380 1386
@@ -1648,6 +1654,7 @@ static struct evlist_test test__events[] = {
1648 }, 1654 },
1649 { 1655 {
1650 .name = "intel_pt//u", 1656 .name = "intel_pt//u",
1657 .valid = test__intel_pt_valid,
1651 .check = test__intel_pt, 1658 .check = test__intel_pt,
1652 .id = 52, 1659 .id = 52,
1653 }, 1660 },
@@ -1686,17 +1693,24 @@ static struct terms_test test__terms[] = {
1686 1693
1687static int test_event(struct evlist_test *e) 1694static int test_event(struct evlist_test *e)
1688{ 1695{
1696 struct parse_events_error err = { .idx = 0, };
1689 struct perf_evlist *evlist; 1697 struct perf_evlist *evlist;
1690 int ret; 1698 int ret;
1691 1699
1700 if (e->valid && !e->valid()) {
1701 pr_debug("... SKIP");
1702 return 0;
1703 }
1704
1692 evlist = perf_evlist__new(); 1705 evlist = perf_evlist__new();
1693 if (evlist == NULL) 1706 if (evlist == NULL)
1694 return -ENOMEM; 1707 return -ENOMEM;
1695 1708
1696 ret = parse_events(evlist, e->name, NULL); 1709 ret = parse_events(evlist, e->name, &err);
1697 if (ret) { 1710 if (ret) {
1698 pr_debug("failed to parse event '%s', err %d\n", 1711 pr_debug("failed to parse event '%s', err %d, str '%s'\n",
1699 e->name, ret); 1712 e->name, ret, err.str);
1713 parse_events_print_error(&err, e->name);
1700 } else { 1714 } else {
1701 ret = e->check(evlist); 1715 ret = e->check(evlist);
1702 } 1716 }
@@ -1714,10 +1728,11 @@ static int test_events(struct evlist_test *events, unsigned cnt)
1714 for (i = 0; i < cnt; i++) { 1728 for (i = 0; i < cnt; i++) {
1715 struct evlist_test *e = &events[i]; 1729 struct evlist_test *e = &events[i];
1716 1730
1717 pr_debug("running test %d '%s'\n", e->id, e->name); 1731 pr_debug("running test %d '%s'", e->id, e->name);
1718 ret1 = test_event(e); 1732 ret1 = test_event(e);
1719 if (ret1) 1733 if (ret1)
1720 ret2 = ret1; 1734 ret2 = ret1;
1735 pr_debug("\n");
1721 } 1736 }
1722 1737
1723 return ret2; 1738 return ret2;
@@ -1799,7 +1814,7 @@ static int test_pmu_events(void)
1799 } 1814 }
1800 1815
1801 while (!ret && (ent = readdir(dir))) { 1816 while (!ret && (ent = readdir(dir))) {
1802 struct evlist_test e; 1817 struct evlist_test e = { .id = 0, };
1803 char name[2 * NAME_MAX + 1 + 12 + 3]; 1818 char name[2 * NAME_MAX + 1 + 12 + 3];
1804 1819
1805 /* Names containing . are special and cannot be used directly */ 1820 /* Names containing . are special and cannot be used directly */
diff --git a/tools/perf/tests/python-use.c b/tools/perf/tests/python-use.c
index 5d2df65ada6a..40ab72149ce1 100644
--- a/tools/perf/tests/python-use.c
+++ b/tools/perf/tests/python-use.c
@@ -7,8 +7,7 @@
7#include <stdlib.h> 7#include <stdlib.h>
8#include <linux/compiler.h> 8#include <linux/compiler.h>
9#include "tests.h" 9#include "tests.h"
10 10#include "util/debug.h"
11extern int verbose;
12 11
13int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unused) 12int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unused)
14{ 13{
diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 650b208f700f..263057039693 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -11,7 +11,7 @@
11. $(dirname $0)/lib/probe.sh 11. $(dirname $0)/lib/probe.sh
12 12
13libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g') 13libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g')
14nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254 14nm -Dg $libc 2>/dev/null | fgrep -q inet_pton || exit 254
15 15
16trace_libc_inet_pton_backtrace() { 16trace_libc_inet_pton_backtrace() {
17 idx=0 17 idx=0
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 40e30a26b23c..9497d02f69e6 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -45,6 +45,7 @@ static int session_write_header(char *path)
45 45
46 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 46 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
47 perf_header__set_feat(&session->header, HEADER_NRCPUS); 47 perf_header__set_feat(&session->header, HEADER_NRCPUS);
48 perf_header__set_feat(&session->header, HEADER_ARCH);
48 49
49 session->header.data_size += DATA_SIZE; 50 session->header.data_size += DATA_SIZE;
50 51
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 8be40fa903aa..3b4f1c10ff57 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -29,6 +29,7 @@ struct annotate_browser {
29 struct rb_node *curr_hot; 29 struct rb_node *curr_hot;
30 struct annotation_line *selection; 30 struct annotation_line *selection;
31 struct arch *arch; 31 struct arch *arch;
32 struct annotation_options *opts;
32 bool searching_backwards; 33 bool searching_backwards;
33 char search_bf[128]; 34 char search_bf[128];
34}; 35};
@@ -410,7 +411,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
410 notes = symbol__annotation(dl->ops.target.sym); 411 notes = symbol__annotation(dl->ops.target.sym);
411 pthread_mutex_lock(&notes->lock); 412 pthread_mutex_lock(&notes->lock);
412 413
413 if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) { 414 if (!symbol__hists(dl->ops.target.sym, evsel->evlist->nr_entries)) {
414 pthread_mutex_unlock(&notes->lock); 415 pthread_mutex_unlock(&notes->lock);
415 ui__warning("Not enough memory for annotating '%s' symbol!\n", 416 ui__warning("Not enough memory for annotating '%s' symbol!\n",
416 dl->ops.target.sym->name); 417 dl->ops.target.sym->name);
@@ -418,7 +419,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
418 } 419 }
419 420
420 pthread_mutex_unlock(&notes->lock); 421 pthread_mutex_unlock(&notes->lock);
421 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt); 422 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
422 sym_title(ms->sym, ms->map, title, sizeof(title)); 423 sym_title(ms->sym, ms->map, title, sizeof(title));
423 ui_browser__show_title(&browser->b, title); 424 ui_browser__show_title(&browser->b, title);
424 return true; 425 return true;
@@ -817,24 +818,27 @@ out:
817} 818}
818 819
819int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 820int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
820 struct hist_browser_timer *hbt) 821 struct hist_browser_timer *hbt,
822 struct annotation_options *opts)
821{ 823{
822 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 824 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt, opts);
823} 825}
824 826
825int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 827int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
826 struct hist_browser_timer *hbt) 828 struct hist_browser_timer *hbt,
829 struct annotation_options *opts)
827{ 830{
828 /* reset abort key so that it can get Ctrl-C as a key */ 831 /* reset abort key so that it can get Ctrl-C as a key */
829 SLang_reset_tty(); 832 SLang_reset_tty();
830 SLang_init_tty(0, 0, 0); 833 SLang_init_tty(0, 0, 0);
831 834
832 return map_symbol__tui_annotate(&he->ms, evsel, hbt); 835 return map_symbol__tui_annotate(&he->ms, evsel, hbt, opts);
833} 836}
834 837
835int symbol__tui_annotate(struct symbol *sym, struct map *map, 838int symbol__tui_annotate(struct symbol *sym, struct map *map,
836 struct perf_evsel *evsel, 839 struct perf_evsel *evsel,
837 struct hist_browser_timer *hbt) 840 struct hist_browser_timer *hbt,
841 struct annotation_options *opts)
838{ 842{
839 struct annotation *notes = symbol__annotation(sym); 843 struct annotation *notes = symbol__annotation(sym);
840 struct map_symbol ms = { 844 struct map_symbol ms = {
@@ -851,6 +855,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
851 .priv = &ms, 855 .priv = &ms,
852 .use_navkeypressed = true, 856 .use_navkeypressed = true,
853 }, 857 },
858 .opts = opts,
854 }; 859 };
855 int ret = -1, err; 860 int ret = -1, err;
856 861
@@ -860,7 +865,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
860 if (map->dso->annotate_warned) 865 if (map->dso->annotate_warned)
861 return -1; 866 return -1;
862 867
863 err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch); 868 err = symbol__annotate2(sym, map, evsel, opts, &browser.arch);
864 if (err) { 869 if (err) {
865 char msg[BUFSIZ]; 870 char msg[BUFSIZ];
866 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 871 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e5f247247daa..a96f62ca984a 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1231,6 +1231,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1231 int width = browser->b.width; 1231 int width = browser->b.width;
1232 char folded_sign = ' '; 1232 char folded_sign = ' ';
1233 bool current_entry = ui_browser__is_current_entry(&browser->b, row); 1233 bool current_entry = ui_browser__is_current_entry(&browser->b, row);
1234 bool use_callchain = hist_entry__has_callchains(entry) && symbol_conf.use_callchain;
1234 off_t row_offset = entry->row_offset; 1235 off_t row_offset = entry->row_offset;
1235 bool first = true; 1236 bool first = true;
1236 struct perf_hpp_fmt *fmt; 1237 struct perf_hpp_fmt *fmt;
@@ -1240,7 +1241,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1240 browser->selection = &entry->ms; 1241 browser->selection = &entry->ms;
1241 } 1242 }
1242 1243
1243 if (symbol_conf.use_callchain) { 1244 if (use_callchain) {
1244 hist_entry__init_have_children(entry); 1245 hist_entry__init_have_children(entry);
1245 folded_sign = hist_entry__folded(entry); 1246 folded_sign = hist_entry__folded(entry);
1246 } 1247 }
@@ -1276,7 +1277,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1276 } 1277 }
1277 1278
1278 if (first) { 1279 if (first) {
1279 if (symbol_conf.use_callchain) { 1280 if (use_callchain) {
1280 ui_browser__printf(&browser->b, "%c ", folded_sign); 1281 ui_browser__printf(&browser->b, "%c ", folded_sign);
1281 width -= 2; 1282 width -= 2;
1282 } 1283 }
@@ -1583,7 +1584,7 @@ hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf,
1583 int column = 0; 1584 int column = 0;
1584 int span = 0; 1585 int span = 0;
1585 1586
1586 if (symbol_conf.use_callchain) { 1587 if (hists__has_callchains(hists) && symbol_conf.use_callchain) {
1587 ret = scnprintf(buf, size, " "); 1588 ret = scnprintf(buf, size, " ");
1588 if (advance_hpp_check(&dummy_hpp, ret)) 1589 if (advance_hpp_check(&dummy_hpp, ret))
1589 return ret; 1590 return ret;
@@ -1987,7 +1988,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1987 bool first = true; 1988 bool first = true;
1988 int ret; 1989 int ret;
1989 1990
1990 if (symbol_conf.use_callchain) { 1991 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
1991 folded_sign = hist_entry__folded(he); 1992 folded_sign = hist_entry__folded(he);
1992 printed += fprintf(fp, "%c ", folded_sign); 1993 printed += fprintf(fp, "%c ", folded_sign);
1993 } 1994 }
@@ -2175,7 +2176,8 @@ struct hist_browser *hist_browser__new(struct hists *hists)
2175static struct hist_browser * 2176static struct hist_browser *
2176perf_evsel_browser__new(struct perf_evsel *evsel, 2177perf_evsel_browser__new(struct perf_evsel *evsel,
2177 struct hist_browser_timer *hbt, 2178 struct hist_browser_timer *hbt,
2178 struct perf_env *env) 2179 struct perf_env *env,
2180 struct annotation_options *annotation_opts)
2179{ 2181{
2180 struct hist_browser *browser = hist_browser__new(evsel__hists(evsel)); 2182 struct hist_browser *browser = hist_browser__new(evsel__hists(evsel));
2181 2183
@@ -2183,6 +2185,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel,
2183 browser->hbt = hbt; 2185 browser->hbt = hbt;
2184 browser->env = env; 2186 browser->env = env;
2185 browser->title = hists_browser__scnprintf_title; 2187 browser->title = hists_browser__scnprintf_title;
2188 browser->annotation_opts = annotation_opts;
2186 } 2189 }
2187 return browser; 2190 return browser;
2188} 2191}
@@ -2336,7 +2339,8 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)
2336 struct hist_entry *he; 2339 struct hist_entry *he;
2337 int err; 2340 int err;
2338 2341
2339 if (!objdump_path && perf_env__lookup_objdump(browser->env)) 2342 if (!browser->annotation_opts->objdump_path &&
2343 perf_env__lookup_objdump(browser->env, &browser->annotation_opts->objdump_path))
2340 return 0; 2344 return 0;
2341 2345
2342 notes = symbol__annotation(act->ms.sym); 2346 notes = symbol__annotation(act->ms.sym);
@@ -2344,7 +2348,8 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)
2344 return 0; 2348 return 0;
2345 2349
2346 evsel = hists_to_evsel(browser->hists); 2350 evsel = hists_to_evsel(browser->hists);
2347 err = map_symbol__tui_annotate(&act->ms, evsel, browser->hbt); 2351 err = map_symbol__tui_annotate(&act->ms, evsel, browser->hbt,
2352 browser->annotation_opts);
2348 he = hist_browser__selected_entry(browser); 2353 he = hist_browser__selected_entry(browser);
2349 /* 2354 /*
2350 * offer option to annotate the other branch source or target 2355 * offer option to annotate the other branch source or target
@@ -2667,7 +2672,7 @@ static void hist_browser__update_percent_limit(struct hist_browser *hb,
2667 he->nr_rows = 0; 2672 he->nr_rows = 0;
2668 } 2673 }
2669 2674
2670 if (!he->leaf || !symbol_conf.use_callchain) 2675 if (!he->leaf || !hist_entry__has_callchains(he) || !symbol_conf.use_callchain)
2671 goto next; 2676 goto next;
2672 2677
2673 if (callchain_param.mode == CHAIN_GRAPH_REL) { 2678 if (callchain_param.mode == CHAIN_GRAPH_REL) {
@@ -2697,10 +2702,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2697 struct hist_browser_timer *hbt, 2702 struct hist_browser_timer *hbt,
2698 float min_pcnt, 2703 float min_pcnt,
2699 struct perf_env *env, 2704 struct perf_env *env,
2700 bool warn_lost_event) 2705 bool warn_lost_event,
2706 struct annotation_options *annotation_opts)
2701{ 2707{
2702 struct hists *hists = evsel__hists(evsel); 2708 struct hists *hists = evsel__hists(evsel);
2703 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env); 2709 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env, annotation_opts);
2704 struct branch_info *bi; 2710 struct branch_info *bi;
2705#define MAX_OPTIONS 16 2711#define MAX_OPTIONS 16
2706 char *options[MAX_OPTIONS]; 2712 char *options[MAX_OPTIONS];
@@ -3062,6 +3068,7 @@ out:
3062struct perf_evsel_menu { 3068struct perf_evsel_menu {
3063 struct ui_browser b; 3069 struct ui_browser b;
3064 struct perf_evsel *selection; 3070 struct perf_evsel *selection;
3071 struct annotation_options *annotation_opts;
3065 bool lost_events, lost_events_warned; 3072 bool lost_events, lost_events_warned;
3066 float min_pcnt; 3073 float min_pcnt;
3067 struct perf_env *env; 3074 struct perf_env *env;
@@ -3163,7 +3170,8 @@ browse_hists:
3163 true, hbt, 3170 true, hbt,
3164 menu->min_pcnt, 3171 menu->min_pcnt,
3165 menu->env, 3172 menu->env,
3166 warn_lost_event); 3173 warn_lost_event,
3174 menu->annotation_opts);
3167 ui_browser__show_title(&menu->b, title); 3175 ui_browser__show_title(&menu->b, title);
3168 switch (key) { 3176 switch (key) {
3169 case K_TAB: 3177 case K_TAB:
@@ -3222,7 +3230,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3222 struct hist_browser_timer *hbt, 3230 struct hist_browser_timer *hbt,
3223 float min_pcnt, 3231 float min_pcnt,
3224 struct perf_env *env, 3232 struct perf_env *env,
3225 bool warn_lost_event) 3233 bool warn_lost_event,
3234 struct annotation_options *annotation_opts)
3226{ 3235{
3227 struct perf_evsel *pos; 3236 struct perf_evsel *pos;
3228 struct perf_evsel_menu menu = { 3237 struct perf_evsel_menu menu = {
@@ -3237,6 +3246,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3237 }, 3246 },
3238 .min_pcnt = min_pcnt, 3247 .min_pcnt = min_pcnt,
3239 .env = env, 3248 .env = env,
3249 .annotation_opts = annotation_opts,
3240 }; 3250 };
3241 3251
3242 ui_helpline__push("Press ESC to exit"); 3252 ui_helpline__push("Press ESC to exit");
@@ -3257,7 +3267,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
3257 struct hist_browser_timer *hbt, 3267 struct hist_browser_timer *hbt,
3258 float min_pcnt, 3268 float min_pcnt,
3259 struct perf_env *env, 3269 struct perf_env *env,
3260 bool warn_lost_event) 3270 bool warn_lost_event,
3271 struct annotation_options *annotation_opts)
3261{ 3272{
3262 int nr_entries = evlist->nr_entries; 3273 int nr_entries = evlist->nr_entries;
3263 3274
@@ -3267,7 +3278,8 @@ single_entry:
3267 3278
3268 return perf_evsel__hists_browse(first, nr_entries, help, 3279 return perf_evsel__hists_browse(first, nr_entries, help,
3269 false, hbt, min_pcnt, 3280 false, hbt, min_pcnt,
3270 env, warn_lost_event); 3281 env, warn_lost_event,
3282 annotation_opts);
3271 } 3283 }
3272 3284
3273 if (symbol_conf.event_group) { 3285 if (symbol_conf.event_group) {
@@ -3285,5 +3297,6 @@ single_entry:
3285 3297
3286 return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, 3298 return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
3287 hbt, min_pcnt, env, 3299 hbt, min_pcnt, env,
3288 warn_lost_event); 3300 warn_lost_event,
3301 annotation_opts);
3289} 3302}
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h
index 9428bee076f2..91d3e18b50aa 100644
--- a/tools/perf/ui/browsers/hists.h
+++ b/tools/perf/ui/browsers/hists.h
@@ -4,6 +4,8 @@
4 4
5#include "ui/browser.h" 5#include "ui/browser.h"
6 6
7struct annotation_options;
8
7struct hist_browser { 9struct hist_browser {
8 struct ui_browser b; 10 struct ui_browser b;
9 struct hists *hists; 11 struct hists *hists;
@@ -12,6 +14,7 @@ struct hist_browser {
12 struct hist_browser_timer *hbt; 14 struct hist_browser_timer *hbt;
13 struct pstack *pstack; 15 struct pstack *pstack;
14 struct perf_env *env; 16 struct perf_env *env;
17 struct annotation_options *annotation_opts;
15 int print_seq; 18 int print_seq;
16 bool show_dso; 19 bool show_dso;
17 bool show_headers; 20 bool show_headers;
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index aeeaf15029f0..48428c9acd89 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -169,7 +169,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
169 if (map->dso->annotate_warned) 169 if (map->dso->annotate_warned)
170 return -1; 170 return -1;
171 171
172 err = symbol__annotate(sym, map, evsel, 0, NULL); 172 err = symbol__annotate(sym, map, evsel, 0, &annotation__default_options, NULL);
173 if (err) { 173 if (err) {
174 char msg[BUFSIZ]; 174 char msg[BUFSIZ];
175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 175 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 24e1ec201ffd..4ab663ec3e5e 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -382,7 +382,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
382 gtk_tree_store_set(store, &iter, col_idx++, s, -1); 382 gtk_tree_store_set(store, &iter, col_idx++, s, -1);
383 } 383 }
384 384
385 if (symbol_conf.use_callchain && hists__has(hists, sym)) { 385 if (hist_entry__has_callchains(h) &&
386 symbol_conf.use_callchain && hists__has(hists, sym)) {
386 if (callchain_param.mode == CHAIN_GRAPH_REL) 387 if (callchain_param.mode == CHAIN_GRAPH_REL)
387 total = symbol_conf.cumulate_callchain ? 388 total = symbol_conf.cumulate_callchain ?
388 h->stat_acc->period : h->stat.period; 389 h->stat_acc->period : h->stat.period;
@@ -479,7 +480,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
479 } 480 }
480 } 481 }
481 482
482 if (symbol_conf.use_callchain && he->leaf) { 483 if (he->leaf && hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
483 if (callchain_param.mode == CHAIN_GRAPH_REL) 484 if (callchain_param.mode == CHAIN_GRAPH_REL)
484 total = symbol_conf.cumulate_callchain ? 485 total = symbol_conf.cumulate_callchain ?
485 he->stat_acc->period : he->stat.period; 486 he->stat_acc->period : he->stat.period;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 706f6f1e9c7d..fe3dfaa64a91 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -207,7 +207,7 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
207 if (ret) 207 if (ret)
208 return ret; 208 return ret;
209 209
210 if (a->thread != b->thread || !symbol_conf.use_callchain) 210 if (a->thread != b->thread || !hist_entry__has_callchains(a) || !symbol_conf.use_callchain)
211 return 0; 211 return 0;
212 212
213 ret = b->callchain->max_depth - a->callchain->max_depth; 213 ret = b->callchain->max_depth - a->callchain->max_depth;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index c1eb476da91b..69b7a28f7a1c 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -516,7 +516,7 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
516 } 516 }
517 printed += putc('\n', fp); 517 printed += putc('\n', fp);
518 518
519 if (symbol_conf.use_callchain && he->leaf) { 519 if (he->leaf && hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
520 u64 total = hists__total_period(hists); 520 u64 total = hists__total_period(hists);
521 521
522 printed += hist_entry_callchain__fprintf(he, total, 0, fp); 522 printed += hist_entry_callchain__fprintf(he, total, 0, fp);
@@ -550,7 +550,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
550 550
551 ret = fprintf(fp, "%s\n", bf); 551 ret = fprintf(fp, "%s\n", bf);
552 552
553 if (use_callchain) 553 if (hist_entry__has_callchains(he) && use_callchain)
554 callchain_ret = hist_entry_callchain__fprintf(he, total_period, 554 callchain_ret = hist_entry_callchain__fprintf(he, total_period,
555 0, fp); 555 0, fp);
556 556
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 5d4c45b76895..b604ef334dc9 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -24,7 +24,6 @@ libperf-y += libstring.o
24libperf-y += bitmap.o 24libperf-y += bitmap.o
25libperf-y += hweight.o 25libperf-y += hweight.o
26libperf-y += smt.o 26libperf-y += smt.o
27libperf-y += quote.o
28libperf-y += strbuf.o 27libperf-y += strbuf.o
29libperf-y += string.o 28libperf-y += string.o
30libperf-y += strlist.o 29libperf-y += strlist.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 71897689dacf..f91775b4bc3c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -21,6 +21,7 @@
21#include "debug.h" 21#include "debug.h"
22#include "annotate.h" 22#include "annotate.h"
23#include "evsel.h" 23#include "evsel.h"
24#include "evlist.h"
24#include "block-range.h" 25#include "block-range.h"
25#include "string2.h" 26#include "string2.h"
26#include "arch/common.h" 27#include "arch/common.h"
@@ -46,11 +47,10 @@
46struct annotation_options annotation__default_options = { 47struct annotation_options annotation__default_options = {
47 .use_offset = true, 48 .use_offset = true,
48 .jump_arrows = true, 49 .jump_arrows = true,
50 .annotate_src = true,
49 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, 51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
50}; 52};
51 53
52const char *disassembler_style;
53const char *objdump_path;
54static regex_t file_lineno; 54static regex_t file_lineno;
55 55
56static struct ins_ops *ins__find(struct arch *arch, const char *name); 56static struct ins_ops *ins__find(struct arch *arch, const char *name);
@@ -678,10 +678,28 @@ static struct arch *arch__find(const char *name)
678 return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp); 678 return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
679} 679}
680 680
681int symbol__alloc_hist(struct symbol *sym) 681static struct annotated_source *annotated_source__new(void)
682{
683 struct annotated_source *src = zalloc(sizeof(*src));
684
685 if (src != NULL)
686 INIT_LIST_HEAD(&src->source);
687
688 return src;
689}
690
691static __maybe_unused void annotated_source__delete(struct annotated_source *src)
692{
693 if (src == NULL)
694 return;
695 zfree(&src->histograms);
696 zfree(&src->cycles_hist);
697 free(src);
698}
699
700static int annotated_source__alloc_histograms(struct annotated_source *src,
701 size_t size, int nr_hists)
682{ 702{
683 struct annotation *notes = symbol__annotation(sym);
684 size_t size = symbol__size(sym);
685 size_t sizeof_sym_hist; 703 size_t sizeof_sym_hist;
686 704
687 /* 705 /*
@@ -701,17 +719,13 @@ int symbol__alloc_hist(struct symbol *sym)
701 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry)); 719 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
702 720
703 /* Check for overflow in zalloc argument */ 721 /* Check for overflow in zalloc argument */
704 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 722 if (sizeof_sym_hist > SIZE_MAX / nr_hists)
705 / symbol_conf.nr_events)
706 return -1; 723 return -1;
707 724
708 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); 725 src->sizeof_sym_hist = sizeof_sym_hist;
709 if (notes->src == NULL) 726 src->nr_histograms = nr_hists;
710 return -1; 727 src->histograms = calloc(nr_hists, sizeof_sym_hist) ;
711 notes->src->sizeof_sym_hist = sizeof_sym_hist; 728 return src->histograms ? 0 : -1;
712 notes->src->nr_histograms = symbol_conf.nr_events;
713 INIT_LIST_HEAD(&notes->src->source);
714 return 0;
715} 729}
716 730
717/* The cycles histogram is lazily allocated. */ 731/* The cycles histogram is lazily allocated. */
@@ -741,14 +755,11 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
741 pthread_mutex_unlock(&notes->lock); 755 pthread_mutex_unlock(&notes->lock);
742} 756}
743 757
744static int __symbol__account_cycles(struct annotation *notes, 758static int __symbol__account_cycles(struct cyc_hist *ch,
745 u64 start, 759 u64 start,
746 unsigned offset, unsigned cycles, 760 unsigned offset, unsigned cycles,
747 unsigned have_start) 761 unsigned have_start)
748{ 762{
749 struct cyc_hist *ch;
750
751 ch = notes->src->cycles_hist;
752 /* 763 /*
753 * For now we can only account one basic block per 764 * For now we can only account one basic block per
754 * final jump. But multiple could be overlapping. 765 * final jump. But multiple could be overlapping.
@@ -791,7 +802,7 @@ static int __symbol__account_cycles(struct annotation *notes,
791} 802}
792 803
793static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 804static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
794 struct annotation *notes, int evidx, u64 addr, 805 struct annotated_source *src, int evidx, u64 addr,
795 struct perf_sample *sample) 806 struct perf_sample *sample)
796{ 807{
797 unsigned offset; 808 unsigned offset;
@@ -807,7 +818,12 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
807 } 818 }
808 819
809 offset = addr - sym->start; 820 offset = addr - sym->start;
810 h = annotation__histogram(notes, evidx); 821 h = annotated_source__histogram(src, evidx);
822 if (h == NULL) {
823 pr_debug("%s(%d): ENOMEM! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 ", func: %d\n",
824 __func__, __LINE__, sym->name, sym->start, addr, sym->end, sym->type == STT_FUNC);
825 return -ENOMEM;
826 }
811 h->nr_samples++; 827 h->nr_samples++;
812 h->addr[offset].nr_samples++; 828 h->addr[offset].nr_samples++;
813 h->period += sample->period; 829 h->period += sample->period;
@@ -820,45 +836,69 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
820 return 0; 836 return 0;
821} 837}
822 838
823static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles) 839static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
824{ 840{
825 struct annotation *notes = symbol__annotation(sym); 841 struct annotation *notes = symbol__annotation(sym);
826 842
827 if (notes->src == NULL) { 843 if (notes->src == NULL) {
828 if (symbol__alloc_hist(sym) < 0) 844 notes->src = annotated_source__new();
845 if (notes->src == NULL)
829 return NULL; 846 return NULL;
847 goto alloc_cycles_hist;
848 }
849
850 if (!notes->src->cycles_hist) {
851alloc_cycles_hist:
852 symbol__alloc_hist_cycles(sym);
830 } 853 }
831 if (!notes->src->cycles_hist && cycles) { 854
832 if (symbol__alloc_hist_cycles(sym) < 0) 855 return notes->src->cycles_hist;
856}
857
858struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
859{
860 struct annotation *notes = symbol__annotation(sym);
861
862 if (notes->src == NULL) {
863 notes->src = annotated_source__new();
864 if (notes->src == NULL)
833 return NULL; 865 return NULL;
866 goto alloc_histograms;
834 } 867 }
835 return notes; 868
869 if (notes->src->histograms == NULL) {
870alloc_histograms:
871 annotated_source__alloc_histograms(notes->src, symbol__size(sym),
872 nr_hists);
873 }
874
875 return notes->src;
836} 876}
837 877
838static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 878static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
839 int evidx, u64 addr, 879 struct perf_evsel *evsel, u64 addr,
840 struct perf_sample *sample) 880 struct perf_sample *sample)
841{ 881{
842 struct annotation *notes; 882 struct annotated_source *src;
843 883
844 if (sym == NULL) 884 if (sym == NULL)
845 return 0; 885 return 0;
846 notes = symbol__get_annotation(sym, false); 886 src = symbol__hists(sym, evsel->evlist->nr_entries);
847 if (notes == NULL) 887 if (src == NULL)
848 return -ENOMEM; 888 return -ENOMEM;
849 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample); 889 return __symbol__inc_addr_samples(sym, map, src, evsel->idx, addr, sample);
850} 890}
851 891
852static int symbol__account_cycles(u64 addr, u64 start, 892static int symbol__account_cycles(u64 addr, u64 start,
853 struct symbol *sym, unsigned cycles) 893 struct symbol *sym, unsigned cycles)
854{ 894{
855 struct annotation *notes; 895 struct cyc_hist *cycles_hist;
856 unsigned offset; 896 unsigned offset;
857 897
858 if (sym == NULL) 898 if (sym == NULL)
859 return 0; 899 return 0;
860 notes = symbol__get_annotation(sym, true); 900 cycles_hist = symbol__cycles_hist(sym);
861 if (notes == NULL) 901 if (cycles_hist == NULL)
862 return -ENOMEM; 902 return -ENOMEM;
863 if (addr < sym->start || addr >= sym->end) 903 if (addr < sym->start || addr >= sym->end)
864 return -ERANGE; 904 return -ERANGE;
@@ -870,7 +910,7 @@ static int symbol__account_cycles(u64 addr, u64 start,
870 start = 0; 910 start = 0;
871 } 911 }
872 offset = addr - sym->start; 912 offset = addr - sym->start;
873 return __symbol__account_cycles(notes, 913 return __symbol__account_cycles(cycles_hist,
874 start ? start - sym->start : 0, 914 start ? start - sym->start : 0,
875 offset, cycles, 915 offset, cycles,
876 !!start); 916 !!start);
@@ -974,15 +1014,15 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
974} 1014}
975 1015
976int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 1016int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
977 int evidx) 1017 struct perf_evsel *evsel)
978{ 1018{
979 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample); 1019 return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
980} 1020}
981 1021
982int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, 1022int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
983 int evidx, u64 ip) 1023 struct perf_evsel *evsel, u64 ip)
984{ 1024{
985 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample); 1025 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
986} 1026}
987 1027
988static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms) 1028static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
@@ -1031,6 +1071,7 @@ struct annotate_args {
1031 struct arch *arch; 1071 struct arch *arch;
1032 struct map_symbol ms; 1072 struct map_symbol ms;
1033 struct perf_evsel *evsel; 1073 struct perf_evsel *evsel;
1074 struct annotation_options *options;
1034 s64 offset; 1075 s64 offset;
1035 char *line; 1076 char *line;
1036 int line_nr; 1077 int line_nr;
@@ -1572,6 +1613,7 @@ fallback:
1572 1613
1573static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1614static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1574{ 1615{
1616 struct annotation_options *opts = args->options;
1575 struct map *map = args->ms.map; 1617 struct map *map = args->ms.map;
1576 struct dso *dso = map->dso; 1618 struct dso *dso = map->dso;
1577 char *command; 1619 char *command;
@@ -1619,13 +1661,13 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1619 "%s %s%s --start-address=0x%016" PRIx64 1661 "%s %s%s --start-address=0x%016" PRIx64
1620 " --stop-address=0x%016" PRIx64 1662 " --stop-address=0x%016" PRIx64
1621 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand", 1663 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
1622 objdump_path ? objdump_path : "objdump", 1664 opts->objdump_path ?: "objdump",
1623 disassembler_style ? "-M " : "", 1665 opts->disassembler_style ? "-M " : "",
1624 disassembler_style ? disassembler_style : "", 1666 opts->disassembler_style ?: "",
1625 map__rip_2objdump(map, sym->start), 1667 map__rip_2objdump(map, sym->start),
1626 map__rip_2objdump(map, sym->end), 1668 map__rip_2objdump(map, sym->end),
1627 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 1669 opts->show_asm_raw ? "" : "--no-show-raw",
1628 symbol_conf.annotate_src ? "-S" : "", 1670 opts->annotate_src ? "-S" : "",
1629 symfs_filename, symfs_filename); 1671 symfs_filename, symfs_filename);
1630 1672
1631 if (err < 0) { 1673 if (err < 0) {
@@ -1767,11 +1809,13 @@ void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
1767 1809
1768int symbol__annotate(struct symbol *sym, struct map *map, 1810int symbol__annotate(struct symbol *sym, struct map *map,
1769 struct perf_evsel *evsel, size_t privsize, 1811 struct perf_evsel *evsel, size_t privsize,
1812 struct annotation_options *options,
1770 struct arch **parch) 1813 struct arch **parch)
1771{ 1814{
1772 struct annotate_args args = { 1815 struct annotate_args args = {
1773 .privsize = privsize, 1816 .privsize = privsize,
1774 .evsel = evsel, 1817 .evsel = evsel,
1818 .options = options,
1775 }; 1819 };
1776 struct perf_env *env = perf_evsel__env(evsel); 1820 struct perf_env *env = perf_evsel__env(evsel);
1777 const char *arch_name = perf_env__arch(env); 1821 const char *arch_name = perf_env__arch(env);
@@ -1949,8 +1993,8 @@ static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
1949} 1993}
1950 1994
1951int symbol__annotate_printf(struct symbol *sym, struct map *map, 1995int symbol__annotate_printf(struct symbol *sym, struct map *map,
1952 struct perf_evsel *evsel, bool full_paths, 1996 struct perf_evsel *evsel,
1953 int min_pcnt, int max_lines, int context) 1997 struct annotation_options *opts)
1954{ 1998{
1955 struct dso *dso = map->dso; 1999 struct dso *dso = map->dso;
1956 char *filename; 2000 char *filename;
@@ -1962,6 +2006,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1962 u64 start = map__rip_2objdump(map, sym->start); 2006 u64 start = map__rip_2objdump(map, sym->start);
1963 int printed = 2, queue_len = 0, addr_fmt_width; 2007 int printed = 2, queue_len = 0, addr_fmt_width;
1964 int more = 0; 2008 int more = 0;
2009 bool context = opts->context;
1965 u64 len; 2010 u64 len;
1966 int width = symbol_conf.show_total_period ? 12 : 8; 2011 int width = symbol_conf.show_total_period ? 12 : 8;
1967 int graph_dotted_len; 2012 int graph_dotted_len;
@@ -1971,7 +2016,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1971 if (!filename) 2016 if (!filename)
1972 return -ENOMEM; 2017 return -ENOMEM;
1973 2018
1974 if (full_paths) 2019 if (opts->full_path)
1975 d_filename = filename; 2020 d_filename = filename;
1976 else 2021 else
1977 d_filename = basename(filename); 2022 d_filename = basename(filename);
@@ -2006,7 +2051,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2006 } 2051 }
2007 2052
2008 err = annotation_line__print(pos, sym, start, evsel, len, 2053 err = annotation_line__print(pos, sym, start, evsel, len,
2009 min_pcnt, printed, max_lines, 2054 opts->min_pcnt, printed, opts->max_lines,
2010 queue, addr_fmt_width); 2055 queue, addr_fmt_width);
2011 2056
2012 switch (err) { 2057 switch (err) {
@@ -2339,20 +2384,19 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
2339} 2384}
2340 2385
2341int symbol__tty_annotate2(struct symbol *sym, struct map *map, 2386int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2342 struct perf_evsel *evsel, bool print_lines, 2387 struct perf_evsel *evsel,
2343 bool full_paths) 2388 struct annotation_options *opts)
2344{ 2389{
2345 struct dso *dso = map->dso; 2390 struct dso *dso = map->dso;
2346 struct rb_root source_line = RB_ROOT; 2391 struct rb_root source_line = RB_ROOT;
2347 struct annotation_options opts = annotation__default_options;
2348 struct annotation *notes = symbol__annotation(sym); 2392 struct annotation *notes = symbol__annotation(sym);
2349 char buf[1024]; 2393 char buf[1024];
2350 2394
2351 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) 2395 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
2352 return -1; 2396 return -1;
2353 2397
2354 if (print_lines) { 2398 if (opts->print_lines) {
2355 srcline_full_filename = full_paths; 2399 srcline_full_filename = opts->full_path;
2356 symbol__calc_lines(sym, map, &source_line); 2400 symbol__calc_lines(sym, map, &source_line);
2357 print_summary(&source_line, dso->long_name); 2401 print_summary(&source_line, dso->long_name);
2358 } 2402 }
@@ -2367,25 +2411,24 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2367} 2411}
2368 2412
2369int symbol__tty_annotate(struct symbol *sym, struct map *map, 2413int symbol__tty_annotate(struct symbol *sym, struct map *map,
2370 struct perf_evsel *evsel, bool print_lines, 2414 struct perf_evsel *evsel,
2371 bool full_paths, int min_pcnt, int max_lines) 2415 struct annotation_options *opts)
2372{ 2416{
2373 struct dso *dso = map->dso; 2417 struct dso *dso = map->dso;
2374 struct rb_root source_line = RB_ROOT; 2418 struct rb_root source_line = RB_ROOT;
2375 2419
2376 if (symbol__annotate(sym, map, evsel, 0, NULL) < 0) 2420 if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0)
2377 return -1; 2421 return -1;
2378 2422
2379 symbol__calc_percent(sym, evsel); 2423 symbol__calc_percent(sym, evsel);
2380 2424
2381 if (print_lines) { 2425 if (opts->print_lines) {
2382 srcline_full_filename = full_paths; 2426 srcline_full_filename = opts->full_path;
2383 symbol__calc_lines(sym, map, &source_line); 2427 symbol__calc_lines(sym, map, &source_line);
2384 print_summary(&source_line, dso->long_name); 2428 print_summary(&source_line, dso->long_name);
2385 } 2429 }
2386 2430
2387 symbol__annotate_printf(sym, map, evsel, full_paths, 2431 symbol__annotate_printf(sym, map, evsel, opts);
2388 min_pcnt, max_lines, 0);
2389 2432
2390 annotated_source__purge(symbol__annotation(sym)->src); 2433 annotated_source__purge(symbol__annotation(sym)->src);
2391 2434
@@ -2620,7 +2663,7 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
2620 if (perf_evsel__is_group_event(evsel)) 2663 if (perf_evsel__is_group_event(evsel))
2621 nr_pcnt = evsel->nr_members; 2664 nr_pcnt = evsel->nr_members;
2622 2665
2623 err = symbol__annotate(sym, map, evsel, 0, parch); 2666 err = symbol__annotate(sym, map, evsel, 0, options, parch);
2624 if (err) 2667 if (err)
2625 goto out_free_offsets; 2668 goto out_free_offsets;
2626 2669
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 5080b6dd98b8..a4c0d91907e6 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -67,12 +67,21 @@ struct annotation_options {
67 bool hide_src_code, 67 bool hide_src_code,
68 use_offset, 68 use_offset,
69 jump_arrows, 69 jump_arrows,
70 print_lines,
71 full_path,
70 show_linenr, 72 show_linenr,
71 show_nr_jumps, 73 show_nr_jumps,
72 show_nr_samples, 74 show_nr_samples,
73 show_total_period, 75 show_total_period,
74 show_minmax_cycle; 76 show_minmax_cycle,
77 show_asm_raw,
78 annotate_src;
75 u8 offset_level; 79 u8 offset_level;
80 int min_pcnt;
81 int max_lines;
82 int context;
83 const char *objdump_path;
84 const char *disassembler_style;
76}; 85};
77 86
78enum { 87enum {
@@ -201,7 +210,11 @@ struct cyc_hist {
201 210
202/** struct annotated_source - symbols with hits have this attached as in sannotation 211/** struct annotated_source - symbols with hits have this attached as in sannotation
203 * 212 *
204 * @histogram: Array of addr hit histograms per event being monitored 213 * @histograms: Array of addr hit histograms per event being monitored
214 * nr_histograms: This may not be the same as evsel->evlist->nr_entries if
215 * we have more than a group in a evlist, where we will want
216 * to see each group separately, that is why symbol__annotate2()
217 * sets src->nr_histograms to evsel->nr_members.
205 * @lines: If 'print_lines' is specified, per source code line percentages 218 * @lines: If 'print_lines' is specified, per source code line percentages
206 * @source: source parsed from a disassembler like objdump -dS 219 * @source: source parsed from a disassembler like objdump -dS
207 * @cyc_hist: Average cycles per basic block 220 * @cyc_hist: Average cycles per basic block
@@ -217,7 +230,7 @@ struct annotated_source {
217 int nr_histograms; 230 int nr_histograms;
218 size_t sizeof_sym_hist; 231 size_t sizeof_sym_hist;
219 struct cyc_hist *cycles_hist; 232 struct cyc_hist *cycles_hist;
220 struct sym_hist histograms[0]; 233 struct sym_hist *histograms;
221}; 234};
222 235
223struct annotation { 236struct annotation {
@@ -267,10 +280,14 @@ void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
267void annotation__update_column_widths(struct annotation *notes); 280void annotation__update_column_widths(struct annotation *notes);
268void annotation__init_column_widths(struct annotation *notes, struct symbol *sym); 281void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
269 282
283static inline struct sym_hist *annotated_source__histogram(struct annotated_source *src, int idx)
284{
285 return ((void *)src->histograms) + (src->sizeof_sym_hist * idx);
286}
287
270static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 288static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
271{ 289{
272 return (((void *)&notes->src->histograms) + 290 return annotated_source__histogram(notes->src, idx);
273 (notes->src->sizeof_sym_hist * idx));
274} 291}
275 292
276static inline struct annotation *symbol__annotation(struct symbol *sym) 293static inline struct annotation *symbol__annotation(struct symbol *sym)
@@ -279,20 +296,21 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
279} 296}
280 297
281int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 298int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
282 int evidx); 299 struct perf_evsel *evsel);
283 300
284int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 301int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
285 struct addr_map_symbol *start, 302 struct addr_map_symbol *start,
286 unsigned cycles); 303 unsigned cycles);
287 304
288int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, 305int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
289 int evidx, u64 addr); 306 struct perf_evsel *evsel, u64 addr);
290 307
291int symbol__alloc_hist(struct symbol *sym); 308struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
292void symbol__annotate_zero_histograms(struct symbol *sym); 309void symbol__annotate_zero_histograms(struct symbol *sym);
293 310
294int symbol__annotate(struct symbol *sym, struct map *map, 311int symbol__annotate(struct symbol *sym, struct map *map,
295 struct perf_evsel *evsel, size_t privsize, 312 struct perf_evsel *evsel, size_t privsize,
313 struct annotation_options *options,
296 struct arch **parch); 314 struct arch **parch);
297int symbol__annotate2(struct symbol *sym, struct map *map, 315int symbol__annotate2(struct symbol *sym, struct map *map,
298 struct perf_evsel *evsel, 316 struct perf_evsel *evsel,
@@ -320,8 +338,8 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
320 int errnum, char *buf, size_t buflen); 338 int errnum, char *buf, size_t buflen);
321 339
322int symbol__annotate_printf(struct symbol *sym, struct map *map, 340int symbol__annotate_printf(struct symbol *sym, struct map *map,
323 struct perf_evsel *evsel, bool full_paths, 341 struct perf_evsel *evsel,
324 int min_pcnt, int max_lines, int context); 342 struct annotation_options *options);
325int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp); 343int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
326void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 344void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
327void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 345void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
@@ -332,30 +350,27 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
332bool ui__has_annotation(void); 350bool ui__has_annotation(void);
333 351
334int symbol__tty_annotate(struct symbol *sym, struct map *map, 352int symbol__tty_annotate(struct symbol *sym, struct map *map,
335 struct perf_evsel *evsel, bool print_lines, 353 struct perf_evsel *evsel, struct annotation_options *opts);
336 bool full_paths, int min_pcnt, int max_lines);
337 354
338int symbol__tty_annotate2(struct symbol *sym, struct map *map, 355int symbol__tty_annotate2(struct symbol *sym, struct map *map,
339 struct perf_evsel *evsel, bool print_lines, 356 struct perf_evsel *evsel, struct annotation_options *opts);
340 bool full_paths);
341 357
342#ifdef HAVE_SLANG_SUPPORT 358#ifdef HAVE_SLANG_SUPPORT
343int symbol__tui_annotate(struct symbol *sym, struct map *map, 359int symbol__tui_annotate(struct symbol *sym, struct map *map,
344 struct perf_evsel *evsel, 360 struct perf_evsel *evsel,
345 struct hist_browser_timer *hbt); 361 struct hist_browser_timer *hbt,
362 struct annotation_options *opts);
346#else 363#else
347static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, 364static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
348 struct map *map __maybe_unused, 365 struct map *map __maybe_unused,
349 struct perf_evsel *evsel __maybe_unused, 366 struct perf_evsel *evsel __maybe_unused,
350 struct hist_browser_timer *hbt 367 struct hist_browser_timer *hbt __maybe_unused,
351 __maybe_unused) 368 struct annotation_options *opts __maybe_unused)
352{ 369{
353 return 0; 370 return 0;
354} 371}
355#endif 372#endif
356 373
357extern const char *disassembler_style;
358
359void annotation_config__init(void); 374void annotation_config__init(void);
360 375
361#endif /* __PERF_ANNOTATE_H */ 376#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 29347756b0af..77e4891e17b0 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -61,7 +61,7 @@ check_pos(struct bpf_insn_pos *pos)
61 61
62/* 62/*
63 * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see 63 * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
64 * Documentation/trace/kprobetrace.txt) to size field of BPF_LDX_MEM 64 * Documentation/trace/kprobetrace.rst) to size field of BPF_LDX_MEM
65 * instruction (BPF_{B,H,W,DW}). 65 * instruction (BPF_{B,H,W,DW}).
66 */ 66 */
67static int 67static int
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index bf31ceab33bd..89512504551b 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -146,8 +146,15 @@ getBPFObjectFromModule(llvm::Module *Module)
146 raw_svector_ostream ostream(*Buffer); 146 raw_svector_ostream ostream(*Buffer);
147 147
148 legacy::PassManager PM; 148 legacy::PassManager PM;
149 if (TargetMachine->addPassesToEmitFile(PM, ostream, 149 bool NotAdded;
150 TargetMachine::CGFT_ObjectFile)) { 150#if CLANG_VERSION_MAJOR < 7
151 NotAdded = TargetMachine->addPassesToEmitFile(PM, ostream,
152 TargetMachine::CGFT_ObjectFile);
153#else
154 NotAdded = TargetMachine->addPassesToEmitFile(PM, ostream, nullptr,
155 TargetMachine::CGFT_ObjectFile);
156#endif
157 if (NotAdded) {
151 llvm::errs() << "TargetMachine can't emit a file of this type\n"; 158 llvm::errs() << "TargetMachine can't emit a file of this type\n";
152 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; 159 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
153 } 160 }
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index decb91f9da82..ccd02634a616 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -93,20 +93,17 @@ static int open_cgroup(const char *name)
93static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str) 93static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str)
94{ 94{
95 struct perf_evsel *counter; 95 struct perf_evsel *counter;
96 struct cgroup *cgrp = NULL;
97 /* 96 /*
98 * check if cgrp is already defined, if so we reuse it 97 * check if cgrp is already defined, if so we reuse it
99 */ 98 */
100 evlist__for_each_entry(evlist, counter) { 99 evlist__for_each_entry(evlist, counter) {
101 if (!counter->cgrp) 100 if (!counter->cgrp)
102 continue; 101 continue;
103 if (!strcmp(counter->cgrp->name, str)) { 102 if (!strcmp(counter->cgrp->name, str))
104 cgrp = cgroup__get(counter->cgrp); 103 return cgroup__get(counter->cgrp);
105 break;
106 }
107 } 104 }
108 105
109 return cgrp; 106 return NULL;
110} 107}
111 108
112static struct cgroup *cgroup__new(const char *name) 109static struct cgroup *cgroup__new(const char *name)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index cdfc2e5f55f5..51cf82cf1882 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -354,6 +354,8 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
354 if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) || 354 if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) ||
355 (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) || 355 (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) ||
356 (strncmp(name, "[vdso]", 6) == 0) || 356 (strncmp(name, "[vdso]", 6) == 0) ||
357 (strncmp(name, "[vdso32]", 8) == 0) ||
358 (strncmp(name, "[vdsox32]", 9) == 0) ||
357 (strncmp(name, "[vsyscall]", 10) == 0)) { 359 (strncmp(name, "[vsyscall]", 10) == 0)) {
358 m->kmod = false; 360 m->kmod = false;
359 361
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 150db5ed7400..94fce4f537e9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2197,7 +2197,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
2197 } 2197 }
2198 } 2198 }
2199 2199
2200 if (type & PERF_SAMPLE_CALLCHAIN) { 2200 if (evsel__has_callchain(evsel)) {
2201 const u64 max_callchain_nr = UINT64_MAX / sizeof(u64); 2201 const u64 max_callchain_nr = UINT64_MAX / sizeof(u64);
2202 2202
2203 OVERFLOW_CHECK_u64(array); 2203 OVERFLOW_CHECK_u64(array);
@@ -2857,7 +2857,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2857 "Hint: Try again after reducing the number of events.\n" 2857 "Hint: Try again after reducing the number of events.\n"
2858 "Hint: Try increasing the limit with 'ulimit -n <limit>'"); 2858 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2859 case ENOMEM: 2859 case ENOMEM:
2860 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 && 2860 if (evsel__has_callchain(evsel) &&
2861 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0) 2861 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
2862 return scnprintf(msg, size, 2862 return scnprintf(msg, size,
2863 "Not enough memory to setup event with callchain.\n" 2863 "Not enough memory to setup event with callchain.\n"
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b13f5f234c8f..d277930b19a1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -459,6 +459,11 @@ static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evs
459 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 459 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
460} 460}
461 461
462static inline bool evsel__has_callchain(const struct perf_evsel *evsel)
463{
464 return (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0;
465}
466
462typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); 467typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
463 468
464int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, 469int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a8bff2178fbc..653ff65aa2c3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1459,8 +1459,24 @@ static void print_cmdline(struct feat_fd *ff, FILE *fp)
1459 1459
1460 fprintf(fp, "# cmdline : "); 1460 fprintf(fp, "# cmdline : ");
1461 1461
1462 for (i = 0; i < nr; i++) 1462 for (i = 0; i < nr; i++) {
1463 fprintf(fp, "%s ", ff->ph->env.cmdline_argv[i]); 1463 char *argv_i = strdup(ff->ph->env.cmdline_argv[i]);
1464 if (!argv_i) {
1465 fprintf(fp, "%s ", ff->ph->env.cmdline_argv[i]);
1466 } else {
1467 char *mem = argv_i;
1468 do {
1469 char *quote = strchr(argv_i, '\'');
1470 if (!quote)
1471 break;
1472 *quote++ = '\0';
1473 fprintf(fp, "%s\\\'", argv_i);
1474 argv_i = quote;
1475 } while (1);
1476 fprintf(fp, "%s ", argv_i);
1477 free(mem);
1478 }
1479 }
1464 fputc('\n', fp); 1480 fputc('\n', fp);
1465} 1481}
1466 1482
@@ -2113,6 +2129,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
2113 int cpu_nr = ff->ph->env.nr_cpus_avail; 2129 int cpu_nr = ff->ph->env.nr_cpus_avail;
2114 u64 size = 0; 2130 u64 size = 0;
2115 struct perf_header *ph = ff->ph; 2131 struct perf_header *ph = ff->ph;
2132 bool do_core_id_test = true;
2116 2133
2117 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); 2134 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
2118 if (!ph->env.cpu) 2135 if (!ph->env.cpu)
@@ -2167,6 +2184,13 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
2167 return 0; 2184 return 0;
2168 } 2185 }
2169 2186
2187 /* On s390 the socket_id number is not related to the numbers of cpus.
2188 * The socket_id number might be higher than the numbers of cpus.
2189 * This depends on the configuration.
2190 */
2191 if (ph->env.arch && !strncmp(ph->env.arch, "s390", 4))
2192 do_core_id_test = false;
2193
2170 for (i = 0; i < (u32)cpu_nr; i++) { 2194 for (i = 0; i < (u32)cpu_nr; i++) {
2171 if (do_read_u32(ff, &nr)) 2195 if (do_read_u32(ff, &nr))
2172 goto free_cpu; 2196 goto free_cpu;
@@ -2176,7 +2200,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
2176 if (do_read_u32(ff, &nr)) 2200 if (do_read_u32(ff, &nr))
2177 goto free_cpu; 2201 goto free_cpu;
2178 2202
2179 if (nr != (u32)-1 && nr > (u32)cpu_nr) { 2203 if (do_core_id_test && nr != (u32)-1 && nr > (u32)cpu_nr) {
2180 pr_debug("socket_id number is too big." 2204 pr_debug("socket_id number is too big."
2181 "You may need to upgrade the perf tool.\n"); 2205 "You may need to upgrade the perf tool.\n");
2182 goto free_cpu; 2206 goto free_cpu;
@@ -3312,8 +3336,6 @@ int perf_session__read_header(struct perf_session *session)
3312 lseek(fd, tmp, SEEK_SET); 3336 lseek(fd, tmp, SEEK_SET);
3313 } 3337 }
3314 3338
3315 symbol_conf.nr_events = nr_attrs;
3316
3317 perf_header__process_sections(header, fd, &session->tevent, 3339 perf_header__process_sections(header, fd, &session->tevent,
3318 perf_file_section__process); 3340 perf_file_section__process);
3319 3341
@@ -3442,7 +3464,7 @@ int perf_event__process_feature(struct perf_tool *tool,
3442 pr_warning("invalid record type %d in pipe-mode\n", type); 3464 pr_warning("invalid record type %d in pipe-mode\n", type);
3443 return 0; 3465 return 0;
3444 } 3466 }
3445 if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) { 3467 if (feat == HEADER_RESERVED || feat >= HEADER_LAST_FEATURE) {
3446 pr_warning("invalid record type %d in pipe-mode\n", type); 3468 pr_warning("invalid record type %d in pipe-mode\n", type);
3447 return -1; 3469 return -1;
3448 } 3470 }
@@ -3739,8 +3761,6 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
3739 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]); 3761 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
3740 } 3762 }
3741 3763
3742 symbol_conf.nr_events = evlist->nr_entries;
3743
3744 return 0; 3764 return 0;
3745} 3765}
3746 3766
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 4d602fba40b2..828cb9794c76 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -370,9 +370,11 @@ void hists__delete_entries(struct hists *hists)
370 370
371static int hist_entry__init(struct hist_entry *he, 371static int hist_entry__init(struct hist_entry *he,
372 struct hist_entry *template, 372 struct hist_entry *template,
373 bool sample_self) 373 bool sample_self,
374 size_t callchain_size)
374{ 375{
375 *he = *template; 376 *he = *template;
377 he->callchain_size = callchain_size;
376 378
377 if (symbol_conf.cumulate_callchain) { 379 if (symbol_conf.cumulate_callchain) {
378 he->stat_acc = malloc(sizeof(he->stat)); 380 he->stat_acc = malloc(sizeof(he->stat));
@@ -410,7 +412,7 @@ static int hist_entry__init(struct hist_entry *he,
410 map__get(he->mem_info->daddr.map); 412 map__get(he->mem_info->daddr.map);
411 } 413 }
412 414
413 if (symbol_conf.use_callchain) 415 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
414 callchain_init(he->callchain); 416 callchain_init(he->callchain);
415 417
416 if (he->raw_data) { 418 if (he->raw_data) {
@@ -473,7 +475,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
473 475
474 he = ops->new(callchain_size); 476 he = ops->new(callchain_size);
475 if (he) { 477 if (he) {
476 err = hist_entry__init(he, template, sample_self); 478 err = hist_entry__init(he, template, sample_self, callchain_size);
477 if (err) { 479 if (err) {
478 ops->free(he); 480 ops->free(he);
479 he = NULL; 481 he = NULL;
@@ -492,7 +494,7 @@ static u8 symbol__parent_filter(const struct symbol *parent)
492 494
493static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period) 495static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period)
494{ 496{
495 if (!symbol_conf.use_callchain) 497 if (!hist_entry__has_callchains(he) || !symbol_conf.use_callchain)
496 return; 498 return;
497 499
498 he->hists->callchain_period += period; 500 he->hists->callchain_period += period;
@@ -619,9 +621,11 @@ __hists__add_entry(struct hists *hists,
619 .raw_data = sample->raw_data, 621 .raw_data = sample->raw_data,
620 .raw_size = sample->raw_size, 622 .raw_size = sample->raw_size,
621 .ops = ops, 623 .ops = ops,
622 }; 624 }, *he = hists__findnew_entry(hists, &entry, al, sample_self);
623 625
624 return hists__findnew_entry(hists, &entry, al, sample_self); 626 if (!hists->has_callchains && he && he->callchain_size != 0)
627 hists->has_callchains = true;
628 return he;
625} 629}
626 630
627struct hist_entry *hists__add_entry(struct hists *hists, 631struct hist_entry *hists__add_entry(struct hists *hists,
@@ -986,7 +990,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
986 iter->he = he; 990 iter->he = he;
987 he_cache[iter->curr++] = he; 991 he_cache[iter->curr++] = he;
988 992
989 if (symbol_conf.use_callchain) 993 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
990 callchain_append(he->callchain, &cursor, sample->period); 994 callchain_append(he->callchain, &cursor, sample->period);
991 return 0; 995 return 0;
992} 996}
@@ -1039,7 +1043,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1039 int err, err2; 1043 int err, err2;
1040 struct map *alm = NULL; 1044 struct map *alm = NULL;
1041 1045
1042 if (al && al->map) 1046 if (al)
1043 alm = map__get(al->map); 1047 alm = map__get(al->map);
1044 1048
1045 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1049 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
@@ -1373,7 +1377,8 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1373 if (new_he) { 1377 if (new_he) {
1374 new_he->leaf = true; 1378 new_he->leaf = true;
1375 1379
1376 if (symbol_conf.use_callchain) { 1380 if (hist_entry__has_callchains(new_he) &&
1381 symbol_conf.use_callchain) {
1377 callchain_cursor_reset(&callchain_cursor); 1382 callchain_cursor_reset(&callchain_cursor);
1378 if (callchain_merge(&callchain_cursor, 1383 if (callchain_merge(&callchain_cursor,
1379 new_he->callchain, 1384 new_he->callchain,
@@ -1414,7 +1419,7 @@ static int hists__collapse_insert_entry(struct hists *hists,
1414 if (symbol_conf.cumulate_callchain) 1419 if (symbol_conf.cumulate_callchain)
1415 he_stat__add_stat(iter->stat_acc, he->stat_acc); 1420 he_stat__add_stat(iter->stat_acc, he->stat_acc);
1416 1421
1417 if (symbol_conf.use_callchain) { 1422 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
1418 callchain_cursor_reset(&callchain_cursor); 1423 callchain_cursor_reset(&callchain_cursor);
1419 if (callchain_merge(&callchain_cursor, 1424 if (callchain_merge(&callchain_cursor,
1420 iter->callchain, 1425 iter->callchain,
@@ -1757,7 +1762,7 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1757 bool use_callchain; 1762 bool use_callchain;
1758 1763
1759 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) 1764 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
1760 use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; 1765 use_callchain = evsel__has_callchain(evsel);
1761 else 1766 else
1762 use_callchain = symbol_conf.use_callchain; 1767 use_callchain = symbol_conf.use_callchain;
1763 1768
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index fbabfd8a215d..73049f7f0f60 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -85,6 +85,7 @@ struct hists {
85 struct events_stats stats; 85 struct events_stats stats;
86 u64 event_stream; 86 u64 event_stream;
87 u16 col_len[HISTC_NR_COLS]; 87 u16 col_len[HISTC_NR_COLS];
88 bool has_callchains;
88 int socket_filter; 89 int socket_filter;
89 struct perf_hpp_list *hpp_list; 90 struct perf_hpp_list *hpp_list;
90 struct list_head hpp_formats; 91 struct list_head hpp_formats;
@@ -220,6 +221,11 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel)
220 return &hevsel->hists; 221 return &hevsel->hists;
221} 222}
222 223
224static __pure inline bool hists__has_callchains(struct hists *hists)
225{
226 return hists->has_callchains;
227}
228
223int hists__init(void); 229int hists__init(void);
224int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 230int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
225 231
@@ -419,19 +425,24 @@ struct hist_browser_timer {
419 int refresh; 425 int refresh;
420}; 426};
421 427
428struct annotation_options;
429
422#ifdef HAVE_SLANG_SUPPORT 430#ifdef HAVE_SLANG_SUPPORT
423#include "../ui/keysyms.h" 431#include "../ui/keysyms.h"
424int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 432int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
425 struct hist_browser_timer *hbt); 433 struct hist_browser_timer *hbt,
434 struct annotation_options *annotation_opts);
426 435
427int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 436int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
428 struct hist_browser_timer *hbt); 437 struct hist_browser_timer *hbt,
438 struct annotation_options *annotation_opts);
429 439
430int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 440int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
431 struct hist_browser_timer *hbt, 441 struct hist_browser_timer *hbt,
432 float min_pcnt, 442 float min_pcnt,
433 struct perf_env *env, 443 struct perf_env *env,
434 bool warn_lost_event); 444 bool warn_lost_event,
445 struct annotation_options *annotation_options);
435int script_browse(const char *script_opt); 446int script_browse(const char *script_opt);
436#else 447#else
437static inline 448static inline
@@ -440,20 +451,23 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
440 struct hist_browser_timer *hbt __maybe_unused, 451 struct hist_browser_timer *hbt __maybe_unused,
441 float min_pcnt __maybe_unused, 452 float min_pcnt __maybe_unused,
442 struct perf_env *env __maybe_unused, 453 struct perf_env *env __maybe_unused,
443 bool warn_lost_event __maybe_unused) 454 bool warn_lost_event __maybe_unused,
455 struct annotation_options *annotation_options __maybe_unused)
444{ 456{
445 return 0; 457 return 0;
446} 458}
447static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused, 459static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
448 struct perf_evsel *evsel __maybe_unused, 460 struct perf_evsel *evsel __maybe_unused,
449 struct hist_browser_timer *hbt __maybe_unused) 461 struct hist_browser_timer *hbt __maybe_unused,
462 struct annotation_options *annotation_options __maybe_unused)
450{ 463{
451 return 0; 464 return 0;
452} 465}
453 466
454static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, 467static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
455 struct perf_evsel *evsel __maybe_unused, 468 struct perf_evsel *evsel __maybe_unused,
456 struct hist_browser_timer *hbt __maybe_unused) 469 struct hist_browser_timer *hbt __maybe_unused,
470 struct annotation_options *annotation_opts __maybe_unused)
457{ 471{
458 return 0; 472 return 0;
459} 473}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index f9157aed1289..d404bed7003a 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -113,6 +113,7 @@ struct intel_pt_decoder {
113 bool have_cyc; 113 bool have_cyc;
114 bool fixup_last_mtc; 114 bool fixup_last_mtc;
115 bool have_last_ip; 115 bool have_last_ip;
116 enum intel_pt_param_flags flags;
116 uint64_t pos; 117 uint64_t pos;
117 uint64_t last_ip; 118 uint64_t last_ip;
118 uint64_t ip; 119 uint64_t ip;
@@ -226,6 +227,8 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
226 decoder->return_compression = params->return_compression; 227 decoder->return_compression = params->return_compression;
227 decoder->branch_enable = params->branch_enable; 228 decoder->branch_enable = params->branch_enable;
228 229
230 decoder->flags = params->flags;
231
229 decoder->period = params->period; 232 decoder->period = params->period;
230 decoder->period_type = params->period_type; 233 decoder->period_type = params->period_type;
231 234
@@ -1097,6 +1100,15 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
1097 return ret; 1100 return ret;
1098} 1101}
1099 1102
1103static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder,
1104 struct intel_pt_insn *intel_pt_insn,
1105 uint64_t ip, int err)
1106{
1107 return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err &&
1108 intel_pt_insn->branch == INTEL_PT_BR_INDIRECT &&
1109 ip == decoder->ip + intel_pt_insn->length;
1110}
1111
1100static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) 1112static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
1101{ 1113{
1102 struct intel_pt_insn intel_pt_insn; 1114 struct intel_pt_insn intel_pt_insn;
@@ -1109,10 +1121,11 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
1109 err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip); 1121 err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip);
1110 if (err == INTEL_PT_RETURN) 1122 if (err == INTEL_PT_RETURN)
1111 return 0; 1123 return 0;
1112 if (err == -EAGAIN) { 1124 if (err == -EAGAIN ||
1125 intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) {
1113 if (intel_pt_fup_event(decoder)) 1126 if (intel_pt_fup_event(decoder))
1114 return 0; 1127 return 0;
1115 return err; 1128 return -EAGAIN;
1116 } 1129 }
1117 decoder->set_fup_tx_flags = false; 1130 decoder->set_fup_tx_flags = false;
1118 if (err) 1131 if (err)
@@ -1376,7 +1389,6 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
1376{ 1389{
1377 intel_pt_log("ERROR: Buffer overflow\n"); 1390 intel_pt_log("ERROR: Buffer overflow\n");
1378 intel_pt_clear_tx_flags(decoder); 1391 intel_pt_clear_tx_flags(decoder);
1379 decoder->have_tma = false;
1380 decoder->cbr = 0; 1392 decoder->cbr = 0;
1381 decoder->timestamp_insn_cnt = 0; 1393 decoder->timestamp_insn_cnt = 0;
1382 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1394 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
@@ -1604,7 +1616,6 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1604 case INTEL_PT_PSB: 1616 case INTEL_PT_PSB:
1605 case INTEL_PT_TSC: 1617 case INTEL_PT_TSC:
1606 case INTEL_PT_TMA: 1618 case INTEL_PT_TMA:
1607 case INTEL_PT_CBR:
1608 case INTEL_PT_MODE_TSX: 1619 case INTEL_PT_MODE_TSX:
1609 case INTEL_PT_BAD: 1620 case INTEL_PT_BAD:
1610 case INTEL_PT_PSBEND: 1621 case INTEL_PT_PSBEND:
@@ -1620,6 +1631,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1620 decoder->pkt_step = 0; 1631 decoder->pkt_step = 0;
1621 return -ENOENT; 1632 return -ENOENT;
1622 1633
1634 case INTEL_PT_CBR:
1635 intel_pt_calc_cbr(decoder);
1636 break;
1637
1623 case INTEL_PT_OVF: 1638 case INTEL_PT_OVF:
1624 return intel_pt_overflow(decoder); 1639 return intel_pt_overflow(decoder);
1625 1640
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index fc1752d50019..51c18d67f4ca 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -60,6 +60,14 @@ enum {
60 INTEL_PT_ERR_MAX, 60 INTEL_PT_ERR_MAX,
61}; 61};
62 62
63enum intel_pt_param_flags {
64 /*
65 * FUP packet can contain next linear instruction pointer instead of
66 * current linear instruction pointer.
67 */
68 INTEL_PT_FUP_WITH_NLIP = 1 << 0,
69};
70
63struct intel_pt_state { 71struct intel_pt_state {
64 enum intel_pt_sample_type type; 72 enum intel_pt_sample_type type;
65 int err; 73 int err;
@@ -106,6 +114,7 @@ struct intel_pt_params {
106 unsigned int mtc_period; 114 unsigned int mtc_period;
107 uint32_t tsc_ctc_ratio_n; 115 uint32_t tsc_ctc_ratio_n;
108 uint32_t tsc_ctc_ratio_d; 116 uint32_t tsc_ctc_ratio_d;
117 enum intel_pt_param_flags flags;
109}; 118};
110 119
111struct intel_pt_decoder; 120struct intel_pt_decoder;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index ba4c9dd18643..d426761a549d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -366,7 +366,7 @@ static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf,
366 if (len < offs) 366 if (len < offs)
367 return INTEL_PT_NEED_MORE_BYTES; 367 return INTEL_PT_NEED_MORE_BYTES;
368 byte = buf[offs++]; 368 byte = buf[offs++];
369 payload |= (byte >> 1) << shift; 369 payload |= ((uint64_t)byte >> 1) << shift;
370 } 370 }
371 371
372 packet->type = INTEL_PT_CYC; 372 packet->type = INTEL_PT_CYC;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 492986a25ef6..aec68908d604 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -749,6 +749,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
749 unsigned int queue_nr) 749 unsigned int queue_nr)
750{ 750{
751 struct intel_pt_params params = { .get_trace = 0, }; 751 struct intel_pt_params params = { .get_trace = 0, };
752 struct perf_env *env = pt->machine->env;
752 struct intel_pt_queue *ptq; 753 struct intel_pt_queue *ptq;
753 754
754 ptq = zalloc(sizeof(struct intel_pt_queue)); 755 ptq = zalloc(sizeof(struct intel_pt_queue));
@@ -830,6 +831,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
830 } 831 }
831 } 832 }
832 833
834 if (env->cpuid && !strncmp(env->cpuid, "GenuineIntel,6,92,", 18))
835 params.flags |= INTEL_PT_FUP_WITH_NLIP;
836
833 ptq->decoder = intel_pt_decoder_new(&params); 837 ptq->decoder = intel_pt_decoder_new(&params);
834 if (!ptq->decoder) 838 if (!ptq->decoder)
835 goto out_free; 839 goto out_free;
@@ -1521,6 +1525,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1521 1525
1522 if (intel_pt_is_switch_ip(ptq, state->to_ip)) { 1526 if (intel_pt_is_switch_ip(ptq, state->to_ip)) {
1523 switch (ptq->switch_state) { 1527 switch (ptq->switch_state) {
1528 case INTEL_PT_SS_NOT_TRACING:
1524 case INTEL_PT_SS_UNKNOWN: 1529 case INTEL_PT_SS_UNKNOWN:
1525 case INTEL_PT_SS_EXPECTING_SWITCH_IP: 1530 case INTEL_PT_SS_EXPECTING_SWITCH_IP:
1526 err = intel_pt_next_tid(pt, ptq); 1531 err = intel_pt_next_tid(pt, ptq);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 6ae97eda370b..89ac5b5dc218 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -415,16 +415,20 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
415 return fprintf(fp, "%s", dsoname); 415 return fprintf(fp, "%s", dsoname);
416} 416}
417 417
418char *map__srcline(struct map *map, u64 addr, struct symbol *sym)
419{
420 if (map == NULL)
421 return SRCLINE_UNKNOWN;
422 return get_srcline(map->dso, map__rip_2objdump(map, addr), sym, true, true, addr);
423}
424
418int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, 425int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
419 FILE *fp) 426 FILE *fp)
420{ 427{
421 char *srcline;
422 int ret = 0; 428 int ret = 0;
423 429
424 if (map && map->dso) { 430 if (map && map->dso) {
425 srcline = get_srcline(map->dso, 431 char *srcline = map__srcline(map, addr, NULL);
426 map__rip_2objdump(map, addr), NULL,
427 true, true, addr);
428 if (srcline != SRCLINE_UNKNOWN) 432 if (srcline != SRCLINE_UNKNOWN)
429 ret = fprintf(fp, "%s%s", prefix, srcline); 433 ret = fprintf(fp, "%s%s", prefix, srcline);
430 free_srcline(srcline); 434 free_srcline(srcline);
@@ -445,6 +449,20 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
445 */ 449 */
446u64 map__rip_2objdump(struct map *map, u64 rip) 450u64 map__rip_2objdump(struct map *map, u64 rip)
447{ 451{
452 struct kmap *kmap = __map__kmap(map);
453
454 /*
455 * vmlinux does not have program headers for PTI entry trampolines and
456 * kcore may not either. However the trampoline object code is on the
457 * main kernel map, so just use that instead.
458 */
459 if (kmap && is_entry_trampoline(kmap->name) && kmap->kmaps && kmap->kmaps->machine) {
460 struct map *kernel_map = machine__kernel_map(kmap->kmaps->machine);
461
462 if (kernel_map)
463 map = kernel_map;
464 }
465
448 if (!map->dso->adjust_symbols) 466 if (!map->dso->adjust_symbols)
449 return rip; 467 return rip;
450 468
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 97e2a063bd65..4cb90f242bed 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -169,6 +169,7 @@ static inline void __map__zput(struct map **map)
169int map__overlap(struct map *l, struct map *r); 169int map__overlap(struct map *l, struct map *r);
170size_t map__fprintf(struct map *map, FILE *fp); 170size_t map__fprintf(struct map *map, FILE *fp);
171size_t map__fprintf_dsoname(struct map *map, FILE *fp); 171size_t map__fprintf_dsoname(struct map *map, FILE *fp);
172char *map__srcline(struct map *map, u64 addr, struct symbol *sym);
172int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, 173int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
173 FILE *fp); 174 FILE *fp);
174 175
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index a1a01b1ac8b8..5f761f3ed0f3 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,7 +53,21 @@ static int str(yyscan_t scanner, int token)
53 YYSTYPE *yylval = parse_events_get_lval(scanner); 53 YYSTYPE *yylval = parse_events_get_lval(scanner);
54 char *text = parse_events_get_text(scanner); 54 char *text = parse_events_get_text(scanner);
55 55
56 yylval->str = strdup(text); 56 if (text[0] != '\'') {
57 yylval->str = strdup(text);
58 } else {
59 /*
60 * If a text tag specified on the command line
61 * contains opening single quite ' then it is
62 * expected that the tag ends with single quote
63 * as well, like this:
64 * name=\'CPU_CLK_UNHALTED.THREAD:cmask=1\'
65 * quotes need to be escaped to bypass shell
66 * processing.
67 */
68 yylval->str = strndup(&text[1], strlen(text) - 2);
69 }
70
57 return token; 71 return token;
58} 72}
59 73
@@ -176,6 +190,7 @@ num_dec [0-9]+
176num_hex 0x[a-fA-F0-9]+ 190num_hex 0x[a-fA-F0-9]+
177num_raw_hex [a-fA-F0-9]+ 191num_raw_hex [a-fA-F0-9]+
178name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]]* 192name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]]*
193name_tag [\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\']
179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 194name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 195drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
181/* If you add a modifier you need to update check_modifier() */ 196/* If you add a modifier you need to update check_modifier() */
@@ -344,6 +359,7 @@ r{num_raw_hex} { return raw(yyscanner); }
344{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } 359{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); }
345{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } 360{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); }
346{name} { return pmu_str_check(yyscanner); } 361{name} { return pmu_str_check(yyscanner); }
362{name_tag} { return str(yyscanner, PE_NAME); }
347"/" { BEGIN(config); return '/'; } 363"/" { BEGIN(config); return '/'; }
348- { return '-'; } 364- { return '-'; }
349, { BEGIN(event); return ','; } 365, { BEGIN(event); return ','; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index e37608a87dba..da8fe57691b8 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -73,6 +73,7 @@ static void inc_group_count(struct list_head *list,
73%type <num> value_sym 73%type <num> value_sym
74%type <head> event_config 74%type <head> event_config
75%type <head> opt_event_config 75%type <head> opt_event_config
76%type <head> opt_pmu_config
76%type <term> event_term 77%type <term> event_term
77%type <head> event_pmu 78%type <head> event_pmu
78%type <head> event_legacy_symbol 79%type <head> event_legacy_symbol
@@ -224,13 +225,18 @@ event_def: event_pmu |
224 event_bpf_file 225 event_bpf_file
225 226
226event_pmu: 227event_pmu:
227PE_NAME opt_event_config 228PE_NAME opt_pmu_config
228{ 229{
230 struct parse_events_state *parse_state = _parse_state;
231 struct parse_events_error *error = parse_state->error;
229 struct list_head *list, *orig_terms, *terms; 232 struct list_head *list, *orig_terms, *terms;
230 233
231 if (parse_events_copy_term_list($2, &orig_terms)) 234 if (parse_events_copy_term_list($2, &orig_terms))
232 YYABORT; 235 YYABORT;
233 236
237 if (error)
238 error->idx = @1.first_column;
239
234 ALLOC_LIST(list); 240 ALLOC_LIST(list);
235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) { 241 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) {
236 struct perf_pmu *pmu = NULL; 242 struct perf_pmu *pmu = NULL;
@@ -496,6 +502,17 @@ opt_event_config:
496 $$ = NULL; 502 $$ = NULL;
497} 503}
498 504
505opt_pmu_config:
506'/' event_config '/'
507{
508 $$ = $2;
509}
510|
511'/' '/'
512{
513 $$ = NULL;
514}
515
499start_terms: event_config 516start_terms: event_config
500{ 517{
501 struct parse_events_state *parse_state = _parse_state; 518 struct parse_events_state *parse_state = _parse_state;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d2fb597c9a8c..3ba6a1742f91 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -234,6 +234,74 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
234 return 0; 234 return 0;
235} 235}
236 236
237static void perf_pmu_assign_str(char *name, const char *field, char **old_str,
238 char **new_str)
239{
240 if (!*old_str)
241 goto set_new;
242
243 if (*new_str) { /* Have new string, check with old */
244 if (strcasecmp(*old_str, *new_str))
245 pr_debug("alias %s differs in field '%s'\n",
246 name, field);
247 zfree(old_str);
248 } else /* Nothing new --> keep old string */
249 return;
250set_new:
251 *old_str = *new_str;
252 *new_str = NULL;
253}
254
255static void perf_pmu_update_alias(struct perf_pmu_alias *old,
256 struct perf_pmu_alias *newalias)
257{
258 perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc);
259 perf_pmu_assign_str(old->name, "long_desc", &old->long_desc,
260 &newalias->long_desc);
261 perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic);
262 perf_pmu_assign_str(old->name, "metric_expr", &old->metric_expr,
263 &newalias->metric_expr);
264 perf_pmu_assign_str(old->name, "metric_name", &old->metric_name,
265 &newalias->metric_name);
266 perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str);
267 old->scale = newalias->scale;
268 old->per_pkg = newalias->per_pkg;
269 old->snapshot = newalias->snapshot;
270 memcpy(old->unit, newalias->unit, sizeof(old->unit));
271}
272
273/* Delete an alias entry. */
274static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
275{
276 zfree(&newalias->name);
277 zfree(&newalias->desc);
278 zfree(&newalias->long_desc);
279 zfree(&newalias->topic);
280 zfree(&newalias->str);
281 zfree(&newalias->metric_expr);
282 zfree(&newalias->metric_name);
283 parse_events_terms__purge(&newalias->terms);
284 free(newalias);
285}
286
287/* Merge an alias, search in alias list. If this name is already
288 * present merge both of them to combine all information.
289 */
290static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias,
291 struct list_head *alist)
292{
293 struct perf_pmu_alias *a;
294
295 list_for_each_entry(a, alist, list) {
296 if (!strcasecmp(newalias->name, a->name)) {
297 perf_pmu_update_alias(a, newalias);
298 perf_pmu_free_alias(newalias);
299 return true;
300 }
301 }
302 return false;
303}
304
237static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 305static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
238 char *desc, char *val, 306 char *desc, char *val,
239 char *long_desc, char *topic, 307 char *long_desc, char *topic,
@@ -241,9 +309,11 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
241 char *metric_expr, 309 char *metric_expr,
242 char *metric_name) 310 char *metric_name)
243{ 311{
312 struct parse_events_term *term;
244 struct perf_pmu_alias *alias; 313 struct perf_pmu_alias *alias;
245 int ret; 314 int ret;
246 int num; 315 int num;
316 char newval[256];
247 317
248 alias = malloc(sizeof(*alias)); 318 alias = malloc(sizeof(*alias));
249 if (!alias) 319 if (!alias)
@@ -262,6 +332,27 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
262 return ret; 332 return ret;
263 } 333 }
264 334
335 /* Scan event and remove leading zeroes, spaces, newlines, some
336 * platforms have terms specified as
337 * event=0x0091 (read from files ../<PMU>/events/<FILE>
338 * and terms specified as event=0x91 (read from JSON files).
339 *
340 * Rebuild string to make alias->str member comparable.
341 */
342 memset(newval, 0, sizeof(newval));
343 ret = 0;
344 list_for_each_entry(term, &alias->terms, list) {
345 if (ret)
346 ret += scnprintf(newval + ret, sizeof(newval) - ret,
347 ",");
348 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
349 ret += scnprintf(newval + ret, sizeof(newval) - ret,
350 "%s=%#x", term->config, term->val.num);
351 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
352 ret += scnprintf(newval + ret, sizeof(newval) - ret,
353 "%s=%s", term->config, term->val.str);
354 }
355
265 alias->name = strdup(name); 356 alias->name = strdup(name);
266 if (dir) { 357 if (dir) {
267 /* 358 /*
@@ -285,9 +376,10 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
285 snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 376 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
286 } 377 }
287 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1; 378 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
288 alias->str = strdup(val); 379 alias->str = strdup(newval);
289 380
290 list_add_tail(&alias->list, list); 381 if (!perf_pmu_merge_alias(alias, list))
382 list_add_tail(&alias->list, list);
291 383
292 return 0; 384 return 0;
293} 385}
@@ -303,6 +395,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
303 395
304 buf[ret] = 0; 396 buf[ret] = 0;
305 397
398 /* Remove trailing newline from sysfs file */
399 rtrim(buf);
400
306 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, 401 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
307 NULL, NULL, NULL); 402 NULL, NULL, NULL);
308} 403}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3094f11e7d81..f119eb628dbb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -165,8 +165,7 @@ static struct map *kernel_get_module_map(const char *module)
165 if (strncmp(pos->dso->short_name + 1, module, 165 if (strncmp(pos->dso->short_name + 1, module,
166 pos->dso->short_name_len - 2) == 0 && 166 pos->dso->short_name_len - 2) == 0 &&
167 module[pos->dso->short_name_len - 2] == '\0') { 167 module[pos->dso->short_name_len - 2] == '\0') {
168 map__get(pos); 168 return map__get(pos);
169 return pos;
170 } 169 }
171 } 170 }
172 return NULL; 171 return NULL;
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
deleted file mode 100644
index 22eaa201aa27..000000000000
--- a/tools/perf/util/quote.c
+++ /dev/null
@@ -1,62 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <errno.h>
3#include <stdlib.h>
4#include "strbuf.h"
5#include "quote.h"
6#include "util.h"
7
8/* Help to copy the thing properly quoted for the shell safety.
9 * any single quote is replaced with '\'', any exclamation point
10 * is replaced with '\!', and the whole thing is enclosed in a
11 *
12 * E.g.
13 * original sq_quote result
14 * name ==> name ==> 'name'
15 * a b ==> a b ==> 'a b'
16 * a'b ==> a'\''b ==> 'a'\''b'
17 * a!b ==> a'\!'b ==> 'a'\!'b'
18 */
19static inline int need_bs_quote(char c)
20{
21 return (c == '\'' || c == '!');
22}
23
24static int sq_quote_buf(struct strbuf *dst, const char *src)
25{
26 char *to_free = NULL;
27 int ret;
28
29 if (dst->buf == src)
30 to_free = strbuf_detach(dst, NULL);
31
32 ret = strbuf_addch(dst, '\'');
33 while (!ret && *src) {
34 size_t len = strcspn(src, "'!");
35 ret = strbuf_add(dst, src, len);
36 src += len;
37 while (!ret && need_bs_quote(*src))
38 ret = strbuf_addf(dst, "'\\%c\'", *src++);
39 }
40 if (!ret)
41 ret = strbuf_addch(dst, '\'');
42 free(to_free);
43
44 return ret;
45}
46
47int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
48{
49 int i, ret;
50
51 /* Copy into destination buffer. */
52 ret = strbuf_grow(dst, 255);
53 for (i = 0; !ret && argv[i]; ++i) {
54 ret = strbuf_addch(dst, ' ');
55 if (ret)
56 break;
57 ret = sq_quote_buf(dst, argv[i]);
58 if (maxlen && dst->len > maxlen)
59 return -ENOSPC;
60 }
61 return ret;
62}
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
deleted file mode 100644
index 274bf26d3511..000000000000
--- a/tools/perf/util/quote.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __PERF_QUOTE_H
3#define __PERF_QUOTE_H
4
5#include <stddef.h>
6
7/* Help to copy the thing properly quoted for the shell safety.
8 * any single quote is replaced with '\'', any exclamation point
9 * is replaced with '\!', and the whole thing is enclosed in a
10 * single quote pair.
11 *
12 * For example, if you are passing the result to system() as an
13 * argument:
14 *
15 * sprintf(cmd, "foobar %s %s", sq_quote(arg0), sq_quote(arg1))
16 *
17 * would be appropriate. If the system() is going to call ssh to
18 * run the command on the other side:
19 *
20 * sprintf(cmd, "git-diff-tree %s %s", sq_quote(arg0), sq_quote(arg1));
21 * sprintf(rcmd, "ssh %s %s", sq_util/quote.host), sq_quote(cmd));
22 *
23 * Note that the above examples leak memory! Remember to free result from
24 * sq_quote() in a real application.
25 */
26
27struct strbuf;
28
29int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
30
31#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 7f8afacd08ee..46e9e19ab1ac 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -48,6 +48,7 @@
48#include "cpumap.h" 48#include "cpumap.h"
49#include "print_binary.h" 49#include "print_binary.h"
50#include "stat.h" 50#include "stat.h"
51#include "mem-events.h"
51 52
52#if PY_MAJOR_VERSION < 3 53#if PY_MAJOR_VERSION < 3
53#define _PyUnicode_FromString(arg) \ 54#define _PyUnicode_FromString(arg) \
@@ -372,6 +373,19 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
372 return obj; 373 return obj;
373} 374}
374 375
376static const char *get_dsoname(struct map *map)
377{
378 const char *dsoname = "[unknown]";
379
380 if (map && map->dso) {
381 if (symbol_conf.show_kernel_path && map->dso->long_name)
382 dsoname = map->dso->long_name;
383 else
384 dsoname = map->dso->name;
385 }
386
387 return dsoname;
388}
375 389
376static PyObject *python_process_callchain(struct perf_sample *sample, 390static PyObject *python_process_callchain(struct perf_sample *sample,
377 struct perf_evsel *evsel, 391 struct perf_evsel *evsel,
@@ -427,14 +441,8 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
427 } 441 }
428 442
429 if (node->map) { 443 if (node->map) {
430 struct map *map = node->map; 444 const char *dsoname = get_dsoname(node->map);
431 const char *dsoname = "[unknown]"; 445
432 if (map && map->dso) {
433 if (symbol_conf.show_kernel_path && map->dso->long_name)
434 dsoname = map->dso->long_name;
435 else
436 dsoname = map->dso->name;
437 }
438 pydict_set_item_string_decref(pyelem, "dso", 446 pydict_set_item_string_decref(pyelem, "dso",
439 _PyUnicode_FromString(dsoname)); 447 _PyUnicode_FromString(dsoname));
440 } 448 }
@@ -448,6 +456,166 @@ exit:
448 return pylist; 456 return pylist;
449} 457}
450 458
459static PyObject *python_process_brstack(struct perf_sample *sample,
460 struct thread *thread)
461{
462 struct branch_stack *br = sample->branch_stack;
463 PyObject *pylist;
464 u64 i;
465
466 pylist = PyList_New(0);
467 if (!pylist)
468 Py_FatalError("couldn't create Python list");
469
470 if (!(br && br->nr))
471 goto exit;
472
473 for (i = 0; i < br->nr; i++) {
474 PyObject *pyelem;
475 struct addr_location al;
476 const char *dsoname;
477
478 pyelem = PyDict_New();
479 if (!pyelem)
480 Py_FatalError("couldn't create Python dictionary");
481
482 pydict_set_item_string_decref(pyelem, "from",
483 PyLong_FromUnsignedLongLong(br->entries[i].from));
484 pydict_set_item_string_decref(pyelem, "to",
485 PyLong_FromUnsignedLongLong(br->entries[i].to));
486 pydict_set_item_string_decref(pyelem, "mispred",
487 PyBool_FromLong(br->entries[i].flags.mispred));
488 pydict_set_item_string_decref(pyelem, "predicted",
489 PyBool_FromLong(br->entries[i].flags.predicted));
490 pydict_set_item_string_decref(pyelem, "in_tx",
491 PyBool_FromLong(br->entries[i].flags.in_tx));
492 pydict_set_item_string_decref(pyelem, "abort",
493 PyBool_FromLong(br->entries[i].flags.abort));
494 pydict_set_item_string_decref(pyelem, "cycles",
495 PyLong_FromUnsignedLongLong(br->entries[i].flags.cycles));
496
497 thread__find_map(thread, sample->cpumode,
498 br->entries[i].from, &al);
499 dsoname = get_dsoname(al.map);
500 pydict_set_item_string_decref(pyelem, "from_dsoname",
501 _PyUnicode_FromString(dsoname));
502
503 thread__find_map(thread, sample->cpumode,
504 br->entries[i].to, &al);
505 dsoname = get_dsoname(al.map);
506 pydict_set_item_string_decref(pyelem, "to_dsoname",
507 _PyUnicode_FromString(dsoname));
508
509 PyList_Append(pylist, pyelem);
510 Py_DECREF(pyelem);
511 }
512
513exit:
514 return pylist;
515}
516
517static unsigned long get_offset(struct symbol *sym, struct addr_location *al)
518{
519 unsigned long offset;
520
521 if (al->addr < sym->end)
522 offset = al->addr - sym->start;
523 else
524 offset = al->addr - al->map->start - sym->start;
525
526 return offset;
527}
528
529static int get_symoff(struct symbol *sym, struct addr_location *al,
530 bool print_off, char *bf, int size)
531{
532 unsigned long offset;
533
534 if (!sym || !sym->name[0])
535 return scnprintf(bf, size, "%s", "[unknown]");
536
537 if (!print_off)
538 return scnprintf(bf, size, "%s", sym->name);
539
540 offset = get_offset(sym, al);
541
542 return scnprintf(bf, size, "%s+0x%x", sym->name, offset);
543}
544
545static int get_br_mspred(struct branch_flags *flags, char *bf, int size)
546{
547 if (!flags->mispred && !flags->predicted)
548 return scnprintf(bf, size, "%s", "-");
549
550 if (flags->mispred)
551 return scnprintf(bf, size, "%s", "M");
552
553 return scnprintf(bf, size, "%s", "P");
554}
555
556static PyObject *python_process_brstacksym(struct perf_sample *sample,
557 struct thread *thread)
558{
559 struct branch_stack *br = sample->branch_stack;
560 PyObject *pylist;
561 u64 i;
562 char bf[512];
563 struct addr_location al;
564
565 pylist = PyList_New(0);
566 if (!pylist)
567 Py_FatalError("couldn't create Python list");
568
569 if (!(br && br->nr))
570 goto exit;
571
572 for (i = 0; i < br->nr; i++) {
573 PyObject *pyelem;
574
575 pyelem = PyDict_New();
576 if (!pyelem)
577 Py_FatalError("couldn't create Python dictionary");
578
579 thread__find_symbol(thread, sample->cpumode,
580 br->entries[i].from, &al);
581 get_symoff(al.sym, &al, true, bf, sizeof(bf));
582 pydict_set_item_string_decref(pyelem, "from",
583 _PyUnicode_FromString(bf));
584
585 thread__find_symbol(thread, sample->cpumode,
586 br->entries[i].to, &al);
587 get_symoff(al.sym, &al, true, bf, sizeof(bf));
588 pydict_set_item_string_decref(pyelem, "to",
589 _PyUnicode_FromString(bf));
590
591 get_br_mspred(&br->entries[i].flags, bf, sizeof(bf));
592 pydict_set_item_string_decref(pyelem, "pred",
593 _PyUnicode_FromString(bf));
594
595 if (br->entries[i].flags.in_tx) {
596 pydict_set_item_string_decref(pyelem, "in_tx",
597 _PyUnicode_FromString("X"));
598 } else {
599 pydict_set_item_string_decref(pyelem, "in_tx",
600 _PyUnicode_FromString("-"));
601 }
602
603 if (br->entries[i].flags.abort) {
604 pydict_set_item_string_decref(pyelem, "abort",
605 _PyUnicode_FromString("A"));
606 } else {
607 pydict_set_item_string_decref(pyelem, "abort",
608 _PyUnicode_FromString("-"));
609 }
610
611 PyList_Append(pylist, pyelem);
612 Py_DECREF(pyelem);
613 }
614
615exit:
616 return pylist;
617}
618
451static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) 619static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
452{ 620{
453 PyObject *t; 621 PyObject *t;
@@ -498,12 +666,63 @@ static void set_sample_read_in_dict(PyObject *dict_sample,
498 pydict_set_item_string_decref(dict_sample, "values", values); 666 pydict_set_item_string_decref(dict_sample, "values", values);
499} 667}
500 668
669static void set_sample_datasrc_in_dict(PyObject *dict,
670 struct perf_sample *sample)
671{
672 struct mem_info mi = { .data_src.val = sample->data_src };
673 char decode[100];
674
675 pydict_set_item_string_decref(dict, "datasrc",
676 PyLong_FromUnsignedLongLong(sample->data_src));
677
678 perf_script__meminfo_scnprintf(decode, 100, &mi);
679
680 pydict_set_item_string_decref(dict, "datasrc_decode",
681 _PyUnicode_FromString(decode));
682}
683
684static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size)
685{
686 unsigned int i = 0, r;
687 int printed = 0;
688
689 bf[0] = 0;
690
691 for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
692 u64 val = regs->regs[i++];
693
694 printed += scnprintf(bf + printed, size - printed,
695 "%5s:0x%" PRIx64 " ",
696 perf_reg_name(r), val);
697 }
698
699 return printed;
700}
701
702static void set_regs_in_dict(PyObject *dict,
703 struct perf_sample *sample,
704 struct perf_evsel *evsel)
705{
706 struct perf_event_attr *attr = &evsel->attr;
707 char bf[512];
708
709 regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf));
710
711 pydict_set_item_string_decref(dict, "iregs",
712 _PyUnicode_FromString(bf));
713
714 regs_map(&sample->user_regs, attr->sample_regs_user, bf, sizeof(bf));
715
716 pydict_set_item_string_decref(dict, "uregs",
717 _PyUnicode_FromString(bf));
718}
719
501static PyObject *get_perf_sample_dict(struct perf_sample *sample, 720static PyObject *get_perf_sample_dict(struct perf_sample *sample,
502 struct perf_evsel *evsel, 721 struct perf_evsel *evsel,
503 struct addr_location *al, 722 struct addr_location *al,
504 PyObject *callchain) 723 PyObject *callchain)
505{ 724{
506 PyObject *dict, *dict_sample; 725 PyObject *dict, *dict_sample, *brstack, *brstacksym;
507 726
508 dict = PyDict_New(); 727 dict = PyDict_New();
509 if (!dict) 728 if (!dict)
@@ -534,6 +753,11 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
534 pydict_set_item_string_decref(dict_sample, "addr", 753 pydict_set_item_string_decref(dict_sample, "addr",
535 PyLong_FromUnsignedLongLong(sample->addr)); 754 PyLong_FromUnsignedLongLong(sample->addr));
536 set_sample_read_in_dict(dict_sample, sample, evsel); 755 set_sample_read_in_dict(dict_sample, sample, evsel);
756 pydict_set_item_string_decref(dict_sample, "weight",
757 PyLong_FromUnsignedLongLong(sample->weight));
758 pydict_set_item_string_decref(dict_sample, "transaction",
759 PyLong_FromUnsignedLongLong(sample->transaction));
760 set_sample_datasrc_in_dict(dict_sample, sample);
537 pydict_set_item_string_decref(dict, "sample", dict_sample); 761 pydict_set_item_string_decref(dict, "sample", dict_sample);
538 762
539 pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( 763 pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize(
@@ -551,6 +775,14 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
551 775
552 pydict_set_item_string_decref(dict, "callchain", callchain); 776 pydict_set_item_string_decref(dict, "callchain", callchain);
553 777
778 brstack = python_process_brstack(sample, al->thread);
779 pydict_set_item_string_decref(dict, "brstack", brstack);
780
781 brstacksym = python_process_brstacksym(sample, al->thread);
782 pydict_set_item_string_decref(dict, "brstacksym", brstacksym);
783
784 set_regs_in_dict(dict, sample, evsel);
785
554 return dict; 786 return dict;
555} 787}
556 788
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b998bb475589..8b9369303561 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1094,7 +1094,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1094 1094
1095 sample_type = evsel->attr.sample_type; 1095 sample_type = evsel->attr.sample_type;
1096 1096
1097 if (sample_type & PERF_SAMPLE_CALLCHAIN) 1097 if (evsel__has_callchain(evsel))
1098 callchain__printf(evsel, sample); 1098 callchain__printf(evsel, sample);
1099 1099
1100 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel)) 1100 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 4058ade352a5..fed2952ab45a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -331,24 +331,18 @@ struct sort_entry sort_sym = {
331 331
332/* --sort srcline */ 332/* --sort srcline */
333 333
334char *hist_entry__get_srcline(struct hist_entry *he) 334char *hist_entry__srcline(struct hist_entry *he)
335{ 335{
336 struct map *map = he->ms.map; 336 return map__srcline(he->ms.map, he->ip, he->ms.sym);
337
338 if (!map)
339 return SRCLINE_UNKNOWN;
340
341 return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
342 he->ms.sym, true, true, he->ip);
343} 337}
344 338
345static int64_t 339static int64_t
346sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) 340sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
347{ 341{
348 if (!left->srcline) 342 if (!left->srcline)
349 left->srcline = hist_entry__get_srcline(left); 343 left->srcline = hist_entry__srcline(left);
350 if (!right->srcline) 344 if (!right->srcline)
351 right->srcline = hist_entry__get_srcline(right); 345 right->srcline = hist_entry__srcline(right);
352 346
353 return strcmp(right->srcline, left->srcline); 347 return strcmp(right->srcline, left->srcline);
354} 348}
@@ -357,7 +351,7 @@ static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
357 size_t size, unsigned int width) 351 size_t size, unsigned int width)
358{ 352{
359 if (!he->srcline) 353 if (!he->srcline)
360 he->srcline = hist_entry__get_srcline(he); 354 he->srcline = hist_entry__srcline(he);
361 355
362 return repsep_snprintf(bf, size, "%-.*s", width, he->srcline); 356 return repsep_snprintf(bf, size, "%-.*s", width, he->srcline);
363} 357}
@@ -371,33 +365,20 @@ struct sort_entry sort_srcline = {
371 365
372/* --sort srcline_from */ 366/* --sort srcline_from */
373 367
368static char *addr_map_symbol__srcline(struct addr_map_symbol *ams)
369{
370 return map__srcline(ams->map, ams->al_addr, ams->sym);
371}
372
374static int64_t 373static int64_t
375sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) 374sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
376{ 375{
377 if (!left->branch_info->srcline_from) { 376 if (!left->branch_info->srcline_from)
378 struct map *map = left->branch_info->from.map; 377 left->branch_info->srcline_from = addr_map_symbol__srcline(&left->branch_info->from);
379 if (!map) 378
380 left->branch_info->srcline_from = SRCLINE_UNKNOWN; 379 if (!right->branch_info->srcline_from)
381 else 380 right->branch_info->srcline_from = addr_map_symbol__srcline(&right->branch_info->from);
382 left->branch_info->srcline_from = get_srcline(map->dso, 381
383 map__rip_2objdump(map,
384 left->branch_info->from.al_addr),
385 left->branch_info->from.sym,
386 true, true,
387 left->branch_info->from.al_addr);
388 }
389 if (!right->branch_info->srcline_from) {
390 struct map *map = right->branch_info->from.map;
391 if (!map)
392 right->branch_info->srcline_from = SRCLINE_UNKNOWN;
393 else
394 right->branch_info->srcline_from = get_srcline(map->dso,
395 map__rip_2objdump(map,
396 right->branch_info->from.al_addr),
397 right->branch_info->from.sym,
398 true, true,
399 right->branch_info->from.al_addr);
400 }
401 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); 382 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
402} 383}
403 384
@@ -419,30 +400,12 @@ struct sort_entry sort_srcline_from = {
419static int64_t 400static int64_t
420sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) 401sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
421{ 402{
422 if (!left->branch_info->srcline_to) { 403 if (!left->branch_info->srcline_to)
423 struct map *map = left->branch_info->to.map; 404 left->branch_info->srcline_to = addr_map_symbol__srcline(&left->branch_info->to);
424 if (!map) 405
425 left->branch_info->srcline_to = SRCLINE_UNKNOWN; 406 if (!right->branch_info->srcline_to)
426 else 407 right->branch_info->srcline_to = addr_map_symbol__srcline(&right->branch_info->to);
427 left->branch_info->srcline_to = get_srcline(map->dso, 408
428 map__rip_2objdump(map,
429 left->branch_info->to.al_addr),
430 left->branch_info->from.sym,
431 true, true,
432 left->branch_info->to.al_addr);
433 }
434 if (!right->branch_info->srcline_to) {
435 struct map *map = right->branch_info->to.map;
436 if (!map)
437 right->branch_info->srcline_to = SRCLINE_UNKNOWN;
438 else
439 right->branch_info->srcline_to = get_srcline(map->dso,
440 map__rip_2objdump(map,
441 right->branch_info->to.al_addr),
442 right->branch_info->to.sym,
443 true, true,
444 right->branch_info->to.al_addr);
445 }
446 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); 409 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
447} 410}
448 411
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 9e6896293bbd..8bf302cafcec 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -112,6 +112,8 @@ struct hist_entry {
112 112
113 char level; 113 char level;
114 u8 filtered; 114 u8 filtered;
115
116 u16 callchain_size;
115 union { 117 union {
116 /* 118 /*
117 * Since perf diff only supports the stdio output, TUI 119 * Since perf diff only supports the stdio output, TUI
@@ -151,6 +153,11 @@ struct hist_entry {
151 struct callchain_root callchain[0]; /* must be last member */ 153 struct callchain_root callchain[0]; /* must be last member */
152}; 154};
153 155
156static __pure inline bool hist_entry__has_callchains(struct hist_entry *he)
157{
158 return he->callchain_size != 0;
159}
160
154static inline bool hist_entry__has_pairs(struct hist_entry *he) 161static inline bool hist_entry__has_pairs(struct hist_entry *he)
155{ 162{
156 return !list_empty(&he->pairs.node); 163 return !list_empty(&he->pairs.node);
@@ -292,5 +299,5 @@ int64_t
292sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right); 299sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right);
293int64_t 300int64_t
294sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right); 301sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right);
295char *hist_entry__get_srcline(struct hist_entry *he); 302char *hist_entry__srcline(struct hist_entry *he);
296#endif /* __PERF_SORT_H */ 303#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8c84437f2a10..d188b7588152 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -40,7 +40,6 @@ char **vmlinux_path;
40struct symbol_conf symbol_conf = { 40struct symbol_conf symbol_conf = {
41 .use_modules = true, 41 .use_modules = true,
42 .try_vmlinux_path = true, 42 .try_vmlinux_path = true,
43 .annotate_src = true,
44 .demangle = true, 43 .demangle = true,
45 .demangle_kernel = false, 44 .demangle_kernel = false,
46 .cumulate_callchain = true, 45 .cumulate_callchain = true,
@@ -74,7 +73,7 @@ static enum dso_binary_type binary_type_symtab[] = {
74static bool symbol_type__filter(char symbol_type) 73static bool symbol_type__filter(char symbol_type)
75{ 74{
76 symbol_type = toupper(symbol_type); 75 symbol_type = toupper(symbol_type);
77 return symbol_type == 'T' || symbol_type == 'W' || symbol_type == 'D'; 76 return symbol_type == 'T' || symbol_type == 'W' || symbol_type == 'D' || symbol_type == 'B';
78} 77}
79 78
80static int prefix_underscores_count(const char *str) 79static int prefix_underscores_count(const char *str)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 1a16438eb3ce..f25fae4b5743 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -90,7 +90,6 @@ struct intlist;
90 90
91struct symbol_conf { 91struct symbol_conf {
92 unsigned short priv_size; 92 unsigned short priv_size;
93 unsigned short nr_events;
94 bool try_vmlinux_path, 93 bool try_vmlinux_path,
95 init_annotation, 94 init_annotation,
96 force, 95 force,
@@ -109,8 +108,6 @@ struct symbol_conf {
109 show_cpu_utilization, 108 show_cpu_utilization,
110 initialized, 109 initialized,
111 kptr_restrict, 110 kptr_restrict,
112 annotate_asm_raw,
113 annotate_src,
114 event_group, 111 event_group,
115 demangle, 112 demangle,
116 demangle_kernel, 113 demangle_kernel,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 9892323cdd7c..9add1f72ce95 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -3,6 +3,7 @@
3#define __PERF_TOP_H 1 3#define __PERF_TOP_H 1
4 4
5#include "tool.h" 5#include "tool.h"
6#include "annotate.h"
6#include <linux/types.h> 7#include <linux/types.h>
7#include <stddef.h> 8#include <stddef.h>
8#include <stdbool.h> 9#include <stdbool.h>
@@ -16,6 +17,7 @@ struct perf_top {
16 struct perf_tool tool; 17 struct perf_tool tool;
17 struct perf_evlist *evlist; 18 struct perf_evlist *evlist;
18 struct record_opts record_opts; 19 struct record_opts record_opts;
20 struct annotation_options annotation_opts;
19 /* 21 /*
20 * Symbols will be added here in perf_event__process_sample and will 22 * Symbols will be added here in perf_event__process_sample and will
21 * get out after decayed. 23 * get out after decayed.
@@ -35,7 +37,6 @@ struct perf_top {
35 struct perf_session *session; 37 struct perf_session *session;
36 struct winsize winsize; 38 struct winsize winsize;
37 int realtime_prio; 39 int realtime_prio;
38 int sym_pcnt_filter;
39 const char *sym_filter; 40 const char *sym_filter;
40 float min_percent; 41 float min_percent;
41 unsigned int nr_threads_synthesize; 42 unsigned int nr_threads_synthesize;