aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 12:04:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 12:04:00 -0400
commit2322d6c5c7b5e4684a8bd26081568404e5b3ba39 (patch)
tree5e3d0be68b024846a06a9420d89a670b1a08a3a7
parent9f3fbe852a510fbc0782f71e3b767418ed809cf4 (diff)
parent2696ec4566f598ab483a6bebc4ec841b2efb88ec (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull more perf tooling updates from Thomas Gleixner: "Perf tool updates and fixes: perf stat: - Display user and system time for workload targets (Jiri Olsa) perf record: - Enable arbitrary event names thru name= modifier (Alexey Budankov) PowerPC: - Add a python script for hypervisor call statistics (Ravi Bangoria) Intel PT: (Adrian Hunter) - Fix sync_switch INTEL_PT_SS_NOT_TRACING - Fix decoding to accept CBR between FUP and corresponding TIP - Fix MTC timing after overflow - Fix "Unexpected indirect branch" error perf test: - record+probe_libc_inet_pton: - To get the symbol table for dynamic shared objects on ubuntu we need to pass the -D/--dynamic command line option, unlike with the fedora distros (Arnaldo Carvalho de Melo) - code-reading: - Fix perf_env setup for PTI entry trampolines (Adrian Hunter) - kmod-path: - Add tests for vdso32 and vdsox32 (Adrian Hunter) - Use header file util/debug.h (Thomas Richter) perf annotate: - Make the various UI backends (stdio, TUI, gtk) use more consistently structs with annotation options as specified by the user (Arnaldo Carvalho de Melo) - Move annotation specific knobs from the symbol_conf global kitchen sink to the annotation option structs (Arnaldo Carvalho de Melo) perf script: - Add more PMU fields to python scripts event handler dict (Jin Yao) Core: - Fix misleading error for some unparsable events mentioning PMUs when those are not involved in the problem (Jiri Olsa) - Consider BSS symbols when processing /proc/kallsyms ('B' and 'b') (Arnaldo Carvalho de Melo) - Be more robust when trying to use per-symbol histograms, checking for unlikely but possible cases where the space for the histograms wasn't allocated, print a debug message for such cases (Arnaldo Carvalho de Melo) - Fix symbol and object code resolution for vdso32 and vdsox32 (Adrian Hunter) - No need to check for null when passing pointers to foo__get() style refcount grabbing helpers, just like in the kernel and with free(), its safe to pass a NULL pointer to avoid having to check it before each and every foo__get() call (Arnaldo Carvalho de Melo) - Remove some dead code (quote.[ch]) (Arnaldo Carvalho de Melo) - Remove some needless globals, making them local (Arnaldo Carvalho de Melo) - Reduce usage of symbol_conf.use_callchain, using other means of finding out if callchains are in use or available for specific events, as we evolved this codebase to allow requesting callchains for just a subset of the monitored events. In time it will help polish recording and showing mixed sets accross the various tools: perf record -e cycles/call-graph=fp/,cache-misses/call-graph=dwarf/,instructions' (Arnaldo Carvalho de Melo) - Consider PTI entry trampolines in map__rip_2objdump() (Adrian Hunter)" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (50 commits) perf script python: Add dict fields introduction to Documentation perf script python: Add more PMU fields to event handler dict perf script python: Move dsoname code to a new function perf symbols: Add BSS symbols when reading from /proc/kallsyms perf annnotate: Make __symbol__inc_addr_samples handle src->histograms == NULL perf intel-pt: Fix "Unexpected indirect branch" error perf intel-pt: Fix MTC timing after overflow perf intel-pt: Fix decoding to accept CBR between FUP and corresponding TIP perf intel-pt: Fix sync_switch INTEL_PT_SS_NOT_TRACING perf script powerpc: Python script for hypervisor call statistics perf test record+probe_libc_inet_pton: Ask 'nm' for dynamic symbols perf map: Consider PTI entry trampolines in rip_2objdump() perf test code-reading: Fix perf_env setup for PTI entry trampolines perf tools: Fix pmu events parsing rule perf stat: Display user and system time perf record: Enable arbitrary event names thru name= modifier perf tools: Fix symbol and object code resolution for vdso32 and vdsox32 perf tests kmod-path: Add tests for vdso32 and vdsox32 perf hists: Check if a hist_entry has callchains before using them perf hists: Introduce hist_entry__has_callchain() method ...
-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.txt40
-rw-r--r--tools/perf/arch/common.c4
-rw-r--r--tools/perf/arch/common.h4
-rw-r--r--tools/perf/builtin-annotate.c36
-rw-r--r--tools/perf/builtin-c2c.c2
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/builtin-probe.c3
-rw-r--r--tools/perf/builtin-report.c39
-rw-r--r--tools/perf/builtin-sched.c14
-rw-r--r--tools/perf/builtin-script.c12
-rw-r--r--tools/perf/builtin-stat.c28
-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.c4
-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/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/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.c24
-rw-r--r--tools/perf/util/hist.c15
-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.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.y14
-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.h7
-rw-r--r--tools/perf/util/symbol.c3
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/top.h3
59 files changed, 998 insertions, 427 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..5dfe102fb5b5 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -310,20 +310,38 @@ Users who wants to get the actual value can apply --no-metric-only.
310EXAMPLES 310EXAMPLES
311-------- 311--------
312 312
313$ perf stat -- make -j 313$ perf stat -- make
314 314
315 Performance counter stats for 'make -j': 315 Performance counter stats for 'make':
316 316
317 8117.370256 task clock ticks # 11.281 CPU utilization factor 317 83723.452481 task-clock:u (msec) # 1.004 CPUs utilized
318 678 context switches # 0.000 M/sec 318 0 context-switches:u # 0.000 K/sec
319 133 CPU migrations # 0.000 M/sec 319 0 cpu-migrations:u # 0.000 K/sec
320 235724 pagefaults # 0.029 M/sec 320 3,228,188 page-faults:u # 0.039 M/sec
321 24821162526 CPU cycles # 3057.784 M/sec 321 229,570,665,834 cycles:u # 2.742 GHz
322 18687303457 instructions # 2302.138 M/sec 322 313,163,853,778 instructions:u # 1.36 insn per cycle
323 172158895 cache references # 21.209 M/sec 323 69,704,684,856 branches:u # 832.559 M/sec
324 27075259 cache misses # 3.335 M/sec 324 2,078,861,393 branch-misses:u # 2.98% of all branches
325 325
326 Wall-clock time elapsed: 719.554352 msecs 326 83.409183620 seconds time elapsed
327
328 74.684747000 seconds user
329 8.739217000 seconds sys
330
331TIMINGS
332-------
333As displayed in the example above we can display 3 types of timings.
334We always display the time the counters were enabled/alive:
335
336 83.409183620 seconds time elapsed
337
338For workload sessions we also display time the workloads spent in
339user/system lands:
340
341 74.684747000 seconds user
342 8.739217000 seconds sys
343
344Those times are the very same as displayed by the 'time' tool.
327 345
328CSV FORMAT 346CSV FORMAT
329---------- 347----------
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/builtin-annotate.c b/tools/perf/builtin-annotate.c
index da5704240239..5eb22cc56363 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}
@@ -289,10 +288,9 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
289 struct perf_annotate *ann) 288 struct perf_annotate *ann)
290{ 289{
291 if (!ann->use_stdio2) 290 if (!ann->use_stdio2)
292 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, &ann->opts);
293 ann->print_line, ann->full_paths, 0, 0); 292
294 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, 293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, &ann->opts);
295 ann->print_line, ann->full_paths);
296} 294}
297 295
298static void hists__find_annotations(struct hists *hists, 296static void hists__find_annotations(struct hists *hists,
@@ -343,7 +341,7 @@ find_next:
343 /* skip missing symbols */ 341 /* skip missing symbols */
344 nd = rb_next(nd); 342 nd = rb_next(nd);
345 } else if (use_browser == 1) { 343 } else if (use_browser == 1) {
346 key = hist_entry__tui_annotate(he, evsel, NULL); 344 key = hist_entry__tui_annotate(he, evsel, NULL, &ann->opts);
347 345
348 switch (key) { 346 switch (key) {
349 case -1: 347 case -1:
@@ -390,8 +388,9 @@ static int __cmd_annotate(struct perf_annotate *ann)
390 goto out; 388 goto out;
391 } 389 }
392 390
393 if (!objdump_path) { 391 if (!ann->opts.objdump_path) {
394 ret = perf_env__lookup_objdump(&session->header.env); 392 ret = perf_env__lookup_objdump(&session->header.env,
393 &ann->opts.objdump_path);
395 if (ret) 394 if (ret)
396 goto out; 395 goto out;
397 } 396 }
@@ -476,6 +475,7 @@ int cmd_annotate(int argc, const char **argv)
476 .ordered_events = true, 475 .ordered_events = true,
477 .ordering_requires_timestamps = true, 476 .ordering_requires_timestamps = true,
478 }, 477 },
478 .opts = annotation__default_options,
479 }; 479 };
480 struct perf_data data = { 480 struct perf_data data = {
481 .mode = PERF_DATA_MODE_READ, 481 .mode = PERF_DATA_MODE_READ,
@@ -503,9 +503,9 @@ int cmd_annotate(int argc, const char **argv)
503 "file", "vmlinux pathname"), 503 "file", "vmlinux pathname"),
504 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 504 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
505 "load module symbols - WARNING: use only with -k and LIVE kernel"), 505 "load module symbols - WARNING: use only with -k and LIVE kernel"),
506 OPT_BOOLEAN('l', "print-line", &annotate.print_line, 506 OPT_BOOLEAN('l', "print-line", &annotate.opts.print_lines,
507 "print matching source lines (may be slow)"), 507 "print matching source lines (may be slow)"),
508 OPT_BOOLEAN('P', "full-paths", &annotate.full_paths, 508 OPT_BOOLEAN('P', "full-paths", &annotate.opts.full_path,
509 "Don't shorten the displayed pathnames"), 509 "Don't shorten the displayed pathnames"),
510 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 510 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
511 "Skip symbols that cannot be annotated"), 511 "Skip symbols that cannot be annotated"),
@@ -516,13 +516,13 @@ int cmd_annotate(int argc, const char **argv)
516 OPT_CALLBACK(0, "symfs", NULL, "directory", 516 OPT_CALLBACK(0, "symfs", NULL, "directory",
517 "Look for files with symbols relative to this directory", 517 "Look for files with symbols relative to this directory",
518 symbol__config_symfs), 518 symbol__config_symfs),
519 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 519 OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src,
520 "Interleave source code with assembly code (default)"), 520 "Interleave source code with assembly code (default)"),
521 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 521 OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw,
522 "Display raw encoding of assembly instructions (default)"), 522 "Display raw encoding of assembly instructions (default)"),
523 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 523 OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style",
524 "Specify disassembler style (e.g. -M intel for intel syntax)"), 524 "Specify disassembler style (e.g. -M intel for intel syntax)"),
525 OPT_STRING(0, "objdump", &objdump_path, "path", 525 OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path",
526 "objdump binary to use for disassembly and annotations"), 526 "objdump binary to use for disassembly and annotations"),
527 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 527 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
528 "Show event group information together"), 528 "Show event group information together"),
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 2126bfbcb385..307b3594525f 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -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..cdb5b6949832 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);
@@ -561,7 +561,7 @@ static int report__browse_hists(struct report *rep)
561 ret = perf_evlist__tui_browse_hists(evlist, help, NULL, 561 ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
562 rep->min_percent, 562 rep->min_percent,
563 &session->header.env, 563 &session->header.env,
564 true); 564 true, &rep->annotation_opts);
565 /* 565 /*
566 * Usually "ret" is the last pressed key, and we only 566 * Usually "ret" is the last pressed key, and we only
567 * care if the key notifies us to switch data file. 567 * care if the key notifies us to switch data file.
@@ -946,12 +946,6 @@ parse_percent_limit(const struct option *opt, const char *str,
946 return 0; 946 return 0;
947} 947}
948 948
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) 949int cmd_report(int argc, const char **argv)
956{ 950{
957 struct perf_session *session; 951 struct perf_session *session;
@@ -960,6 +954,10 @@ int cmd_report(int argc, const char **argv)
960 bool has_br_stack = false; 954 bool has_br_stack = false;
961 int branch_mode = -1; 955 int branch_mode = -1;
962 bool branch_call_mode = false; 956 bool branch_call_mode = false;
957#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
958 const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
959 CALLCHAIN_REPORT_HELP
960 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
963 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 961 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
964 const char * const report_usage[] = { 962 const char * const report_usage[] = {
965 "perf report [<options>]", 963 "perf report [<options>]",
@@ -989,6 +987,7 @@ int cmd_report(int argc, const char **argv)
989 .max_stack = PERF_MAX_STACK_DEPTH, 987 .max_stack = PERF_MAX_STACK_DEPTH,
990 .pretty_printing_style = "normal", 988 .pretty_printing_style = "normal",
991 .socket_filter = -1, 989 .socket_filter = -1,
990 .annotation_opts = annotation__default_options,
992 }; 991 };
993 const struct option options[] = { 992 const struct option options[] = {
994 OPT_STRING('i', "input", &input_name, "file", 993 OPT_STRING('i', "input", &input_name, "file",
@@ -1078,11 +1077,11 @@ int cmd_report(int argc, const char **argv)
1078 "list of cpus to profile"), 1077 "list of cpus to profile"),
1079 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 1078 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
1080 "Display extended information about perf.data file"), 1079 "Display extended information about perf.data file"),
1081 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 1080 OPT_BOOLEAN(0, "source", &report.annotation_opts.annotate_src,
1082 "Interleave source code with assembly code (default)"), 1081 "Interleave source code with assembly code (default)"),
1083 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1082 OPT_BOOLEAN(0, "asm-raw", &report.annotation_opts.show_asm_raw,
1084 "Display raw encoding of assembly instructions (default)"), 1083 "Display raw encoding of assembly instructions (default)"),
1085 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1084 OPT_STRING('M', "disassembler-style", &report.annotation_opts.disassembler_style, "disassembler style",
1086 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1085 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1087 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1086 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1088 "Show a column with the sum of periods"), 1087 "Show a column with the sum of periods"),
@@ -1093,7 +1092,7 @@ int cmd_report(int argc, const char **argv)
1093 parse_branch_mode), 1092 parse_branch_mode),
1094 OPT_BOOLEAN(0, "branch-history", &branch_call_mode, 1093 OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
1095 "add last branch records to call history"), 1094 "add last branch records to call history"),
1096 OPT_STRING(0, "objdump", &objdump_path, "path", 1095 OPT_STRING(0, "objdump", &report.annotation_opts.objdump_path, "path",
1097 "objdump binary to use for disassembly and annotations"), 1096 "objdump binary to use for disassembly and annotations"),
1098 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 1097 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
1099 "Disable symbol demangling"), 1098 "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..b3bf35512d21 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -517,7 +517,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
517 517
518 evlist__for_each_entry(session->evlist, evsel) { 518 evlist__for_each_entry(session->evlist, evsel) {
519 not_pipe = true; 519 not_pipe = true;
520 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { 520 if (evsel__has_callchain(evsel)) {
521 use_callchain = true; 521 use_callchain = true;
522 break; 522 break;
523 } 523 }
@@ -532,22 +532,18 @@ static int perf_session__check_output_opt(struct perf_session *session)
532 */ 532 */
533 if (symbol_conf.use_callchain && 533 if (symbol_conf.use_callchain &&
534 !output[PERF_TYPE_TRACEPOINT].user_set) { 534 !output[PERF_TYPE_TRACEPOINT].user_set) {
535 struct perf_event_attr *attr;
536
537 j = PERF_TYPE_TRACEPOINT; 535 j = PERF_TYPE_TRACEPOINT;
538 536
539 evlist__for_each_entry(session->evlist, evsel) { 537 evlist__for_each_entry(session->evlist, evsel) {
540 if (evsel->attr.type != j) 538 if (evsel->attr.type != j)
541 continue; 539 continue;
542 540
543 attr = &evsel->attr; 541 if (evsel__has_callchain(evsel)) {
544
545 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
546 output[j].fields |= PERF_OUTPUT_IP; 542 output[j].fields |= PERF_OUTPUT_IP;
547 output[j].fields |= PERF_OUTPUT_SYM; 543 output[j].fields |= PERF_OUTPUT_SYM;
548 output[j].fields |= PERF_OUTPUT_SYMOFFSET; 544 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
549 output[j].fields |= PERF_OUTPUT_DSO; 545 output[j].fields |= PERF_OUTPUT_DSO;
550 set_print_ip_opts(attr); 546 set_print_ip_opts(&evsel->attr);
551 goto out; 547 goto out;
552 } 548 }
553 } 549 }
@@ -610,7 +606,7 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
610 if (PRINT_FIELD(COMM)) { 606 if (PRINT_FIELD(COMM)) {
611 if (latency_format) 607 if (latency_format)
612 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread)); 608 printed += fprintf(fp, "%8.8s ", thread__comm_str(thread));
613 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 609 else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
614 printed += fprintf(fp, "%s ", thread__comm_str(thread)); 610 printed += fprintf(fp, "%s ", thread__comm_str(thread));
615 else 611 else
616 printed += fprintf(fp, "%16s ", thread__comm_str(thread)); 612 printed += fprintf(fp, "%16s ", thread__comm_str(thread));
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a4f662a462c6..096ccb25c11f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -80,6 +80,9 @@
80#include <sys/stat.h> 80#include <sys/stat.h>
81#include <sys/wait.h> 81#include <sys/wait.h>
82#include <unistd.h> 82#include <unistd.h>
83#include <sys/time.h>
84#include <sys/resource.h>
85#include <sys/wait.h>
83 86
84#include "sane_ctype.h" 87#include "sane_ctype.h"
85 88
@@ -175,6 +178,8 @@ static int output_fd;
175static int print_free_counters_hint; 178static int print_free_counters_hint;
176static int print_mixed_hw_group_error; 179static int print_mixed_hw_group_error;
177static u64 *walltime_run; 180static u64 *walltime_run;
181static bool ru_display = false;
182static struct rusage ru_data;
178 183
179struct perf_stat { 184struct perf_stat {
180 bool record; 185 bool record;
@@ -726,7 +731,7 @@ try_again:
726 break; 731 break;
727 } 732 }
728 } 733 }
729 waitpid(child_pid, &status, 0); 734 wait4(child_pid, &status, 0, &ru_data);
730 735
731 if (workload_exec_errno) { 736 if (workload_exec_errno) {
732 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 737 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -1804,6 +1809,11 @@ static void print_table(FILE *output, int precision, double avg)
1804 fprintf(output, "\n%*s# Final result:\n", indent, ""); 1809 fprintf(output, "\n%*s# Final result:\n", indent, "");
1805} 1810}
1806 1811
1812static double timeval2double(struct timeval *t)
1813{
1814 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1815}
1816
1807static void print_footer(void) 1817static void print_footer(void)
1808{ 1818{
1809 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 1819 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
@@ -1815,6 +1825,15 @@ static void print_footer(void)
1815 1825
1816 if (run_count == 1) { 1826 if (run_count == 1) {
1817 fprintf(output, " %17.9f seconds time elapsed", avg); 1827 fprintf(output, " %17.9f seconds time elapsed", avg);
1828
1829 if (ru_display) {
1830 double ru_utime = timeval2double(&ru_data.ru_utime);
1831 double ru_stime = timeval2double(&ru_data.ru_stime);
1832
1833 fprintf(output, "\n\n");
1834 fprintf(output, " %17.9f seconds user\n", ru_utime);
1835 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1836 }
1818 } else { 1837 } else {
1819 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 1838 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1820 /* 1839 /*
@@ -2950,6 +2969,13 @@ int cmd_stat(int argc, const char **argv)
2950 2969
2951 setup_system_wide(argc); 2970 setup_system_wide(argc);
2952 2971
2972 /*
2973 * Display user/system times only for single
2974 * run and when there's specified tracee.
2975 */
2976 if ((run_count == 1) && target__none(&target))
2977 ru_display = true;
2978
2953 if (run_count < 0) { 2979 if (run_count < 0) {
2954 pr_err("Run count must be a positive number\n"); 2980 pr_err("Run count must be a positive number\n");
2955 parse_options_usage(stat_usage, stat_options, "r", 1); 2981 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..7d4077068454 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;
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/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..b085f1b3e34d 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 (hists__has_callchains(hists) &&
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/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..540cd2dcd3e7 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
@@ -3312,8 +3328,6 @@ int perf_session__read_header(struct perf_session *session)
3312 lseek(fd, tmp, SEEK_SET); 3328 lseek(fd, tmp, SEEK_SET);
3313 } 3329 }
3314 3330
3315 symbol_conf.nr_events = nr_attrs;
3316
3317 perf_header__process_sections(header, fd, &session->tevent, 3331 perf_header__process_sections(header, fd, &session->tevent,
3318 perf_file_section__process); 3332 perf_file_section__process);
3319 3333
@@ -3739,8 +3753,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]); 3753 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
3740 } 3754 }
3741 3755
3742 symbol_conf.nr_events = evlist->nr_entries;
3743
3744 return 0; 3756 return 0;
3745} 3757}
3746 3758
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 4d602fba40b2..52e8fda93a47 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -410,7 +410,7 @@ static int hist_entry__init(struct hist_entry *he,
410 map__get(he->mem_info->daddr.map); 410 map__get(he->mem_info->daddr.map);
411 } 411 }
412 412
413 if (symbol_conf.use_callchain) 413 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
414 callchain_init(he->callchain); 414 callchain_init(he->callchain);
415 415
416 if (he->raw_data) { 416 if (he->raw_data) {
@@ -492,7 +492,7 @@ static u8 symbol__parent_filter(const struct symbol *parent)
492 492
493static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period) 493static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period)
494{ 494{
495 if (!symbol_conf.use_callchain) 495 if (!hist_entry__has_callchains(he) || !symbol_conf.use_callchain)
496 return; 496 return;
497 497
498 he->hists->callchain_period += period; 498 he->hists->callchain_period += period;
@@ -986,7 +986,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
986 iter->he = he; 986 iter->he = he;
987 he_cache[iter->curr++] = he; 987 he_cache[iter->curr++] = he;
988 988
989 if (symbol_conf.use_callchain) 989 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
990 callchain_append(he->callchain, &cursor, sample->period); 990 callchain_append(he->callchain, &cursor, sample->period);
991 return 0; 991 return 0;
992} 992}
@@ -1039,7 +1039,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1039 int err, err2; 1039 int err, err2;
1040 struct map *alm = NULL; 1040 struct map *alm = NULL;
1041 1041
1042 if (al && al->map) 1042 if (al)
1043 alm = map__get(al->map); 1043 alm = map__get(al->map);
1044 1044
1045 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1045 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
@@ -1373,7 +1373,8 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1373 if (new_he) { 1373 if (new_he) {
1374 new_he->leaf = true; 1374 new_he->leaf = true;
1375 1375
1376 if (symbol_conf.use_callchain) { 1376 if (hist_entry__has_callchains(new_he) &&
1377 symbol_conf.use_callchain) {
1377 callchain_cursor_reset(&callchain_cursor); 1378 callchain_cursor_reset(&callchain_cursor);
1378 if (callchain_merge(&callchain_cursor, 1379 if (callchain_merge(&callchain_cursor,
1379 new_he->callchain, 1380 new_he->callchain,
@@ -1414,7 +1415,7 @@ static int hists__collapse_insert_entry(struct hists *hists,
1414 if (symbol_conf.cumulate_callchain) 1415 if (symbol_conf.cumulate_callchain)
1415 he_stat__add_stat(iter->stat_acc, he->stat_acc); 1416 he_stat__add_stat(iter->stat_acc, he->stat_acc);
1416 1417
1417 if (symbol_conf.use_callchain) { 1418 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
1418 callchain_cursor_reset(&callchain_cursor); 1419 callchain_cursor_reset(&callchain_cursor);
1419 if (callchain_merge(&callchain_cursor, 1420 if (callchain_merge(&callchain_cursor,
1420 iter->callchain, 1421 iter->callchain,
@@ -1757,7 +1758,7 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1757 bool use_callchain; 1758 bool use_callchain;
1758 1759
1759 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) 1760 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
1760 use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; 1761 use_callchain = evsel__has_callchain(evsel);
1761 else 1762 else
1762 use_callchain = symbol_conf.use_callchain; 1763 use_callchain = symbol_conf.use_callchain;
1763 1764
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index fbabfd8a215d..06607c434949 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -220,6 +220,12 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel)
220 return &hevsel->hists; 220 return &hevsel->hists;
221} 221}
222 222
223static __pure inline bool hists__has_callchains(struct hists *hists)
224{
225 const struct perf_evsel *evsel = hists_to_evsel(hists);
226 return evsel__has_callchain(evsel);
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.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..155d2570274f 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,7 +225,7 @@ 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{
229 struct list_head *list, *orig_terms, *terms; 230 struct list_head *list, *orig_terms, *terms;
230 231
@@ -496,6 +497,17 @@ opt_event_config:
496 $$ = NULL; 497 $$ = NULL;
497} 498}
498 499
500opt_pmu_config:
501'/' event_config '/'
502{
503 $$ = $2;
504}
505|
506'/' '/'
507{
508 $$ = NULL;
509}
510
499start_terms: event_config 511start_terms: event_config
500{ 512{
501 struct parse_events_state *parse_state = _parse_state; 513 struct parse_events_state *parse_state = _parse_state;
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..7cf2d5cc038e 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -151,6 +151,11 @@ struct hist_entry {
151 struct callchain_root callchain[0]; /* must be last member */ 151 struct callchain_root callchain[0]; /* must be last member */
152}; 152};
153 153
154static __pure inline bool hist_entry__has_callchains(struct hist_entry *he)
155{
156 return hists__has_callchains(he->hists);
157}
158
154static inline bool hist_entry__has_pairs(struct hist_entry *he) 159static inline bool hist_entry__has_pairs(struct hist_entry *he)
155{ 160{
156 return !list_empty(&he->pairs.node); 161 return !list_empty(&he->pairs.node);
@@ -292,5 +297,5 @@ int64_t
292sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right); 297sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right);
293int64_t 298int64_t
294sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right); 299sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right);
295char *hist_entry__get_srcline(struct hist_entry *he); 300char *hist_entry__srcline(struct hist_entry *he);
296#endif /* __PERF_SORT_H */ 301#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;