aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-08-13 03:23:53 -0400
committerIngo Molnar <mingo@kernel.org>2015-08-13 03:23:53 -0400
commita897b5f0393a8a05d230c9248dc5324fb30720a0 (patch)
tree8b0ed53246df201d073e8fd6dd47304994b15f5b /tools
parent5f1230c9b80b89f404938ff88dfa64a963f74f2c (diff)
parent71ef150ee06df29c5b427307dc0bacfe06a8baea (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Allow selecting the type of callchains per event, including disabling callchains in all but one entry in an event list, to save space, and also to ask for the callchains collected in one event to be used in other events. (Kan Liang) - Beautify more syscall arguments in 'perf trace': (Arnaldo Carvalho de Melo) - A bunch more translate file/pathnames from pointers to strings. - Convert numbers to strings for the 'keyctl' syscall 'option' arg. - Add missing 'clockid' entries. - Fix 'perf probe -L sys_*' as it was not showing all the source code for syscall functions in the kernel. (Masami Hiramatsu) - Make ESC unzoom as well in the hists browser, i.e. in 'report' and 'top', as we're considering repurposing the right and left arrow keys to use in horizontal scrolling, i.e. leave just ESC to be used for what <- works now, and ENTER for what -> does (they are already aliases for ages). (Arnaldo Carvalho de Melo) Infrastructure fixes: - Check for SRCLINE_UNKNOWN case in "srcfile" processing (Andi Kleen) - Wrap the slsmg_{printf,write_nstring} slang functions behind ui_browser, so that we can make the ui_browser based browsers (annotate, menus, hists, etc) UI library agnostic and usable with multiple backends (slang now, GTK+ and others in the future, maybe) (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-report.txt11
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-diff.c3
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/builtin-trace.c54
-rw-r--r--tools/perf/tests/hists_cumulate.c4
-rw-r--r--tools/perf/tests/parse-events.c38
-rw-r--r--tools/perf/ui/browser.c17
-rw-r--r--tools/perf/ui/browser.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c43
-rw-r--r--tools/perf/ui/browsers/header.c2
-rw-r--r--tools/perf/ui/browsers/hists.c54
-rw-r--r--tools/perf/ui/browsers/map.c11
-rw-r--r--tools/perf/ui/browsers/scripts.c2
-rw-r--r--tools/perf/ui/libslang.h3
-rw-r--r--tools/perf/ui/tui/util.c2
-rw-r--r--tools/perf/util/dwarf-aux.c18
-rw-r--r--tools/perf/util/evsel.c67
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/hist.c14
-rw-r--r--tools/perf/util/parse-events.c12
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/pmu.c4
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/symbol.h3
27 files changed, 307 insertions, 81 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index afbe45ef7e3e..347a27322ed8 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -53,6 +53,10 @@ OPTIONS
53 - 'time': Disable/enable time stamping. Acceptable values are 1 for 53 - 'time': Disable/enable time stamping. Acceptable values are 1 for
54 enabling time stamping. 0 for disabling time stamping. 54 enabling time stamping. 0 for disabling time stamping.
55 The default is 1. 55 The default is 1.
56 - 'call-graph': Disable/enable callgraph. Acceptable str are "fp" for
57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and
58 "no" for disable callgraph.
59 - 'stack-size': user stack size for dwarf mode
56 Note: If user explicitly sets options which conflict with the params, 60 Note: If user explicitly sets options which conflict with the params,
57 the value set by the params will be overridden. 61 the value set by the params will be overridden.
58 62
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 7b07d19e2d54..a18ba757a0ed 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -359,6 +359,17 @@ OPTIONS
359--full-source-path:: 359--full-source-path::
360 Show the full path for source files for srcline output. 360 Show the full path for source files for srcline output.
361 361
362--show-ref-call-graph::
363 When multiple events are sampled, it may not be needed to collect
364 callgraphs for all of them. The sample sites are usually nearby,
365 and it's enough to collect the callgraphs on a reference event.
366 So user can use "call-graph=no" event modifier to disable callgraph
367 for other events to reduce the overhead.
368 However, perf report cannot show callgraphs for the event which
369 disable the callgraph.
370 This option extends the perf report to show reference callgraphs,
371 which collected by reference event, in no callgraph event.
372
362include::callchain-overhead-calculation.txt[] 373include::callchain-overhead-calculation.txt[]
363 374
364SEE ALSO 375SEE ALSO
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 467a23b14e2f..a32a64ef08e2 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -239,6 +239,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
239 if (nr_samples > 0) { 239 if (nr_samples > 0) {
240 total_nr_samples += nr_samples; 240 total_nr_samples += nr_samples;
241 hists__collapse_resort(hists, NULL); 241 hists__collapse_resort(hists, NULL);
242 /* Don't sort callchain */
243 perf_evsel__reset_sample_bit(pos, CALLCHAIN);
242 hists__output_resort(hists, NULL); 244 hists__output_resort(hists, NULL);
243 245
244 if (symbol_conf.event_group && 246 if (symbol_conf.event_group &&
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index daaa7dca9c3b..0b180a885ba3 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -722,6 +722,9 @@ static void data_process(void)
722 if (verbose || data__files_cnt > 2) 722 if (verbose || data__files_cnt > 2)
723 data__fprintf(); 723 data__fprintf();
724 724
725 /* Don't sort callchain for perf diff */
726 perf_evsel__reset_sample_bit(evsel_base, CALLCHAIN);
727
725 hists__process(hists_base); 728 hists__process(hists_base);
726 } 729 }
727} 730}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f301e865001f..62b285e32aa5 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -316,6 +316,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
316 if (evname != NULL) 316 if (evname != NULL)
317 ret += fprintf(fp, " of event '%s'", evname); 317 ret += fprintf(fp, " of event '%s'", evname);
318 318
319 if (symbol_conf.show_ref_callgraph &&
320 strstr(evname, "call-graph=no")) {
321 ret += fprintf(fp, ", show reference callgraph");
322 }
323
319 if (rep->mem_mode) { 324 if (rep->mem_mode) {
320 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); 325 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
321 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); 326 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
@@ -740,6 +745,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
740 itrace_parse_synth_opts), 745 itrace_parse_synth_opts),
741 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 746 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
742 "Show full source file name path for source lines"), 747 "Show full source file name path for source lines"),
748 OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
749 "Show callgraph from reference event"),
743 OPT_END() 750 OPT_END()
744 }; 751 };
745 struct perf_data_file file = { 752 struct perf_data_file file = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a25048c85b76..489cc118a36a 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -569,6 +569,15 @@ static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
569static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", }; 569static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
570static DEFINE_STRARRAY(itimers); 570static DEFINE_STRARRAY(itimers);
571 571
572static const char *keyctl_options[] = {
573 "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN",
574 "SETPERM", "DESCRIBE", "CLEAR", "LINK", "UNLINK", "SEARCH", "READ",
575 "INSTANTIATE", "NEGATE", "SET_REQKEY_KEYRING", "SET_TIMEOUT",
576 "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT",
577 "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT",
578};
579static DEFINE_STRARRAY(keyctl_options);
580
572static const char *whences[] = { "SET", "CUR", "END", 581static const char *whences[] = { "SET", "CUR", "END",
573#ifdef SEEK_DATA 582#ifdef SEEK_DATA
574"DATA", 583"DATA",
@@ -599,7 +608,8 @@ static DEFINE_STRARRAY(sighow);
599 608
600static const char *clockid[] = { 609static const char *clockid[] = {
601 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID", 610 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
602 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", 611 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME",
612 "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI"
603}; 613};
604static DEFINE_STRARRAY(clockid); 614static DEFINE_STRARRAY(clockid);
605 615
@@ -1014,7 +1024,8 @@ static struct syscall_fmt {
1014 { .name = "fchmod", .errmsg = true, 1024 { .name = "fchmod", .errmsg = true,
1015 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1025 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1016 { .name = "fchmodat", .errmsg = true, 1026 { .name = "fchmodat", .errmsg = true,
1017 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1027 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1028 [1] = SCA_FILENAME, /* filename */ }, },
1018 { .name = "fchown", .errmsg = true, 1029 { .name = "fchown", .errmsg = true,
1019 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1030 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1020 { .name = "fchownat", .errmsg = true, 1031 { .name = "fchownat", .errmsg = true,
@@ -1045,7 +1056,8 @@ static struct syscall_fmt {
1045 { .name = "futex", .errmsg = true, 1056 { .name = "futex", .errmsg = true,
1046 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 1057 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
1047 { .name = "futimesat", .errmsg = true, 1058 { .name = "futimesat", .errmsg = true,
1048 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1059 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1060 [1] = SCA_FILENAME, /* filename */ }, },
1049 { .name = "getdents", .errmsg = true, 1061 { .name = "getdents", .errmsg = true,
1050 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1062 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1051 { .name = "getdents64", .errmsg = true, 1063 { .name = "getdents64", .errmsg = true,
@@ -1068,6 +1080,7 @@ static struct syscall_fmt {
1068#else 1080#else
1069 [2] = SCA_HEX, /* arg */ }, }, 1081 [2] = SCA_HEX, /* arg */ }, },
1070#endif 1082#endif
1083 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
1071 { .name = "kill", .errmsg = true, 1084 { .name = "kill", .errmsg = true,
1072 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 1085 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1073 { .name = "lchown", .errmsg = true, 1086 { .name = "lchown", .errmsg = true,
@@ -1078,13 +1091,18 @@ static struct syscall_fmt {
1078 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1091 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1079 { .name = "listxattr", .errmsg = true, 1092 { .name = "listxattr", .errmsg = true,
1080 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 1093 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1094 { .name = "llistxattr", .errmsg = true,
1095 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1096 { .name = "lremovexattr", .errmsg = true,
1097 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1081 { .name = "lseek", .errmsg = true, 1098 { .name = "lseek", .errmsg = true,
1082 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 1099 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1083 [2] = SCA_STRARRAY, /* whence */ }, 1100 [2] = SCA_STRARRAY, /* whence */ },
1084 .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, 1101 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
1085 { .name = "lsetxattr", .errmsg = true, 1102 { .name = "lsetxattr", .errmsg = true,
1086 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 1103 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1087 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 1104 { .name = "lstat", .errmsg = true, .alias = "newlstat",
1105 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1088 { .name = "lsxattr", .errmsg = true, 1106 { .name = "lsxattr", .errmsg = true,
1089 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 1107 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1090 { .name = "madvise", .errmsg = true, 1108 { .name = "madvise", .errmsg = true,
@@ -1098,7 +1116,8 @@ static struct syscall_fmt {
1098 { .name = "mknod", .errmsg = true, 1116 { .name = "mknod", .errmsg = true,
1099 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 1117 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1100 { .name = "mknodat", .errmsg = true, 1118 { .name = "mknodat", .errmsg = true,
1101 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1119 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */
1120 [1] = SCA_FILENAME, /* filename */ }, },
1102 { .name = "mlock", .errmsg = true, 1121 { .name = "mlock", .errmsg = true,
1103 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1122 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1104 { .name = "mlockall", .errmsg = true, 1123 { .name = "mlockall", .errmsg = true,
@@ -1111,6 +1130,8 @@ static struct syscall_fmt {
1111 { .name = "mprotect", .errmsg = true, 1130 { .name = "mprotect", .errmsg = true,
1112 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 1131 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1113 [2] = SCA_MMAP_PROT, /* prot */ }, }, 1132 [2] = SCA_MMAP_PROT, /* prot */ }, },
1133 { .name = "mq_unlink", .errmsg = true,
1134 .arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
1114 { .name = "mremap", .hexret = true, 1135 { .name = "mremap", .hexret = true,
1115 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 1136 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1116 [3] = SCA_MREMAP_FLAGS, /* flags */ 1137 [3] = SCA_MREMAP_FLAGS, /* flags */
@@ -1162,11 +1183,14 @@ static struct syscall_fmt {
1162 { .name = "readv", .errmsg = true, 1183 { .name = "readv", .errmsg = true,
1163 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1184 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1164 { .name = "recvfrom", .errmsg = true, 1185 { .name = "recvfrom", .errmsg = true,
1165 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1186 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1187 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1166 { .name = "recvmmsg", .errmsg = true, 1188 { .name = "recvmmsg", .errmsg = true,
1167 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1189 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1190 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1168 { .name = "recvmsg", .errmsg = true, 1191 { .name = "recvmsg", .errmsg = true,
1169 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 1192 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1193 [2] = SCA_MSG_FLAGS, /* flags */ }, },
1170 { .name = "removexattr", .errmsg = true, 1194 { .name = "removexattr", .errmsg = true,
1171 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 1195 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1172 { .name = "renameat", .errmsg = true, 1196 { .name = "renameat", .errmsg = true,
@@ -1182,11 +1206,14 @@ static struct syscall_fmt {
1182 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 1206 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1183 { .name = "select", .errmsg = true, .timeout = true, }, 1207 { .name = "select", .errmsg = true, .timeout = true, },
1184 { .name = "sendmmsg", .errmsg = true, 1208 { .name = "sendmmsg", .errmsg = true,
1185 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1209 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1210 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1186 { .name = "sendmsg", .errmsg = true, 1211 { .name = "sendmsg", .errmsg = true,
1187 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 1212 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1213 [2] = SCA_MSG_FLAGS, /* flags */ }, },
1188 { .name = "sendto", .errmsg = true, 1214 { .name = "sendto", .errmsg = true,
1189 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1215 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1216 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1190 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 1217 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1191 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 1218 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1192 { .name = "setxattr", .errmsg = true, 1219 { .name = "setxattr", .errmsg = true,
@@ -1201,7 +1228,8 @@ static struct syscall_fmt {
1201 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 1228 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1202 [1] = SCA_SK_TYPE, /* type */ }, 1229 [1] = SCA_SK_TYPE, /* type */ },
1203 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 1230 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1204 { .name = "stat", .errmsg = true, .alias = "newstat", }, 1231 { .name = "stat", .errmsg = true, .alias = "newstat",
1232 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1205 { .name = "statfs", .errmsg = true, 1233 { .name = "statfs", .errmsg = true,
1206 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 1234 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1207 { .name = "swapoff", .errmsg = true, 1235 { .name = "swapoff", .errmsg = true,
@@ -1227,6 +1255,8 @@ static struct syscall_fmt {
1227 [1] = SCA_FILENAME, /* filename */ }, }, 1255 [1] = SCA_FILENAME, /* filename */ }, },
1228 { .name = "utimes", .errmsg = true, 1256 { .name = "utimes", .errmsg = true,
1229 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 1257 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1258 { .name = "vmsplice", .errmsg = true,
1259 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1230 { .name = "write", .errmsg = true, 1260 { .name = "write", .errmsg = true,
1231 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1261 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1232 { .name = "writev", .errmsg = true, 1262 { .name = "writev", .errmsg = true,
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 7d82c8be5e36..7ed737019de7 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -279,6 +279,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
279 279
280 symbol_conf.use_callchain = false; 280 symbol_conf.use_callchain = false;
281 symbol_conf.cumulate_callchain = false; 281 symbol_conf.cumulate_callchain = false;
282 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
282 283
283 setup_sorting(); 284 setup_sorting();
284 callchain_register_param(&callchain_param); 285 callchain_register_param(&callchain_param);
@@ -425,6 +426,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
425 426
426 symbol_conf.use_callchain = true; 427 symbol_conf.use_callchain = true;
427 symbol_conf.cumulate_callchain = false; 428 symbol_conf.cumulate_callchain = false;
429 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
428 430
429 setup_sorting(); 431 setup_sorting();
430 callchain_register_param(&callchain_param); 432 callchain_register_param(&callchain_param);
@@ -482,6 +484,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
482 484
483 symbol_conf.use_callchain = false; 485 symbol_conf.use_callchain = false;
484 symbol_conf.cumulate_callchain = true; 486 symbol_conf.cumulate_callchain = true;
487 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
485 488
486 setup_sorting(); 489 setup_sorting();
487 callchain_register_param(&callchain_param); 490 callchain_register_param(&callchain_param);
@@ -665,6 +668,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
665 668
666 symbol_conf.use_callchain = true; 669 symbol_conf.use_callchain = true;
667 symbol_conf.cumulate_callchain = true; 670 symbol_conf.cumulate_callchain = true;
671 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
668 672
669 setup_sorting(); 673 setup_sorting();
670 callchain_register_param(&callchain_param); 674 callchain_register_param(&callchain_param);
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index f65bb89e109e..9b6b2b6324a1 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -479,6 +479,39 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
479 return 0; 479 return 0;
480} 480}
481 481
482static int test__checkevent_pmu_partial_time_callgraph(struct perf_evlist *evlist)
483{
484 struct perf_evsel *evsel = perf_evlist__first(evlist);
485
486 /* cpu/config=1,call-graph=fp,time,period=100000/ */
487 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
488 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
489 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
490 /*
491 * The period, time and callgraph value gets configured
492 * within perf_evlist__config,
493 * while this test executes only parse events method.
494 */
495 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
496 TEST_ASSERT_VAL("wrong callgraph", !(PERF_SAMPLE_CALLCHAIN & evsel->attr.sample_type));
497 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
498
499 /* cpu/config=2,call-graph=no,time=0,period=2000/ */
500 evsel = perf_evsel__next(evsel);
501 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
502 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
503 /*
504 * The period, time and callgraph value gets configured
505 * within perf_evlist__config,
506 * while this test executes only parse events method.
507 */
508 TEST_ASSERT_VAL("wrong period", 0 == evsel->attr.sample_period);
509 TEST_ASSERT_VAL("wrong callgraph", !(PERF_SAMPLE_CALLCHAIN & evsel->attr.sample_type));
510 TEST_ASSERT_VAL("wrong time", !(PERF_SAMPLE_TIME & evsel->attr.sample_type));
511
512 return 0;
513}
514
482static int test__checkevent_pmu_events(struct perf_evlist *evlist) 515static int test__checkevent_pmu_events(struct perf_evlist *evlist)
483{ 516{
484 struct perf_evsel *evsel = perf_evlist__first(evlist); 517 struct perf_evsel *evsel = perf_evlist__first(evlist);
@@ -1555,6 +1588,11 @@ static struct evlist_test test__events_pmu[] = {
1555 .check = test__checkevent_pmu_name, 1588 .check = test__checkevent_pmu_name,
1556 .id = 1, 1589 .id = 1,
1557 }, 1590 },
1591 {
1592 .name = "cpu/config=1,call-graph=fp,time,period=100000/,cpu/config=2,call-graph=no,time=0,period=2000/",
1593 .check = test__checkevent_pmu_partial_time_callgraph,
1594 .id = 2,
1595 },
1558}; 1596};
1559 1597
1560struct terms_test { 1598struct terms_test {
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 6680fa5cb9dd..c6c7e5189214 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -46,6 +46,21 @@ void ui_browser__gotorc(struct ui_browser *browser, int y, int x)
46 SLsmg_gotorc(browser->y + y, browser->x + x); 46 SLsmg_gotorc(browser->y + y, browser->x + x);
47} 47}
48 48
49void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg,
50 unsigned int width)
51{
52 slsmg_write_nstring(msg, width);
53}
54
55void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...)
56{
57 va_list args;
58
59 va_start(args, fmt);
60 slsmg_vprintf(fmt, args);
61 va_end(args);
62}
63
49static struct list_head * 64static struct list_head *
50ui_browser__list_head_filter_entries(struct ui_browser *browser, 65ui_browser__list_head_filter_entries(struct ui_browser *browser,
51 struct list_head *pos) 66 struct list_head *pos)
@@ -234,7 +249,7 @@ void __ui_browser__show_title(struct ui_browser *browser, const char *title)
234{ 249{
235 SLsmg_gotorc(0, 0); 250 SLsmg_gotorc(0, 0);
236 ui_browser__set_color(browser, HE_COLORSET_ROOT); 251 ui_browser__set_color(browser, HE_COLORSET_ROOT);
237 slsmg_write_nstring(title, browser->width + 1); 252 ui_browser__write_nstring(browser, title, browser->width + 1);
238} 253}
239 254
240void ui_browser__show_title(struct ui_browser *browser, const char *title) 255void ui_browser__show_title(struct ui_browser *browser, const char *title)
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 92ae72113965..52be87125def 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -37,6 +37,9 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser);
37void ui_browser__reset_index(struct ui_browser *browser); 37void ui_browser__reset_index(struct ui_browser *browser);
38 38
39void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 39void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
40void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
41 unsigned int width);
42void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
40void ui_browser__write_graph(struct ui_browser *browser, int graph); 43void ui_browser__write_graph(struct ui_browser *browser, int graph);
41void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 44void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
42 u64 start, u64 end); 45 u64 start, u64 end);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index b5fc847f9660..29739b347599 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -1,7 +1,6 @@
1#include "../../util/util.h" 1#include "../../util/util.h"
2#include "../browser.h" 2#include "../browser.h"
3#include "../helpline.h" 3#include "../helpline.h"
4#include "../libslang.h"
5#include "../ui.h" 4#include "../ui.h"
6#include "../util.h" 5#include "../util.h"
7#include "../../util/annotate.h" 6#include "../../util/annotate.h"
@@ -134,29 +133,31 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
134 ui_browser__set_percent_color(browser, 133 ui_browser__set_percent_color(browser,
135 bdl->samples[i].percent, 134 bdl->samples[i].percent,
136 current_entry); 135 current_entry);
137 if (annotate_browser__opts.show_total_period) 136 if (annotate_browser__opts.show_total_period) {
138 slsmg_printf("%6" PRIu64 " ", 137 ui_browser__printf(browser, "%6" PRIu64 " ",
139 bdl->samples[i].nr); 138 bdl->samples[i].nr);
140 else 139 } else {
141 slsmg_printf("%6.2f ", bdl->samples[i].percent); 140 ui_browser__printf(browser, "%6.2f ",
141 bdl->samples[i].percent);
142 }
142 } 143 }
143 } else { 144 } else {
144 slsmg_write_nstring(" ", 7 * ab->nr_events); 145 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
145 } 146 }
146 } else { 147 } else {
147 ui_browser__set_percent_color(browser, 0, current_entry); 148 ui_browser__set_percent_color(browser, 0, current_entry);
148 slsmg_write_nstring(" ", 7 * ab->nr_events); 149 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
149 } 150 }
150 if (ab->have_cycles) { 151 if (ab->have_cycles) {
151 if (dl->ipc) 152 if (dl->ipc)
152 slsmg_printf("%*.2f ", IPC_WIDTH - 1, dl->ipc); 153 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc);
153 else 154 else
154 slsmg_write_nstring(" ", IPC_WIDTH); 155 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
155 if (dl->cycles) 156 if (dl->cycles)
156 slsmg_printf("%*" PRIu64 " ", 157 ui_browser__printf(browser, "%*" PRIu64 " ",
157 CYCLES_WIDTH - 1, dl->cycles); 158 CYCLES_WIDTH - 1, dl->cycles);
158 else 159 else
159 slsmg_write_nstring(" ", CYCLES_WIDTH); 160 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
160 } 161 }
161 162
162 SLsmg_write_char(' '); 163 SLsmg_write_char(' ');
@@ -166,7 +167,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
166 width += 1; 167 width += 1;
167 168
168 if (!*dl->line) 169 if (!*dl->line)
169 slsmg_write_nstring(" ", width - pcnt_width); 170 ui_browser__write_nstring(browser, " ", width - pcnt_width);
170 else if (dl->offset == -1) { 171 else if (dl->offset == -1) {
171 if (dl->line_nr && annotate_browser__opts.show_linenr) 172 if (dl->line_nr && annotate_browser__opts.show_linenr)
172 printed = scnprintf(bf, sizeof(bf), "%-*d ", 173 printed = scnprintf(bf, sizeof(bf), "%-*d ",
@@ -174,8 +175,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
174 else 175 else
175 printed = scnprintf(bf, sizeof(bf), "%*s ", 176 printed = scnprintf(bf, sizeof(bf), "%*s ",
176 ab->addr_width, " "); 177 ab->addr_width, " ");
177 slsmg_write_nstring(bf, printed); 178 ui_browser__write_nstring(browser, bf, printed);
178 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 179 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1);
179 } else { 180 } else {
180 u64 addr = dl->offset; 181 u64 addr = dl->offset;
181 int color = -1; 182 int color = -1;
@@ -194,7 +195,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
194 bdl->jump_sources); 195 bdl->jump_sources);
195 prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 196 prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources,
196 current_entry); 197 current_entry);
197 slsmg_write_nstring(bf, printed); 198 ui_browser__write_nstring(browser, bf, printed);
198 ui_browser__set_color(browser, prev); 199 ui_browser__set_color(browser, prev);
199 } 200 }
200 201
@@ -208,7 +209,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
208 209
209 if (change_color) 210 if (change_color)
210 color = ui_browser__set_color(browser, HE_COLORSET_ADDR); 211 color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
211 slsmg_write_nstring(bf, printed); 212 ui_browser__write_nstring(browser, bf, printed);
212 if (change_color) 213 if (change_color)
213 ui_browser__set_color(browser, color); 214 ui_browser__set_color(browser, color);
214 if (dl->ins && dl->ins->ops->scnprintf) { 215 if (dl->ins && dl->ins->ops->scnprintf) {
@@ -222,11 +223,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
222 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 223 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
223 SLsmg_write_char(' '); 224 SLsmg_write_char(' ');
224 } else { 225 } else {
225 slsmg_write_nstring(" ", 2); 226 ui_browser__write_nstring(browser, " ", 2);
226 } 227 }
227 } else { 228 } else {
228 if (strcmp(dl->name, "retq")) { 229 if (strcmp(dl->name, "retq")) {
229 slsmg_write_nstring(" ", 2); 230 ui_browser__write_nstring(browser, " ", 2);
230 } else { 231 } else {
231 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); 232 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
232 SLsmg_write_char(' '); 233 SLsmg_write_char(' ');
@@ -234,7 +235,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
234 } 235 }
235 236
236 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 237 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
237 slsmg_write_nstring(bf, width - pcnt_width - 3 - printed); 238 ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed);
238 } 239 }
239 240
240 if (current_entry) 241 if (current_entry)
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index e8278c558d4a..f10681717f93 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -25,7 +25,7 @@ static void ui_browser__argv_write(struct ui_browser *browser,
25 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 25 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
26 HE_COLORSET_NORMAL); 26 HE_COLORSET_NORMAL);
27 27
28 slsmg_write_nstring(str, browser->width); 28 ui_browser__write_nstring(browser, str, browser->width);
29} 29}
30 30
31static int list_menu__run(struct ui_browser *menu) 31static int list_menu__run(struct ui_browser *menu)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index fa67613976a8..10c7ec041039 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1,5 +1,4 @@
1#include <stdio.h> 1#include <stdio.h>
2#include "../libslang.h"
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
5#include <linux/rbtree.h> 4#include <linux/rbtree.h>
@@ -540,10 +539,10 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
540 539
541 ui_browser__set_color(&browser->b, color); 540 ui_browser__set_color(&browser->b, color);
542 hist_browser__gotorc(browser, row, 0); 541 hist_browser__gotorc(browser, row, 0);
543 slsmg_write_nstring(" ", offset); 542 ui_browser__write_nstring(&browser->b, " ", offset);
544 slsmg_printf("%c", folded_sign); 543 ui_browser__printf(&browser->b, "%c", folded_sign);
545 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); 544 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
546 slsmg_write_nstring(str, width); 545 ui_browser__write_nstring(&browser->b, str, width);
547} 546}
548 547
549static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused, 548static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
@@ -680,7 +679,7 @@ static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
680 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 679 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
681 680
682 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent); 681 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
683 slsmg_printf("%s", hpp->buf); 682 ui_browser__printf(arg->b, "%s", hpp->buf);
684 683
685 advance_hpp(hpp, ret); 684 advance_hpp(hpp, ret);
686 return ret; 685 return ret;
@@ -713,10 +712,11 @@ hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
713 struct hist_entry *he) \ 712 struct hist_entry *he) \
714{ \ 713{ \
715 if (!symbol_conf.cumulate_callchain) { \ 714 if (!symbol_conf.cumulate_callchain) { \
715 struct hpp_arg *arg = hpp->ptr; \
716 int len = fmt->user_len ?: fmt->len; \ 716 int len = fmt->user_len ?: fmt->len; \
717 int ret = scnprintf(hpp->buf, hpp->size, \ 717 int ret = scnprintf(hpp->buf, hpp->size, \
718 "%*s", len, "N/A"); \ 718 "%*s", len, "N/A"); \
719 slsmg_printf("%s", hpp->buf); \ 719 ui_browser__printf(arg->b, "%s", hpp->buf); \
720 \ 720 \
721 return ret; \ 721 return ret; \
722 } \ 722 } \
@@ -801,12 +801,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
801 801
802 if (first) { 802 if (first) {
803 if (symbol_conf.use_callchain) { 803 if (symbol_conf.use_callchain) {
804 slsmg_printf("%c ", folded_sign); 804 ui_browser__printf(&browser->b, "%c ", folded_sign);
805 width -= 2; 805 width -= 2;
806 } 806 }
807 first = false; 807 first = false;
808 } else { 808 } else {
809 slsmg_printf(" "); 809 ui_browser__printf(&browser->b, " ");
810 width -= 2; 810 width -= 2;
811 } 811 }
812 812
@@ -814,7 +814,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
814 width -= fmt->color(fmt, &hpp, entry); 814 width -= fmt->color(fmt, &hpp, entry);
815 } else { 815 } else {
816 width -= fmt->entry(fmt, &hpp, entry); 816 width -= fmt->entry(fmt, &hpp, entry);
817 slsmg_printf("%s", s); 817 ui_browser__printf(&browser->b, "%s", s);
818 } 818 }
819 } 819 }
820 820
@@ -822,7 +822,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
822 if (!browser->b.navkeypressed) 822 if (!browser->b.navkeypressed)
823 width += 1; 823 width += 1;
824 824
825 slsmg_write_nstring("", width); 825 ui_browser__write_nstring(&browser->b, "", width);
826 826
827 ++row; 827 ++row;
828 ++printed; 828 ++printed;
@@ -899,7 +899,7 @@ static void hist_browser__show_headers(struct hist_browser *browser)
899 hists__scnprintf_headers(headers, sizeof(headers), browser->hists); 899 hists__scnprintf_headers(headers, sizeof(headers), browser->hists);
900 ui_browser__gotorc(&browser->b, 0, 0); 900 ui_browser__gotorc(&browser->b, 0, 0);
901 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 901 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
902 slsmg_write_nstring(headers, browser->b.width + 1); 902 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
903} 903}
904 904
905static void ui_browser__hists_init_top(struct ui_browser *browser) 905static void ui_browser__hists_init_top(struct ui_browser *browser)
@@ -1267,6 +1267,8 @@ static int hists__browser_title(struct hists *hists,
1267 const char *ev_name = perf_evsel__name(evsel); 1267 const char *ev_name = perf_evsel__name(evsel);
1268 char buf[512]; 1268 char buf[512];
1269 size_t buflen = sizeof(buf); 1269 size_t buflen = sizeof(buf);
1270 char ref[30] = " show reference callgraph, ";
1271 bool enable_ref = false;
1270 1272
1271 if (symbol_conf.filter_relative) { 1273 if (symbol_conf.filter_relative) {
1272 nr_samples = hists->stats.nr_non_filtered_samples; 1274 nr_samples = hists->stats.nr_non_filtered_samples;
@@ -1292,10 +1294,13 @@ static int hists__browser_title(struct hists *hists,
1292 } 1294 }
1293 } 1295 }
1294 1296
1297 if (symbol_conf.show_ref_callgraph &&
1298 strstr(ev_name, "call-graph=no"))
1299 enable_ref = true;
1295 nr_samples = convert_unit(nr_samples, &unit); 1300 nr_samples = convert_unit(nr_samples, &unit);
1296 printed = scnprintf(bf, size, 1301 printed = scnprintf(bf, size,
1297 "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64, 1302 "Samples: %lu%c of event '%s',%sEvent count (approx.): %" PRIu64,
1298 nr_samples, unit, ev_name, nr_events); 1303 nr_samples, unit, ev_name, enable_ref ? ref : " ", nr_events);
1299 1304
1300 1305
1301 if (hists->uid_filter_str) 1306 if (hists->uid_filter_str)
@@ -1868,6 +1873,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1868 case K_RIGHT: 1873 case K_RIGHT:
1869 /* menu */ 1874 /* menu */
1870 break; 1875 break;
1876 case K_ESC:
1871 case K_LEFT: { 1877 case K_LEFT: {
1872 const void *top; 1878 const void *top;
1873 1879
@@ -1877,6 +1883,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1877 */ 1883 */
1878 if (left_exits) 1884 if (left_exits)
1879 goto out_free_stack; 1885 goto out_free_stack;
1886
1887 if (key == K_ESC &&
1888 ui_browser__dialog_yesno(&browser->b,
1889 "Do you really want to exit?"))
1890 goto out_free_stack;
1891
1880 continue; 1892 continue;
1881 } 1893 }
1882 top = pstack__peek(browser->pstack); 1894 top = pstack__peek(browser->pstack);
@@ -1892,12 +1904,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1892 do_zoom_thread(browser, actions); 1904 do_zoom_thread(browser, actions);
1893 continue; 1905 continue;
1894 } 1906 }
1895 case K_ESC:
1896 if (!left_exits &&
1897 !ui_browser__dialog_yesno(&browser->b,
1898 "Do you really want to exit?"))
1899 continue;
1900 /* Fall thru */
1901 case 'q': 1907 case 'q':
1902 case CTRL('c'): 1908 case CTRL('c'):
1903 goto out_free_stack; 1909 goto out_free_stack;
@@ -2044,7 +2050,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
2044 nr_events = convert_unit(nr_events, &unit); 2050 nr_events = convert_unit(nr_events, &unit);
2045 printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 2051 printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
2046 unit, unit == ' ' ? "" : " ", ev_name); 2052 unit, unit == ' ' ? "" : " ", ev_name);
2047 slsmg_printf("%s", bf); 2053 ui_browser__printf(browser, "%s", bf);
2048 2054
2049 nr_events = hists->stats.nr_events[PERF_RECORD_LOST]; 2055 nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
2050 if (nr_events != 0) { 2056 if (nr_events != 0) {
@@ -2057,7 +2063,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
2057 warn = bf; 2063 warn = bf;
2058 } 2064 }
2059 2065
2060 slsmg_write_nstring(warn, browser->width - printed); 2066 ui_browser__write_nstring(browser, warn, browser->width - printed);
2061 2067
2062 if (current_entry) 2068 if (current_entry)
2063 menu->selection = evsel; 2069 menu->selection = evsel;
@@ -2120,15 +2126,11 @@ browse_hists:
2120 else 2126 else
2121 pos = perf_evsel__prev(pos); 2127 pos = perf_evsel__prev(pos);
2122 goto browse_hists; 2128 goto browse_hists;
2123 case K_ESC:
2124 if (!ui_browser__dialog_yesno(&menu->b,
2125 "Do you really want to exit?"))
2126 continue;
2127 /* Fall thru */
2128 case K_SWITCH_INPUT_DATA: 2129 case K_SWITCH_INPUT_DATA:
2129 case 'q': 2130 case 'q':
2130 case CTRL('c'): 2131 case CTRL('c'):
2131 goto out; 2132 goto out;
2133 case K_ESC:
2132 default: 2134 default:
2133 continue; 2135 continue;
2134 } 2136 }
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index b11639f33682..8c154c7d4669 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -1,4 +1,3 @@
1#include "../libslang.h"
2#include <elf.h> 1#include <elf.h>
3#include <inttypes.h> 2#include <inttypes.h>
4#include <sys/ttydefaults.h> 3#include <sys/ttydefaults.h>
@@ -26,13 +25,13 @@ static void map_browser__write(struct ui_browser *browser, void *nd, int row)
26 int width; 25 int width;
27 26
28 ui_browser__set_percent_color(browser, 0, current_entry); 27 ui_browser__set_percent_color(browser, 0, current_entry);
29 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ", 28 ui_browser__printf(browser, "%*" PRIx64 " %*" PRIx64 " %c ",
30 mb->addrlen, sym->start, mb->addrlen, sym->end, 29 mb->addrlen, sym->start, mb->addrlen, sym->end,
31 sym->binding == STB_GLOBAL ? 'g' : 30 sym->binding == STB_GLOBAL ? 'g' :
32 sym->binding == STB_LOCAL ? 'l' : 'w'); 31 sym->binding == STB_LOCAL ? 'l' : 'w');
33 width = browser->width - ((mb->addrlen * 2) + 4); 32 width = browser->width - ((mb->addrlen * 2) + 4);
34 if (width > 0) 33 if (width > 0)
35 slsmg_write_nstring(sym->name, width); 34 ui_browser__write_nstring(browser, sym->name, width);
36} 35}
37 36
38/* FIXME uber-kludgy, see comment on cmd_report... */ 37/* FIXME uber-kludgy, see comment on cmd_report... */
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 402d2bd30b09..e13b48d705ef 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -81,7 +81,7 @@ static void script_browser__write(struct ui_browser *browser,
81 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 81 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
82 HE_COLORSET_NORMAL); 82 HE_COLORSET_NORMAL);
83 83
84 slsmg_write_nstring(sline->line, browser->width); 84 ui_browser__write_nstring(browser, sline->line, browser->width);
85} 85}
86 86
87static int script_browser__run(struct perf_script_browser *browser) 87static int script_browser__run(struct perf_script_browser *browser)
diff --git a/tools/perf/ui/libslang.h b/tools/perf/ui/libslang.h
index 4d54b6450f5b..db816695ad97 100644
--- a/tools/perf/ui/libslang.h
+++ b/tools/perf/ui/libslang.h
@@ -14,12 +14,15 @@
14#if SLANG_VERSION < 20104 14#if SLANG_VERSION < 20104
15#define slsmg_printf(msg, args...) \ 15#define slsmg_printf(msg, args...) \
16 SLsmg_printf((char *)(msg), ##args) 16 SLsmg_printf((char *)(msg), ##args)
17#define slsmg_vprintf(msg, vargs) \
18 SLsmg_vprintf((char *)(msg), vargs)
17#define slsmg_write_nstring(msg, len) \ 19#define slsmg_write_nstring(msg, len) \
18 SLsmg_write_nstring((char *)(msg), len) 20 SLsmg_write_nstring((char *)(msg), len)
19#define sltt_set_color(obj, name, fg, bg) \ 21#define sltt_set_color(obj, name, fg, bg) \
20 SLtt_set_color(obj,(char *)(name), (char *)(fg), (char *)(bg)) 22 SLtt_set_color(obj,(char *)(name), (char *)(fg), (char *)(bg))
21#else 23#else
22#define slsmg_printf SLsmg_printf 24#define slsmg_printf SLsmg_printf
25#define slsmg_vprintf SLsmg_vprintf
23#define slsmg_write_nstring SLsmg_write_nstring 26#define slsmg_write_nstring SLsmg_write_nstring
24#define sltt_set_color SLtt_set_color 27#define sltt_set_color SLtt_set_color
25#endif 28#endif
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index bf890f72fe80..d96ad7c8325d 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -21,7 +21,7 @@ static void ui_browser__argv_write(struct ui_browser *browser,
21 21
22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
23 HE_COLORSET_NORMAL); 23 HE_COLORSET_NORMAL);
24 slsmg_write_nstring(*arg, browser->width); 24 ui_browser__write_nstring(browser, *arg, browser->width);
25} 25}
26 26
27static int popup_menu__run(struct ui_browser *menu) 27static int popup_menu__run(struct ui_browser *menu)
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 57f3ef41c2bc..445f455dd377 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -734,15 +734,18 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
734 Dwarf_Lines *lines; 734 Dwarf_Lines *lines;
735 Dwarf_Line *line; 735 Dwarf_Line *line;
736 Dwarf_Addr addr; 736 Dwarf_Addr addr;
737 const char *fname; 737 const char *fname, *decf = NULL;
738 int lineno, ret = 0; 738 int lineno, ret = 0;
739 int decl = 0, inl;
739 Dwarf_Die die_mem, *cu_die; 740 Dwarf_Die die_mem, *cu_die;
740 size_t nlines, i; 741 size_t nlines, i;
741 742
742 /* Get the CU die */ 743 /* Get the CU die */
743 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) 744 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
744 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); 745 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
745 else 746 dwarf_decl_line(rt_die, &decl);
747 decf = dwarf_decl_file(rt_die);
748 } else
746 cu_die = rt_die; 749 cu_die = rt_die;
747 if (!cu_die) { 750 if (!cu_die) {
748 pr_debug2("Failed to get CU from given DIE.\n"); 751 pr_debug2("Failed to get CU from given DIE.\n");
@@ -773,9 +776,14 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
773 * The line is included in given function, and 776 * The line is included in given function, and
774 * no inline block includes it. 777 * no inline block includes it.
775 */ 778 */
776 if (!dwarf_haspc(rt_die, addr) || 779 if (!dwarf_haspc(rt_die, addr))
777 die_find_inlinefunc(rt_die, addr, &die_mem))
778 continue; 780 continue;
781 if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
782 dwarf_decl_line(&die_mem, &inl);
783 if (inl != decl ||
784 decf != dwarf_decl_file(&die_mem))
785 continue;
786 }
779 /* Get source line */ 787 /* Get source line */
780 fname = dwarf_linesrc(line, NULL, NULL); 788 fname = dwarf_linesrc(line, NULL, NULL);
781 789
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 04fddddc6b6f..b096ef7a240c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -588,11 +588,36 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
588 } 588 }
589} 589}
590 590
591static void apply_config_terms(struct perf_evsel *evsel) 591static void
592perf_evsel__reset_callgraph(struct perf_evsel *evsel,
593 struct callchain_param *param)
594{
595 struct perf_event_attr *attr = &evsel->attr;
596
597 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
598 if (param->record_mode == CALLCHAIN_LBR) {
599 perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
600 attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER |
601 PERF_SAMPLE_BRANCH_CALL_STACK);
602 }
603 if (param->record_mode == CALLCHAIN_DWARF) {
604 perf_evsel__reset_sample_bit(evsel, REGS_USER);
605 perf_evsel__reset_sample_bit(evsel, STACK_USER);
606 }
607}
608
609static void apply_config_terms(struct perf_evsel *evsel,
610 struct record_opts *opts)
592{ 611{
593 struct perf_evsel_config_term *term; 612 struct perf_evsel_config_term *term;
594 struct list_head *config_terms = &evsel->config_terms; 613 struct list_head *config_terms = &evsel->config_terms;
595 struct perf_event_attr *attr = &evsel->attr; 614 struct perf_event_attr *attr = &evsel->attr;
615 struct callchain_param param;
616 u32 dump_size = 0;
617 char *callgraph_buf = NULL;
618
619 /* callgraph default */
620 param.record_mode = callchain_param.record_mode;
596 621
597 list_for_each_entry(term, config_terms, list) { 622 list_for_each_entry(term, config_terms, list) {
598 switch (term->type) { 623 switch (term->type) {
@@ -610,10 +635,48 @@ static void apply_config_terms(struct perf_evsel *evsel)
610 else 635 else
611 perf_evsel__reset_sample_bit(evsel, TIME); 636 perf_evsel__reset_sample_bit(evsel, TIME);
612 break; 637 break;
638 case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
639 callgraph_buf = term->val.callgraph;
640 break;
641 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
642 dump_size = term->val.stack_user;
643 break;
613 default: 644 default:
614 break; 645 break;
615 } 646 }
616 } 647 }
648
649 /* User explicitly set per-event callgraph, clear the old setting and reset. */
650 if ((callgraph_buf != NULL) || (dump_size > 0)) {
651
652 /* parse callgraph parameters */
653 if (callgraph_buf != NULL) {
654 if (!strcmp(callgraph_buf, "no")) {
655 param.enabled = false;
656 param.record_mode = CALLCHAIN_NONE;
657 } else {
658 param.enabled = true;
659 if (parse_callchain_record(callgraph_buf, &param)) {
660 pr_err("per-event callgraph setting for %s failed. "
661 "Apply callgraph global setting for it\n",
662 evsel->name);
663 return;
664 }
665 }
666 }
667 if (dump_size > 0) {
668 dump_size = round_up(dump_size, sizeof(u64));
669 param.dump_size = dump_size;
670 }
671
672 /* If global callgraph set, clear it */
673 if (callchain_param.enabled)
674 perf_evsel__reset_callgraph(evsel, &callchain_param);
675
676 /* set perf-event callgraph */
677 if (param.enabled)
678 perf_evsel__config_callgraph(evsel, opts, &param);
679 }
617} 680}
618 681
619/* 682/*
@@ -812,7 +875,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
812 * Apply event specific term settings, 875 * Apply event specific term settings,
813 * it overloads any global configuration. 876 * it overloads any global configuration.
814 */ 877 */
815 apply_config_terms(evsel); 878 apply_config_terms(evsel, opts);
816} 879}
817 880
818static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 881static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index fdf2674ab339..93ac6b128149 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -41,6 +41,8 @@ enum {
41 PERF_EVSEL__CONFIG_TERM_PERIOD, 41 PERF_EVSEL__CONFIG_TERM_PERIOD,
42 PERF_EVSEL__CONFIG_TERM_FREQ, 42 PERF_EVSEL__CONFIG_TERM_FREQ,
43 PERF_EVSEL__CONFIG_TERM_TIME, 43 PERF_EVSEL__CONFIG_TERM_TIME,
44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
45 PERF_EVSEL__CONFIG_TERM_STACK_USER,
44 PERF_EVSEL__CONFIG_TERM_MAX, 46 PERF_EVSEL__CONFIG_TERM_MAX,
45}; 47};
46 48
@@ -51,6 +53,8 @@ struct perf_evsel_config_term {
51 u64 period; 53 u64 period;
52 u64 freq; 54 u64 freq;
53 bool time; 55 bool time;
56 char *callgraph;
57 u64 stack_user;
54 } val; 58 } val;
55}; 59};
56 60
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6bccfae334b1..08b6cd945f1e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1109,13 +1109,14 @@ void hists__inc_stats(struct hists *hists, struct hist_entry *h)
1109 1109
1110static void __hists__insert_output_entry(struct rb_root *entries, 1110static void __hists__insert_output_entry(struct rb_root *entries,
1111 struct hist_entry *he, 1111 struct hist_entry *he,
1112 u64 min_callchain_hits) 1112 u64 min_callchain_hits,
1113 bool use_callchain)
1113{ 1114{
1114 struct rb_node **p = &entries->rb_node; 1115 struct rb_node **p = &entries->rb_node;
1115 struct rb_node *parent = NULL; 1116 struct rb_node *parent = NULL;
1116 struct hist_entry *iter; 1117 struct hist_entry *iter;
1117 1118
1118 if (symbol_conf.use_callchain) 1119 if (use_callchain)
1119 callchain_param.sort(&he->sorted_chain, he->callchain, 1120 callchain_param.sort(&he->sorted_chain, he->callchain,
1120 min_callchain_hits, &callchain_param); 1121 min_callchain_hits, &callchain_param);
1121 1122
@@ -1139,6 +1140,13 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1139 struct rb_node *next; 1140 struct rb_node *next;
1140 struct hist_entry *n; 1141 struct hist_entry *n;
1141 u64 min_callchain_hits; 1142 u64 min_callchain_hits;
1143 struct perf_evsel *evsel = hists_to_evsel(hists);
1144 bool use_callchain;
1145
1146 if (evsel && !symbol_conf.show_ref_callgraph)
1147 use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
1148 else
1149 use_callchain = symbol_conf.use_callchain;
1142 1150
1143 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100); 1151 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
1144 1152
@@ -1157,7 +1165,7 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1157 n = rb_entry(next, struct hist_entry, rb_node_in); 1165 n = rb_entry(next, struct hist_entry, rb_node_in);
1158 next = rb_next(&n->rb_node_in); 1166 next = rb_next(&n->rb_node_in);
1159 1167
1160 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits); 1168 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain);
1161 hists__inc_stats(hists, n); 1169 hists__inc_stats(hists, n);
1162 1170
1163 if (!n->filtered) 1171 if (!n->filtered)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index dbf315df4220..d826e6f515db 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -614,6 +614,12 @@ do { \
614 return -EINVAL; 614 return -EINVAL;
615 } 615 }
616 break; 616 break;
617 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
618 CHECK_TYPE_VAL(STR);
619 break;
620 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
621 CHECK_TYPE_VAL(NUM);
622 break;
617 case PARSE_EVENTS__TERM_TYPE_NAME: 623 case PARSE_EVENTS__TERM_TYPE_NAME:
618 CHECK_TYPE_VAL(STR); 624 CHECK_TYPE_VAL(STR);
619 break; 625 break;
@@ -668,6 +674,12 @@ do { \
668 case PARSE_EVENTS__TERM_TYPE_TIME: 674 case PARSE_EVENTS__TERM_TYPE_TIME:
669 ADD_CONFIG_TERM(TIME, time, term->val.num); 675 ADD_CONFIG_TERM(TIME, time, term->val.num);
670 break; 676 break;
677 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
678 ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
679 break;
680 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
681 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
682 break;
671 default: 683 default:
672 break; 684 break;
673 } 685 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ce2d13a16226..a09b0e210997 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -65,6 +65,8 @@ enum {
65 PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, 65 PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ,
66 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, 66 PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
67 PARSE_EVENTS__TERM_TYPE_TIME, 67 PARSE_EVENTS__TERM_TYPE_TIME,
68 PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
69 PARSE_EVENTS__TERM_TYPE_STACKSIZE,
68}; 70};
69 71
70struct parse_events_term { 72struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 4306f5ad75c7..936d566f48d8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -185,6 +185,8 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
185freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } 185freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
186branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 186branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 187time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
188call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
189stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
188, { return ','; } 190, { return ','; }
189"/" { BEGIN(INITIAL); return '/'; } 191"/" { BEGIN(INITIAL); return '/'; }
190{name_minus} { return str(yyscanner, PE_NAME); } 192{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d85f11b8cacf..84cad054d6f7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -634,7 +634,9 @@ static char *formats_error_string(struct list_head *formats)
634{ 634{
635 struct perf_pmu_format *format; 635 struct perf_pmu_format *format;
636 char *err, *str; 636 char *err, *str;
637 static const char *static_terms = "config,config1,config2,name,period,freq,branch_type,time\n"; 637 static const char *static_terms = "config,config1,config2,name,"
638 "period,freq,branch_type,time,"
639 "call-graph,stack-size\n";
638 unsigned i = 0; 640 unsigned i = 0;
639 641
640 if (!asprintf(&str, "valid terms:")) 642 if (!asprintf(&str, "valid terms:"))
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index c0c32b050e45..7e3871606df3 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -330,6 +330,8 @@ static char *get_srcfile(struct hist_entry *e)
330 330
331 sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip), 331 sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip),
332 e->ms.sym, true); 332 e->ms.sym, true);
333 if (!strcmp(sf, SRCLINE_UNKNOWN))
334 return no_srcfile;
333 p = strchr(sf, ':'); 335 p = strchr(sf, ':');
334 if (p && *sf) { 336 if (p && *sf) {
335 *p = 0; 337 *p = 0;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b98ce51af142..a4cde92afbad 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -106,7 +106,8 @@ struct symbol_conf {
106 filter_relative, 106 filter_relative,
107 show_hist_headers, 107 show_hist_headers,
108 branch_callstack, 108 branch_callstack,
109 has_filter; 109 has_filter,
110 show_ref_callgraph;
110 const char *vmlinux_name, 111 const char *vmlinux_name,
111 *kallsyms_name, 112 *kallsyms_name,
112 *source_prefix, 113 *source_prefix,