aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-list.txt4
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/bench/bench.h20
-rw-r--r--tools/perf/bench/futex-hash.c3
-rw-r--r--tools/perf/bench/futex-lock-pi.c3
-rw-r--r--tools/perf/bench/futex-requeue.c3
-rw-r--r--tools/perf/bench/futex-wake-parallel.c3
-rw-r--r--tools/perf/bench/futex-wake.c3
-rw-r--r--tools/perf/bench/mem-functions.c4
-rw-r--r--tools/perf/bench/numa.c2
-rw-r--r--tools/perf/bench/sched-messaging.c3
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-bench.c12
-rw-r--r--tools/perf/builtin-buildid-cache.c3
-rw-r--r--tools/perf/builtin-buildid-list.c3
-rw-r--r--tools/perf/builtin-c2c.c4
-rw-r--r--tools/perf/builtin-config.c2
-rw-r--r--tools/perf/builtin-data.c9
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-ftrace.c2
-rw-r--r--tools/perf/builtin-help.c2
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kallsyms.c2
-rw-r--r--tools/perf/builtin-kmem.c4
-rw-r--r--tools/perf/builtin-kvm.c16
-rw-r--r--tools/perf/builtin-list.c2
-rw-r--r--tools/perf/builtin-lock.c6
-rw-r--r--tools/perf/builtin-mem.c6
-rw-r--r--tools/perf/builtin-probe.c6
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/builtin-sched.c6
-rw-r--r--tools/perf/builtin-script.c4
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-timechart.c7
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c25
-rw-r--r--tools/perf/builtin-version.c3
-rw-r--r--tools/perf/builtin.h58
-rw-r--r--tools/perf/perf.c11
-rw-r--r--tools/perf/tests/builtin-test.c2
-rw-r--r--tools/perf/tests/sdt.c2
-rw-r--r--tools/perf/ui/browsers/hists.c181
-rw-r--r--tools/perf/ui/stdio/hist.c86
-rw-r--r--tools/perf/util/annotate.c23
-rw-r--r--tools/perf/util/auxtrace.c4
-rw-r--r--tools/perf/util/build-id.c8
-rw-r--r--tools/perf/util/callchain.c52
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/header.c8
-rw-r--r--tools/perf/util/hist.c5
-rw-r--r--tools/perf/util/map.c3
-rw-r--r--tools/perf/util/sort.c16
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/srcline.c246
-rw-r--r--tools/perf/util/symbol-elf.c5
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.h5
-rw-r--r--tools/perf/util/trace-event-read.c4
-rw-r--r--tools/perf/util/util.h20
62 files changed, 739 insertions, 208 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 143d98df2df9..f709de54707b 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|event_glob] 11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -244,6 +244,8 @@ To limit the list use:
244 244
245. 'pmu' to print the kernel supplied PMU events. 245. 'pmu' to print the kernel supplied PMU events.
246 246
247. 'sdt' to list all Statically Defined Tracepoint events.
248
247. If none of the above is matched, it will apply the supplied glob to all 249. If none of the above is matched, it will apply the supplied glob to all
248 events, printing the ones that match. 250 events, printing the ones that match.
249 251
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index e9a61f5485eb..37a175914157 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -235,6 +235,7 @@ OPTIONS
235 sort_key can be: 235 sort_key can be:
236 - function: compare on functions (default) 236 - function: compare on functions (default)
237 - address: compare on individual code addresses 237 - address: compare on individual code addresses
238 - srcline: compare on source filename and line number
238 239
239 branch can be: 240 branch can be:
240 - branch: include last branch information in callgraph when available. 241 - branch: include last branch information in callgraph when available.
@@ -430,6 +431,10 @@ include::itrace.txt[]
430--hierarchy:: 431--hierarchy::
431 Enable hierarchical output. 432 Enable hierarchical output.
432 433
434--inline::
435 If a callgraph address belongs to an inlined function, the inline stack
436 will be printed. Each entry is function name or file/line.
437
433include::callchain-overhead-calculation.txt[] 438include::callchain-overhead-calculation.txt[]
434 439
435SEE ALSO 440SEE ALSO
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index 579a592990dd..842ab2781cdc 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -25,17 +25,17 @@
25# endif 25# endif
26#endif 26#endif
27 27
28int bench_numa(int argc, const char **argv, const char *prefix); 28int bench_numa(int argc, const char **argv);
29int bench_sched_messaging(int argc, const char **argv, const char *prefix); 29int bench_sched_messaging(int argc, const char **argv);
30int bench_sched_pipe(int argc, const char **argv, const char *prefix); 30int bench_sched_pipe(int argc, const char **argv);
31int bench_mem_memcpy(int argc, const char **argv, const char *prefix); 31int bench_mem_memcpy(int argc, const char **argv);
32int bench_mem_memset(int argc, const char **argv, const char *prefix); 32int bench_mem_memset(int argc, const char **argv);
33int bench_futex_hash(int argc, const char **argv, const char *prefix); 33int bench_futex_hash(int argc, const char **argv);
34int bench_futex_wake(int argc, const char **argv, const char *prefix); 34int bench_futex_wake(int argc, const char **argv);
35int bench_futex_wake_parallel(int argc, const char **argv, const char *prefix); 35int bench_futex_wake_parallel(int argc, const char **argv);
36int bench_futex_requeue(int argc, const char **argv, const char *prefix); 36int bench_futex_requeue(int argc, const char **argv);
37/* pi futexes */ 37/* pi futexes */
38int bench_futex_lock_pi(int argc, const char **argv, const char *prefix); 38int bench_futex_lock_pi(int argc, const char **argv);
39 39
40#define BENCH_FORMAT_DEFAULT_STR "default" 40#define BENCH_FORMAT_DEFAULT_STR "default"
41#define BENCH_FORMAT_DEFAULT 0 41#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 2499e1b0c6fb..fe16b310097f 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -114,8 +114,7 @@ static void print_summary(void)
114 (int) runtime.tv_sec); 114 (int) runtime.tv_sec);
115} 115}
116 116
117int bench_futex_hash(int argc, const char **argv, 117int bench_futex_hash(int argc, const char **argv)
118 const char *prefix __maybe_unused)
119{ 118{
120 int ret = 0; 119 int ret = 0;
121 cpu_set_t cpu; 120 cpu_set_t cpu;
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index a20814d94af1..73a1c44ea63c 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -140,8 +140,7 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr)
140 } 140 }
141} 141}
142 142
143int bench_futex_lock_pi(int argc, const char **argv, 143int bench_futex_lock_pi(int argc, const char **argv)
144 const char *prefix __maybe_unused)
145{ 144{
146 int ret = 0; 145 int ret = 0;
147 unsigned int i; 146 unsigned int i;
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 9fad1e4fcd3e..41786cbea24c 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -109,8 +109,7 @@ static void toggle_done(int sig __maybe_unused,
109 done = true; 109 done = true;
110} 110}
111 111
112int bench_futex_requeue(int argc, const char **argv, 112int bench_futex_requeue(int argc, const char **argv)
113 const char *prefix __maybe_unused)
114{ 113{
115 int ret = 0; 114 int ret = 0;
116 unsigned int i, j; 115 unsigned int i, j;
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 40f5fcf1d120..4ab12c8e016a 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -197,8 +197,7 @@ static void toggle_done(int sig __maybe_unused,
197 done = true; 197 done = true;
198} 198}
199 199
200int bench_futex_wake_parallel(int argc, const char **argv, 200int bench_futex_wake_parallel(int argc, const char **argv)
201 const char *prefix __maybe_unused)
202{ 201{
203 int ret = 0; 202 int ret = 0;
204 unsigned int i, j; 203 unsigned int i, j;
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 789490281ae3..2fa49222ef8d 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -115,8 +115,7 @@ static void toggle_done(int sig __maybe_unused,
115 done = true; 115 done = true;
116} 116}
117 117
118int bench_futex_wake(int argc, const char **argv, 118int bench_futex_wake(int argc, const char **argv)
119 const char *prefix __maybe_unused)
120{ 119{
121 int ret = 0; 120 int ret = 0;
122 unsigned int i, j; 121 unsigned int i, j;
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 52504a83b5a1..d1dea33dcfcf 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -284,7 +284,7 @@ static const char * const bench_mem_memcpy_usage[] = {
284 NULL 284 NULL
285}; 285};
286 286
287int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused) 287int bench_mem_memcpy(int argc, const char **argv)
288{ 288{
289 struct bench_mem_info info = { 289 struct bench_mem_info info = {
290 .functions = memcpy_functions, 290 .functions = memcpy_functions,
@@ -358,7 +358,7 @@ static const struct function memset_functions[] = {
358 { .name = NULL, } 358 { .name = NULL, }
359}; 359};
360 360
361int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused) 361int bench_mem_memset(int argc, const char **argv)
362{ 362{
363 struct bench_mem_info info = { 363 struct bench_mem_info info = {
364 .functions = memset_functions, 364 .functions = memset_functions,
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 6bd0581de298..1fe43bd5a012 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -1767,7 +1767,7 @@ static int bench_all(void)
1767 return 0; 1767 return 0;
1768} 1768}
1769 1769
1770int bench_numa(int argc, const char **argv, const char *prefix __maybe_unused) 1770int bench_numa(int argc, const char **argv)
1771{ 1771{
1772 init_params(&p0, "main,", argc, argv); 1772 init_params(&p0, "main,", argc, argv);
1773 argc = parse_options(argc, argv, options, bench_numa_usage, 0); 1773 argc = parse_options(argc, argv, options, bench_numa_usage, 0);
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 6a111e775210..4f961e74535b 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -260,8 +260,7 @@ static const char * const bench_sched_message_usage[] = {
260 NULL 260 NULL
261}; 261};
262 262
263int bench_sched_messaging(int argc, const char **argv, 263int bench_sched_messaging(int argc, const char **argv)
264 const char *prefix __maybe_unused)
265{ 264{
266 unsigned int i, total_children; 265 unsigned int i, total_children;
267 struct timeval start, stop, diff; 266 struct timeval start, stop, diff;
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 2243f0150d76..a152737370c5 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -76,7 +76,7 @@ static void *worker_thread(void *__tdata)
76 return NULL; 76 return NULL;
77} 77}
78 78
79int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused) 79int bench_sched_pipe(int argc, const char **argv)
80{ 80{
81 struct thread_data threads[2], *td; 81 struct thread_data threads[2], *td;
82 int pipe_1[2], pipe_2[2]; 82 int pipe_1[2], pipe_2[2];
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e54b1f9fe1ee..56a7c8d210b9 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -383,7 +383,7 @@ static const char * const annotate_usage[] = {
383 NULL 383 NULL
384}; 384};
385 385
386int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) 386int cmd_annotate(int argc, const char **argv)
387{ 387{
388 struct perf_annotate annotate = { 388 struct perf_annotate annotate = {
389 .tool = { 389 .tool = {
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index a1cddc6bbf0f..445e62881254 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -25,7 +25,7 @@
25#include <string.h> 25#include <string.h>
26#include <sys/prctl.h> 26#include <sys/prctl.h>
27 27
28typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix); 28typedef int (*bench_fn_t)(int argc, const char **argv);
29 29
30struct bench { 30struct bench {
31 const char *name; 31 const char *name;
@@ -155,7 +155,7 @@ static int bench_str2int(const char *str)
155 * to something meaningful: 155 * to something meaningful:
156 */ 156 */
157static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn, 157static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
158 int argc, const char **argv, const char *prefix) 158 int argc, const char **argv)
159{ 159{
160 int size; 160 int size;
161 char *name; 161 char *name;
@@ -171,7 +171,7 @@ static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t f
171 prctl(PR_SET_NAME, name); 171 prctl(PR_SET_NAME, name);
172 argv[0] = name; 172 argv[0] = name;
173 173
174 ret = fn(argc, argv, prefix); 174 ret = fn(argc, argv);
175 175
176 free(name); 176 free(name);
177 177
@@ -198,7 +198,7 @@ static void run_collection(struct collection *coll)
198 fflush(stdout); 198 fflush(stdout);
199 199
200 argv[1] = bench->name; 200 argv[1] = bench->name;
201 run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL); 201 run_bench(coll->name, bench->name, bench->fn, 1, argv);
202 printf("\n"); 202 printf("\n");
203 } 203 }
204} 204}
@@ -211,7 +211,7 @@ static void run_all_collections(void)
211 run_collection(coll); 211 run_collection(coll);
212} 212}
213 213
214int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 214int cmd_bench(int argc, const char **argv)
215{ 215{
216 struct collection *coll; 216 struct collection *coll;
217 int ret = 0; 217 int ret = 0;
@@ -270,7 +270,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
270 if (bench_format == BENCH_FORMAT_DEFAULT) 270 if (bench_format == BENCH_FORMAT_DEFAULT)
271 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); 271 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
272 fflush(stdout); 272 fflush(stdout);
273 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix); 273 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1);
274 goto end; 274 goto end;
275 } 275 }
276 276
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 30e2b2cb2421..94b55eee0d9b 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -276,8 +276,7 @@ static int build_id_cache__update_file(const char *filename)
276 return err; 276 return err;
277} 277}
278 278
279int cmd_buildid_cache(int argc, const char **argv, 279int cmd_buildid_cache(int argc, const char **argv)
280 const char *prefix __maybe_unused)
281{ 280{
282 struct strlist *list; 281 struct strlist *list;
283 struct str_node *pos; 282 struct str_node *pos;
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 5e914ee79eb3..26f4e608207f 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -87,8 +87,7 @@ out:
87 return 0; 87 return 0;
88} 88}
89 89
90int cmd_buildid_list(int argc, const char **argv, 90int cmd_buildid_list(int argc, const char **argv)
91 const char *prefix __maybe_unused)
92{ 91{
93 bool show_kernel = false; 92 bool show_kernel = false;
94 bool with_hits = false; 93 bool with_hits = false;
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 5cd6d7a047b9..70c2c773a2b8 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2755,12 +2755,12 @@ static int perf_c2c__record(int argc, const char **argv)
2755 pr_debug("\n"); 2755 pr_debug("\n");
2756 } 2756 }
2757 2757
2758 ret = cmd_record(i, rec_argv, NULL); 2758 ret = cmd_record(i, rec_argv);
2759 free(rec_argv); 2759 free(rec_argv);
2760 return ret; 2760 return ret;
2761} 2761}
2762 2762
2763int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused) 2763int cmd_c2c(int argc, const char **argv)
2764{ 2764{
2765 argc = parse_options(argc, argv, c2c_options, c2c_usage, 2765 argc = parse_options(argc, argv, c2c_options, c2c_usage,
2766 PARSE_OPT_STOP_AT_NON_OPTION); 2766 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 8c0d93b7c2f0..55f04f85b049 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -154,7 +154,7 @@ static int parse_config_arg(char *arg, char **var, char **value)
154 return 0; 154 return 0;
155} 155}
156 156
157int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) 157int cmd_config(int argc, const char **argv)
158{ 158{
159 int i, ret = 0; 159 int i, ret = 0;
160 struct perf_config_set *set; 160 struct perf_config_set *set;
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 7ad6e17ac6b3..0adb5f82335a 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -6,7 +6,7 @@
6#include "data-convert.h" 6#include "data-convert.h"
7#include "data-convert-bt.h" 7#include "data-convert-bt.h"
8 8
9typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); 9typedef int (*data_cmd_fn_t)(int argc, const char **argv);
10 10
11struct data_cmd { 11struct data_cmd {
12 const char *name; 12 const char *name;
@@ -50,8 +50,7 @@ static const char * const data_convert_usage[] = {
50 NULL 50 NULL
51}; 51};
52 52
53static int cmd_data_convert(int argc, const char **argv, 53static int cmd_data_convert(int argc, const char **argv)
54 const char *prefix __maybe_unused)
55{ 54{
56 const char *to_ctf = NULL; 55 const char *to_ctf = NULL;
57 struct perf_data_convert_opts opts = { 56 struct perf_data_convert_opts opts = {
@@ -98,7 +97,7 @@ static struct data_cmd data_cmds[] = {
98 { .name = NULL, }, 97 { .name = NULL, },
99}; 98};
100 99
101int cmd_data(int argc, const char **argv, const char *prefix) 100int cmd_data(int argc, const char **argv)
102{ 101{
103 struct data_cmd *cmd; 102 struct data_cmd *cmd;
104 const char *cmdstr; 103 const char *cmdstr;
@@ -118,7 +117,7 @@ int cmd_data(int argc, const char **argv, const char *prefix)
118 if (strcmp(cmd->name, cmdstr)) 117 if (strcmp(cmd->name, cmdstr))
119 continue; 118 continue;
120 119
121 return cmd->fn(argc, argv, prefix); 120 return cmd->fn(argc, argv);
122 } 121 }
123 122
124 pr_err("Unknown command: %s\n", cmdstr); 123 pr_err("Unknown command: %s\n", cmdstr);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 5e4803158672..cd2605d86984 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1321,7 +1321,7 @@ static int diff__config(const char *var, const char *value,
1321 return 0; 1321 return 0;
1322} 1322}
1323 1323
1324int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1324int cmd_diff(int argc, const char **argv)
1325{ 1325{
1326 int ret = hists__init(); 1326 int ret = hists__init();
1327 1327
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index e09c4287fe87..6d210e40d611 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -46,7 +46,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
46 return 0; 46 return 0;
47} 47}
48 48
49int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 49int cmd_evlist(int argc, const char **argv)
50{ 50{
51 struct perf_attr_details details = { .verbose = false, }; 51 struct perf_attr_details details = { .verbose = false, };
52 const struct option options[] = { 52 const struct option options[] = {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 6087295f8827..f80fb60b00b0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -304,7 +304,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
304 return -1; 304 return -1;
305} 305}
306 306
307int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused) 307int cmd_ftrace(int argc, const char **argv)
308{ 308{
309 int ret; 309 int ret;
310 struct perf_ftrace ftrace = { 310 struct perf_ftrace ftrace = {
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index aed0d844e8c2..7ae238929e95 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -418,7 +418,7 @@ static int show_html_page(const char *perf_cmd)
418 return 0; 418 return 0;
419} 419}
420 420
421int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) 421int cmd_help(int argc, const char **argv)
422{ 422{
423 bool show_all = false; 423 bool show_all = false;
424 enum help_format help_format = HELP_FORMAT_MAN; 424 enum help_format help_format = HELP_FORMAT_MAN;
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8d1d13b9bab6..42dff0b1375a 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -738,7 +738,7 @@ static int __cmd_inject(struct perf_inject *inject)
738 return ret; 738 return ret;
739} 739}
740 740
741int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) 741int cmd_inject(int argc, const char **argv)
742{ 742{
743 struct perf_inject inject = { 743 struct perf_inject inject = {
744 .tool = { 744 .tool = {
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
index 224bfc454b4a..8ff38c4eb2c0 100644
--- a/tools/perf/builtin-kallsyms.c
+++ b/tools/perf/builtin-kallsyms.c
@@ -43,7 +43,7 @@ static int __cmd_kallsyms(int argc, const char **argv)
43 return 0; 43 return 0;
44} 44}
45 45
46int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused) 46int cmd_kallsyms(int argc, const char **argv)
47{ 47{
48 const struct option options[] = { 48 const struct option options[] = {
49 OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), 49 OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index d509e74bc6e8..515587825af4 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1866,7 +1866,7 @@ static int __cmd_record(int argc, const char **argv)
1866 for (j = 1; j < (unsigned int)argc; j++, i++) 1866 for (j = 1; j < (unsigned int)argc; j++, i++)
1867 rec_argv[i] = argv[j]; 1867 rec_argv[i] = argv[j];
1868 1868
1869 return cmd_record(i, rec_argv, NULL); 1869 return cmd_record(i, rec_argv);
1870} 1870}
1871 1871
1872static int kmem_config(const char *var, const char *value, void *cb __maybe_unused) 1872static int kmem_config(const char *var, const char *value, void *cb __maybe_unused)
@@ -1885,7 +1885,7 @@ static int kmem_config(const char *var, const char *value, void *cb __maybe_unus
1885 return 0; 1885 return 0;
1886} 1886}
1887 1887
1888int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 1888int cmd_kmem(int argc, const char **argv)
1889{ 1889{
1890 const char * const default_slab_sort = "frag,hit,bytes"; 1890 const char * const default_slab_sort = "frag,hit,bytes";
1891 const char * const default_page_sort = "bytes,hit"; 1891 const char * const default_page_sort = "bytes,hit";
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 18e6c38864bc..38b409173693 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1209,7 +1209,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1209 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED); 1209 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
1210 1210
1211 record_usage = kvm_stat_record_usage; 1211 record_usage = kvm_stat_record_usage;
1212 return cmd_record(i, rec_argv, NULL); 1212 return cmd_record(i, rec_argv);
1213} 1213}
1214 1214
1215static int 1215static int
@@ -1477,7 +1477,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1477#endif 1477#endif
1478 1478
1479perf_stat: 1479perf_stat:
1480 return cmd_stat(argc, argv, NULL); 1480 return cmd_stat(argc, argv);
1481} 1481}
1482#endif /* HAVE_KVM_STAT_SUPPORT */ 1482#endif /* HAVE_KVM_STAT_SUPPORT */
1483 1483
@@ -1496,7 +1496,7 @@ static int __cmd_record(const char *file_name, int argc, const char **argv)
1496 1496
1497 BUG_ON(i != rec_argc); 1497 BUG_ON(i != rec_argc);
1498 1498
1499 return cmd_record(i, rec_argv, NULL); 1499 return cmd_record(i, rec_argv);
1500} 1500}
1501 1501
1502static int __cmd_report(const char *file_name, int argc, const char **argv) 1502static int __cmd_report(const char *file_name, int argc, const char **argv)
@@ -1514,7 +1514,7 @@ static int __cmd_report(const char *file_name, int argc, const char **argv)
1514 1514
1515 BUG_ON(i != rec_argc); 1515 BUG_ON(i != rec_argc);
1516 1516
1517 return cmd_report(i, rec_argv, NULL); 1517 return cmd_report(i, rec_argv);
1518} 1518}
1519 1519
1520static int 1520static int
@@ -1533,10 +1533,10 @@ __cmd_buildid_list(const char *file_name, int argc, const char **argv)
1533 1533
1534 BUG_ON(i != rec_argc); 1534 BUG_ON(i != rec_argc);
1535 1535
1536 return cmd_buildid_list(i, rec_argv, NULL); 1536 return cmd_buildid_list(i, rec_argv);
1537} 1537}
1538 1538
1539int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 1539int cmd_kvm(int argc, const char **argv)
1540{ 1540{
1541 const char *file_name = NULL; 1541 const char *file_name = NULL;
1542 const struct option kvm_options[] = { 1542 const struct option kvm_options[] = {
@@ -1591,9 +1591,9 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1591 else if (!strncmp(argv[0], "rep", 3)) 1591 else if (!strncmp(argv[0], "rep", 3))
1592 return __cmd_report(file_name, argc, argv); 1592 return __cmd_report(file_name, argc, argv);
1593 else if (!strncmp(argv[0], "diff", 4)) 1593 else if (!strncmp(argv[0], "diff", 4))
1594 return cmd_diff(argc, argv, NULL); 1594 return cmd_diff(argc, argv);
1595 else if (!strncmp(argv[0], "top", 3)) 1595 else if (!strncmp(argv[0], "top", 3))
1596 return cmd_top(argc, argv, NULL); 1596 return cmd_top(argc, argv);
1597 else if (!strncmp(argv[0], "buildid-list", 12)) 1597 else if (!strncmp(argv[0], "buildid-list", 12))
1598 return __cmd_buildid_list(file_name, argc, argv); 1598 return __cmd_buildid_list(file_name, argc, argv);
1599#ifdef HAVE_KVM_STAT_SUPPORT 1599#ifdef HAVE_KVM_STAT_SUPPORT
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index be9195e95c78..4bf2cb4d25aa 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -20,7 +20,7 @@
20static bool desc_flag = true; 20static bool desc_flag = true;
21static bool details_flag; 21static bool details_flag;
22 22
23int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 23int cmd_list(int argc, const char **argv)
24{ 24{
25 int i; 25 int i;
26 bool raw_dump = false; 26 bool raw_dump = false;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index e992e7206993..b686fb6759da 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -941,12 +941,12 @@ static int __cmd_record(int argc, const char **argv)
941 941
942 BUG_ON(i != rec_argc); 942 BUG_ON(i != rec_argc);
943 943
944 ret = cmd_record(i, rec_argv, NULL); 944 ret = cmd_record(i, rec_argv);
945 free(rec_argv); 945 free(rec_argv);
946 return ret; 946 return ret;
947} 947}
948 948
949int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 949int cmd_lock(int argc, const char **argv)
950{ 950{
951 const struct option lock_options[] = { 951 const struct option lock_options[] = {
952 OPT_STRING('i', "input", &input_name, "file", "input file name"), 952 OPT_STRING('i', "input", &input_name, "file", "input file name"),
@@ -1009,7 +1009,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
1009 rc = __cmd_report(false); 1009 rc = __cmd_report(false);
1010 } else if (!strcmp(argv[0], "script")) { 1010 } else if (!strcmp(argv[0], "script")) {
1011 /* Aliased to 'perf script' */ 1011 /* Aliased to 'perf script' */
1012 return cmd_script(argc, argv, prefix); 1012 return cmd_script(argc, argv);
1013 } else if (!strcmp(argv[0], "info")) { 1013 } else if (!strcmp(argv[0], "info")) {
1014 if (argc) { 1014 if (argc) {
1015 argc = parse_options(argc, argv, 1015 argc = parse_options(argc, argv,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 030a6cfdda59..643f4faac0d0 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -129,7 +129,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
129 pr_debug("\n"); 129 pr_debug("\n");
130 } 130 }
131 131
132 ret = cmd_record(i, rec_argv, NULL); 132 ret = cmd_record(i, rec_argv);
133 free(rec_argv); 133 free(rec_argv);
134 return ret; 134 return ret;
135} 135}
@@ -256,7 +256,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
256 for (j = 1; j < argc; j++, i++) 256 for (j = 1; j < argc; j++, i++)
257 rep_argv[i] = argv[j]; 257 rep_argv[i] = argv[j];
258 258
259 ret = cmd_report(i, rep_argv, NULL); 259 ret = cmd_report(i, rep_argv);
260 free(rep_argv); 260 free(rep_argv);
261 return ret; 261 return ret;
262} 262}
@@ -330,7 +330,7 @@ error:
330 return ret; 330 return ret;
331} 331}
332 332
333int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) 333int cmd_mem(int argc, const char **argv)
334{ 334{
335 struct stat st; 335 struct stat st;
336 struct perf_mem mem = { 336 struct perf_mem mem = {
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 51cdc230f6ca..d7360c2bda13 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -468,7 +468,7 @@ out:
468 468
469 469
470static int 470static int
471__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 471__cmd_probe(int argc, const char **argv)
472{ 472{
473 const char * const probe_usage[] = { 473 const char * const probe_usage[] = {
474 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 474 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -687,13 +687,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
687 return 0; 687 return 0;
688} 688}
689 689
690int cmd_probe(int argc, const char **argv, const char *prefix) 690int cmd_probe(int argc, const char **argv)
691{ 691{
692 int ret; 692 int ret;
693 693
694 ret = init_params(); 694 ret = init_params();
695 if (!ret) { 695 if (!ret) {
696 ret = __cmd_probe(argc, argv, prefix); 696 ret = __cmd_probe(argc, argv);
697 cleanup_params(); 697 cleanup_params();
698 } 698 }
699 699
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 04faef79a548..3191ab063852 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1667,7 +1667,7 @@ static struct option __record_options[] = {
1667 1667
1668struct option *record_options = __record_options; 1668struct option *record_options = __record_options;
1669 1669
1670int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 1670int cmd_record(int argc, const char **argv)
1671{ 1671{
1672 int err; 1672 int err;
1673 struct record *rec = &record; 1673 struct record *rec = &record;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5ab8117c3bfd..c18158b83eb1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -681,7 +681,7 @@ const char report_callchain_help[] = "Display call graph (stack chain/backtrace)
681 CALLCHAIN_REPORT_HELP 681 CALLCHAIN_REPORT_HELP
682 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; 682 "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
683 683
684int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 684int cmd_report(int argc, const char **argv)
685{ 685{
686 struct perf_session *session; 686 struct perf_session *session;
687 struct itrace_synth_opts itrace_synth_opts = { .set = 0, }; 687 struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
@@ -845,6 +845,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
845 stdio__config_color, "always"), 845 stdio__config_color, "always"),
846 OPT_STRING(0, "time", &report.time_str, "str", 846 OPT_STRING(0, "time", &report.time_str, "str",
847 "Time span of interest (start,stop)"), 847 "Time span of interest (start,stop)"),
848 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
849 "Show inline function"),
848 OPT_END() 850 OPT_END()
849 }; 851 };
850 struct perf_data_file file = { 852 struct perf_data_file file = {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b92c4d97192c..79833e226789 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -3272,10 +3272,10 @@ static int __cmd_record(int argc, const char **argv)
3272 3272
3273 BUG_ON(i != rec_argc); 3273 BUG_ON(i != rec_argc);
3274 3274
3275 return cmd_record(i, rec_argv, NULL); 3275 return cmd_record(i, rec_argv);
3276} 3276}
3277 3277
3278int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 3278int cmd_sched(int argc, const char **argv)
3279{ 3279{
3280 const char default_sort_order[] = "avg, max, switch, runtime"; 3280 const char default_sort_order[] = "avg, max, switch, runtime";
3281 struct perf_sched sched = { 3281 struct perf_sched sched = {
@@ -3412,7 +3412,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
3412 * Aliased to 'perf script' for now: 3412 * Aliased to 'perf script' for now:
3413 */ 3413 */
3414 if (!strcmp(argv[0], "script")) 3414 if (!strcmp(argv[0], "script"))
3415 return cmd_script(argc, argv, prefix); 3415 return cmd_script(argc, argv);
3416 3416
3417 if (!strncmp(argv[0], "rec", 3)) { 3417 if (!strncmp(argv[0], "rec", 3)) {
3418 return __cmd_record(argc, argv); 3418 return __cmd_record(argc, argv);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index c98e16689b57..46acc8ece41f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2359,7 +2359,7 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
2359 return set_maps(script); 2359 return set_maps(script);
2360} 2360}
2361 2361
2362int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 2362int cmd_script(int argc, const char **argv)
2363{ 2363{
2364 bool show_full_info = false; 2364 bool show_full_info = false;
2365 bool header = false; 2365 bool header = false;
@@ -2504,7 +2504,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2504 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 2504 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2505 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 2505 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
2506 if (!rec_script_path) 2506 if (!rec_script_path)
2507 return cmd_record(argc, argv, NULL); 2507 return cmd_record(argc, argv);
2508 } 2508 }
2509 2509
2510 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { 2510 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 01b589e3c3a6..2158ea14da57 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -2478,7 +2478,7 @@ static void setup_system_wide(int forks)
2478 } 2478 }
2479} 2479}
2480 2480
2481int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 2481int cmd_stat(int argc, const char **argv)
2482{ 2482{
2483 const char * const stat_usage[] = { 2483 const char * const stat_usage[] = {
2484 "perf stat [<options>] [<command>]", 2484 "perf stat [<options>] [<command>]",
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index fbd7c6c695b8..fafdb44b8bcb 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1773,7 +1773,7 @@ static int timechart__io_record(int argc, const char **argv)
1773 for (i = 0; i < (unsigned int)argc; i++) 1773 for (i = 0; i < (unsigned int)argc; i++)
1774 *p++ = argv[i]; 1774 *p++ = argv[i];
1775 1775
1776 return cmd_record(rec_argc, rec_argv, NULL); 1776 return cmd_record(rec_argc, rec_argv);
1777} 1777}
1778 1778
1779 1779
@@ -1864,7 +1864,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar
1864 for (j = 0; j < (unsigned int)argc; j++) 1864 for (j = 0; j < (unsigned int)argc; j++)
1865 *p++ = argv[j]; 1865 *p++ = argv[j];
1866 1866
1867 return cmd_record(rec_argc, rec_argv, NULL); 1867 return cmd_record(rec_argc, rec_argv);
1868} 1868}
1869 1869
1870static int 1870static int
@@ -1917,8 +1917,7 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
1917 return 0; 1917 return 0;
1918} 1918}
1919 1919
1920int cmd_timechart(int argc, const char **argv, 1920int cmd_timechart(int argc, const char **argv)
1921 const char *prefix __maybe_unused)
1922{ 1921{
1923 struct timechart tchart = { 1922 struct timechart tchart = {
1924 .tool = { 1923 .tool = {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ab9077915763..a0c97c70ec81 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1075,7 +1075,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
1075const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP 1075const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP
1076 "\n\t\t\t\tDefault: fp,graph,0.5,caller,function"; 1076 "\n\t\t\t\tDefault: fp,graph,0.5,caller,function";
1077 1077
1078int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1078int cmd_top(int argc, const char **argv)
1079{ 1079{
1080 char errbuf[BUFSIZ]; 1080 char errbuf[BUFSIZ];
1081 struct perf_top top = { 1081 struct perf_top top = {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 912fedc5b42d..c88f9f215e6f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1653,15 +1653,17 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1653 1653
1654 ttrace = thread__priv(thread); 1654 ttrace = thread__priv(thread);
1655 if (!ttrace) 1655 if (!ttrace)
1656 goto out; 1656 goto out_put;
1657 1657
1658 filename_len = strlen(filename); 1658 filename_len = strlen(filename);
1659 if (filename_len == 0)
1660 goto out_put;
1659 1661
1660 if (ttrace->filename.namelen < filename_len) { 1662 if (ttrace->filename.namelen < filename_len) {
1661 char *f = realloc(ttrace->filename.name, filename_len + 1); 1663 char *f = realloc(ttrace->filename.name, filename_len + 1);
1662 1664
1663 if (f == NULL) 1665 if (f == NULL)
1664 goto out; 1666 goto out_put;
1665 1667
1666 ttrace->filename.namelen = filename_len; 1668 ttrace->filename.namelen = filename_len;
1667 ttrace->filename.name = f; 1669 ttrace->filename.name = f;
@@ -1671,12 +1673,12 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1671 ttrace->filename.pending_open = true; 1673 ttrace->filename.pending_open = true;
1672 1674
1673 if (!ttrace->filename.ptr) 1675 if (!ttrace->filename.ptr)
1674 goto out; 1676 goto out_put;
1675 1677
1676 entry_str_len = strlen(ttrace->entry_str); 1678 entry_str_len = strlen(ttrace->entry_str);
1677 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */ 1679 remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
1678 if (remaining_space <= 0) 1680 if (remaining_space <= 0)
1679 goto out; 1681 goto out_put;
1680 1682
1681 if (filename_len > (size_t)remaining_space) { 1683 if (filename_len > (size_t)remaining_space) {
1682 filename += filename_len - remaining_space; 1684 filename += filename_len - remaining_space;
@@ -1690,6 +1692,8 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1690 1692
1691 ttrace->filename.ptr = 0; 1693 ttrace->filename.ptr = 0;
1692 ttrace->filename.entry_str_pos = 0; 1694 ttrace->filename.entry_str_pos = 0;
1695out_put:
1696 thread__put(thread);
1693out: 1697out:
1694 return 0; 1698 return 0;
1695} 1699}
@@ -1710,6 +1714,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
1710 1714
1711 ttrace->runtime_ms += runtime_ms; 1715 ttrace->runtime_ms += runtime_ms;
1712 trace->runtime_ms += runtime_ms; 1716 trace->runtime_ms += runtime_ms;
1717out_put:
1713 thread__put(thread); 1718 thread__put(thread);
1714 return 0; 1719 return 0;
1715 1720
@@ -1720,8 +1725,7 @@ out_dump:
1720 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 1725 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
1721 runtime, 1726 runtime,
1722 perf_evsel__intval(evsel, sample, "vruntime")); 1727 perf_evsel__intval(evsel, sample, "vruntime"));
1723 thread__put(thread); 1728 goto out_put;
1724 return 0;
1725} 1729}
1726 1730
1727static void bpf_output__printer(enum binary_printer_ops op, 1731static void bpf_output__printer(enum binary_printer_ops op,
@@ -1920,7 +1924,7 @@ static int trace__process_sample(struct perf_tool *tool,
1920 1924
1921 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1925 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1922 if (thread && thread__is_filtered(thread)) 1926 if (thread && thread__is_filtered(thread))
1923 return 0; 1927 goto out;
1924 1928
1925 trace__set_base_time(trace, evsel, sample); 1929 trace__set_base_time(trace, evsel, sample);
1926 1930
@@ -1928,7 +1932,8 @@ static int trace__process_sample(struct perf_tool *tool,
1928 ++trace->nr_events; 1932 ++trace->nr_events;
1929 handler(trace, evsel, event, sample); 1933 handler(trace, evsel, event, sample);
1930 } 1934 }
1931 1935out:
1936 thread__put(thread);
1932 return err; 1937 return err;
1933} 1938}
1934 1939
@@ -1988,7 +1993,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv)
1988 for (i = 0; i < (unsigned int)argc; i++) 1993 for (i = 0; i < (unsigned int)argc; i++)
1989 rec_argv[j++] = argv[i]; 1994 rec_argv[j++] = argv[i];
1990 1995
1991 return cmd_record(j, rec_argv, NULL); 1996 return cmd_record(j, rec_argv);
1992} 1997}
1993 1998
1994static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); 1999static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
@@ -2786,7 +2791,7 @@ out:
2786 return err; 2791 return err;
2787} 2792}
2788 2793
2789int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2794int cmd_trace(int argc, const char **argv)
2790{ 2795{
2791 const char *trace_usage[] = { 2796 const char *trace_usage[] = {
2792 "perf trace [<options>] [<command>]", 2797 "perf trace [<options>] [<command>]",
diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c
index 9b10cda6b6dc..b9a095b1db99 100644
--- a/tools/perf/builtin-version.c
+++ b/tools/perf/builtin-version.c
@@ -2,8 +2,7 @@
2#include "builtin.h" 2#include "builtin.h"
3#include "perf.h" 3#include "perf.h"
4 4
5int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused, 5int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused)
6 const char *prefix __maybe_unused)
7{ 6{
8 printf("perf version %s\n", perf_version_string); 7 printf("perf version %s\n", perf_version_string);
9 return 0; 8 return 0;
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 036e1e35b1a8..26669bf9129c 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -13,35 +13,35 @@ void prune_packed_objects(int);
13int read_line_with_nul(char *buf, int size, FILE *file); 13int read_line_with_nul(char *buf, int size, FILE *file);
14int check_pager_config(const char *cmd); 14int check_pager_config(const char *cmd);
15 15
16int cmd_annotate(int argc, const char **argv, const char *prefix); 16int cmd_annotate(int argc, const char **argv);
17int cmd_bench(int argc, const char **argv, const char *prefix); 17int cmd_bench(int argc, const char **argv);
18int cmd_buildid_cache(int argc, const char **argv, const char *prefix); 18int cmd_buildid_cache(int argc, const char **argv);
19int cmd_buildid_list(int argc, const char **argv, const char *prefix); 19int cmd_buildid_list(int argc, const char **argv);
20int cmd_config(int argc, const char **argv, const char *prefix); 20int cmd_config(int argc, const char **argv);
21int cmd_c2c(int argc, const char **argv, const char *prefix); 21int cmd_c2c(int argc, const char **argv);
22int cmd_diff(int argc, const char **argv, const char *prefix); 22int cmd_diff(int argc, const char **argv);
23int cmd_evlist(int argc, const char **argv, const char *prefix); 23int cmd_evlist(int argc, const char **argv);
24int cmd_help(int argc, const char **argv, const char *prefix); 24int cmd_help(int argc, const char **argv);
25int cmd_sched(int argc, const char **argv, const char *prefix); 25int cmd_sched(int argc, const char **argv);
26int cmd_kallsyms(int argc, const char **argv, const char *prefix); 26int cmd_kallsyms(int argc, const char **argv);
27int cmd_list(int argc, const char **argv, const char *prefix); 27int cmd_list(int argc, const char **argv);
28int cmd_record(int argc, const char **argv, const char *prefix); 28int cmd_record(int argc, const char **argv);
29int cmd_report(int argc, const char **argv, const char *prefix); 29int cmd_report(int argc, const char **argv);
30int cmd_stat(int argc, const char **argv, const char *prefix); 30int cmd_stat(int argc, const char **argv);
31int cmd_timechart(int argc, const char **argv, const char *prefix); 31int cmd_timechart(int argc, const char **argv);
32int cmd_top(int argc, const char **argv, const char *prefix); 32int cmd_top(int argc, const char **argv);
33int cmd_script(int argc, const char **argv, const char *prefix); 33int cmd_script(int argc, const char **argv);
34int cmd_version(int argc, const char **argv, const char *prefix); 34int cmd_version(int argc, const char **argv);
35int cmd_probe(int argc, const char **argv, const char *prefix); 35int cmd_probe(int argc, const char **argv);
36int cmd_kmem(int argc, const char **argv, const char *prefix); 36int cmd_kmem(int argc, const char **argv);
37int cmd_lock(int argc, const char **argv, const char *prefix); 37int cmd_lock(int argc, const char **argv);
38int cmd_kvm(int argc, const char **argv, const char *prefix); 38int cmd_kvm(int argc, const char **argv);
39int cmd_test(int argc, const char **argv, const char *prefix); 39int cmd_test(int argc, const char **argv);
40int cmd_trace(int argc, const char **argv, const char *prefix); 40int cmd_trace(int argc, const char **argv);
41int cmd_inject(int argc, const char **argv, const char *prefix); 41int cmd_inject(int argc, const char **argv);
42int cmd_mem(int argc, const char **argv, const char *prefix); 42int cmd_mem(int argc, const char **argv);
43int cmd_data(int argc, const char **argv, const char *prefix); 43int cmd_data(int argc, const char **argv);
44int cmd_ftrace(int argc, const char **argv, const char *prefix); 44int cmd_ftrace(int argc, const char **argv);
45 45
46int find_scripts(char **scripts_array, char **scripts_path_array); 46int find_scripts(char **scripts_array, char **scripts_path_array);
47#endif 47#endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 6d5479e03e0d..4b283d18e158 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -34,7 +34,7 @@ const char *input_name;
34 34
35struct cmd_struct { 35struct cmd_struct {
36 const char *cmd; 36 const char *cmd;
37 int (*fn)(int, const char **, const char *); 37 int (*fn)(int, const char **);
38 int option; 38 int option;
39}; 39};
40 40
@@ -339,13 +339,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
339{ 339{
340 int status; 340 int status;
341 struct stat st; 341 struct stat st;
342 const char *prefix;
343 char sbuf[STRERR_BUFSIZE]; 342 char sbuf[STRERR_BUFSIZE];
344 343
345 prefix = NULL;
346 if (p->option & RUN_SETUP)
347 prefix = NULL; /* setup_perf_directory(); */
348
349 if (use_browser == -1) 344 if (use_browser == -1)
350 use_browser = check_browser_config(p->cmd); 345 use_browser = check_browser_config(p->cmd);
351 346
@@ -356,7 +351,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
356 commit_pager_choice(); 351 commit_pager_choice();
357 352
358 perf_env__set_cmdline(&perf_env, argc, argv); 353 perf_env__set_cmdline(&perf_env, argc, argv);
359 status = p->fn(argc, argv, prefix); 354 status = p->fn(argc, argv);
360 perf_config__exit(); 355 perf_config__exit();
361 exit_browser(status); 356 exit_browser(status);
362 perf_env__exit(&perf_env); 357 perf_env__exit(&perf_env);
@@ -566,7 +561,7 @@ int main(int argc, const char **argv)
566#ifdef HAVE_LIBAUDIT_SUPPORT 561#ifdef HAVE_LIBAUDIT_SUPPORT
567 setup_path(); 562 setup_path();
568 argv[0] = "trace"; 563 argv[0] = "trace";
569 return cmd_trace(argc, argv, NULL); 564 return cmd_trace(argc, argv);
570#else 565#else
571 fprintf(stderr, 566 fprintf(stderr,
572 "trace command not available: missing audit-libs devel package at build time.\n"); 567 "trace command not available: missing audit-libs devel package at build time.\n");
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 86822969e8a8..e6d7876c94c2 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -464,7 +464,7 @@ static int perf_test__list(int argc, const char **argv)
464 return 0; 464 return 0;
465} 465}
466 466
467int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) 467int cmd_test(int argc, const char **argv)
468{ 468{
469 const char *test_usage[] = { 469 const char *test_usage[] = {
470 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 470 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
index f59d210e1baf..26e5b7a0b839 100644
--- a/tools/perf/tests/sdt.c
+++ b/tools/perf/tests/sdt.c
@@ -43,7 +43,7 @@ static char *get_self_path(void)
43{ 43{
44 char *buf = calloc(PATH_MAX, sizeof(char)); 44 char *buf = calloc(PATH_MAX, sizeof(char));
45 45
46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) { 46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX - 1) < 0) {
47 pr_debug("Failed to get correct path of perf\n"); 47 pr_debug("Failed to get correct path of perf\n");
48 free(buf); 48 free(buf);
49 return NULL; 49 return NULL;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 2dc82bec10c0..da24072bb76e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -144,9 +144,60 @@ static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
144 cl->unfolded = unfold ? cl->has_children : false; 144 cl->unfolded = unfold ? cl->has_children : false;
145} 145}
146 146
147static struct inline_node *inline_node__create(struct map *map, u64 ip)
148{
149 struct dso *dso;
150 struct inline_node *node;
151
152 if (map == NULL)
153 return NULL;
154
155 dso = map->dso;
156 if (dso == NULL)
157 return NULL;
158
159 if (dso->kernel != DSO_TYPE_USER)
160 return NULL;
161
162 node = dso__parse_addr_inlines(dso,
163 map__rip_2objdump(map, ip));
164
165 return node;
166}
167
168static int inline__count_rows(struct inline_node *node)
169{
170 struct inline_list *ilist;
171 int i = 0;
172
173 if (node == NULL)
174 return 0;
175
176 list_for_each_entry(ilist, &node->val, list) {
177 if ((ilist->filename != NULL) || (ilist->funcname != NULL))
178 i++;
179 }
180
181 return i;
182}
183
184static int callchain_list__inline_rows(struct callchain_list *chain)
185{
186 struct inline_node *node;
187 int rows;
188
189 node = inline_node__create(chain->ms.map, chain->ip);
190 if (node == NULL)
191 return 0;
192
193 rows = inline__count_rows(node);
194 inline_node__delete(node);
195 return rows;
196}
197
147static int callchain_node__count_rows_rb_tree(struct callchain_node *node) 198static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
148{ 199{
149 int n = 0; 200 int n = 0, inline_rows;
150 struct rb_node *nd; 201 struct rb_node *nd;
151 202
152 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) { 203 for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
@@ -156,6 +207,13 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
156 207
157 list_for_each_entry(chain, &child->val, list) { 208 list_for_each_entry(chain, &child->val, list) {
158 ++n; 209 ++n;
210
211 if (symbol_conf.inline_name) {
212 inline_rows =
213 callchain_list__inline_rows(chain);
214 n += inline_rows;
215 }
216
159 /* We need this because we may not have children */ 217 /* We need this because we may not have children */
160 folded_sign = callchain_list__folded(chain); 218 folded_sign = callchain_list__folded(chain);
161 if (folded_sign == '+') 219 if (folded_sign == '+')
@@ -207,7 +265,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
207{ 265{
208 struct callchain_list *chain; 266 struct callchain_list *chain;
209 bool unfolded = false; 267 bool unfolded = false;
210 int n = 0; 268 int n = 0, inline_rows;
211 269
212 if (callchain_param.mode == CHAIN_FLAT) 270 if (callchain_param.mode == CHAIN_FLAT)
213 return callchain_node__count_flat_rows(node); 271 return callchain_node__count_flat_rows(node);
@@ -216,6 +274,11 @@ static int callchain_node__count_rows(struct callchain_node *node)
216 274
217 list_for_each_entry(chain, &node->val, list) { 275 list_for_each_entry(chain, &node->val, list) {
218 ++n; 276 ++n;
277 if (symbol_conf.inline_name) {
278 inline_rows = callchain_list__inline_rows(chain);
279 n += inline_rows;
280 }
281
219 unfolded = chain->unfolded; 282 unfolded = chain->unfolded;
220 } 283 }
221 284
@@ -362,6 +425,19 @@ static void hist_entry__init_have_children(struct hist_entry *he)
362 he->init_have_children = true; 425 he->init_have_children = true;
363} 426}
364 427
428static void hist_entry_init_inline_node(struct hist_entry *he)
429{
430 if (he->inline_node)
431 return;
432
433 he->inline_node = inline_node__create(he->ms.map, he->ip);
434
435 if (he->inline_node == NULL)
436 return;
437
438 he->has_children = true;
439}
440
365static bool hist_browser__toggle_fold(struct hist_browser *browser) 441static bool hist_browser__toggle_fold(struct hist_browser *browser)
366{ 442{
367 struct hist_entry *he = browser->he_selection; 443 struct hist_entry *he = browser->he_selection;
@@ -393,7 +469,12 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
393 469
394 if (he->unfolded) { 470 if (he->unfolded) {
395 if (he->leaf) 471 if (he->leaf)
396 he->nr_rows = callchain__count_rows(&he->sorted_chain); 472 if (he->inline_node)
473 he->nr_rows = inline__count_rows(
474 he->inline_node);
475 else
476 he->nr_rows = callchain__count_rows(
477 &he->sorted_chain);
397 else 478 else
398 he->nr_rows = hierarchy_count_rows(browser, he, false); 479 he->nr_rows = hierarchy_count_rows(browser, he, false);
399 480
@@ -753,6 +834,71 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u
753 834
754#define LEVEL_OFFSET_STEP 3 835#define LEVEL_OFFSET_STEP 3
755 836
837static int hist_browser__show_inline(struct hist_browser *browser,
838 struct inline_node *node,
839 unsigned short row,
840 int offset)
841{
842 struct inline_list *ilist;
843 char buf[1024];
844 int color, width, first_row;
845
846 first_row = row;
847 width = browser->b.width - (LEVEL_OFFSET_STEP + 2);
848 list_for_each_entry(ilist, &node->val, list) {
849 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
850 color = HE_COLORSET_NORMAL;
851 if (ui_browser__is_current_entry(&browser->b, row))
852 color = HE_COLORSET_SELECTED;
853
854 if (callchain_param.key == CCKEY_ADDRESS ||
855 callchain_param.key == CCKEY_SRCLINE) {
856 if (ilist->filename != NULL)
857 scnprintf(buf, sizeof(buf),
858 "%s:%d (inline)",
859 ilist->filename,
860 ilist->line_nr);
861 else
862 scnprintf(buf, sizeof(buf), "??");
863 } else if (ilist->funcname != NULL)
864 scnprintf(buf, sizeof(buf), "%s (inline)",
865 ilist->funcname);
866 else if (ilist->filename != NULL)
867 scnprintf(buf, sizeof(buf),
868 "%s:%d (inline)",
869 ilist->filename,
870 ilist->line_nr);
871 else
872 scnprintf(buf, sizeof(buf), "??");
873
874 ui_browser__set_color(&browser->b, color);
875 hist_browser__gotorc(browser, row, 0);
876 ui_browser__write_nstring(&browser->b, " ",
877 LEVEL_OFFSET_STEP + offset);
878 ui_browser__write_nstring(&browser->b, buf, width);
879 row++;
880 }
881 }
882
883 return row - first_row;
884}
885
886static size_t show_inline_list(struct hist_browser *browser, struct map *map,
887 u64 ip, int row, int offset)
888{
889 struct inline_node *node;
890 int ret;
891
892 node = inline_node__create(map, ip);
893 if (node == NULL)
894 return 0;
895
896 ret = hist_browser__show_inline(browser, node, row, offset);
897
898 inline_node__delete(node);
899 return ret;
900}
901
756static int hist_browser__show_callchain_list(struct hist_browser *browser, 902static int hist_browser__show_callchain_list(struct hist_browser *browser,
757 struct callchain_node *node, 903 struct callchain_node *node,
758 struct callchain_list *chain, 904 struct callchain_list *chain,
@@ -764,6 +910,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
764 char bf[1024], *alloc_str; 910 char bf[1024], *alloc_str;
765 char buf[64], *alloc_str2; 911 char buf[64], *alloc_str2;
766 const char *str; 912 const char *str;
913 int inline_rows = 0, ret = 1;
767 914
768 if (arg->row_offset != 0) { 915 if (arg->row_offset != 0) {
769 arg->row_offset--; 916 arg->row_offset--;
@@ -801,10 +948,15 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
801 } 948 }
802 949
803 print(browser, chain, str, offset, row, arg); 950 print(browser, chain, str, offset, row, arg);
804
805 free(alloc_str); 951 free(alloc_str);
806 free(alloc_str2); 952 free(alloc_str2);
807 return 1; 953
954 if (symbol_conf.inline_name) {
955 inline_rows = show_inline_list(browser, chain->ms.map,
956 chain->ip, row + 1, offset);
957 }
958
959 return ret + inline_rows;
808} 960}
809 961
810static bool check_percent_display(struct rb_node *node, u64 parent_total) 962static bool check_percent_display(struct rb_node *node, u64 parent_total)
@@ -1228,6 +1380,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1228 folded_sign = hist_entry__folded(entry); 1380 folded_sign = hist_entry__folded(entry);
1229 } 1381 }
1230 1382
1383 if (symbol_conf.inline_name &&
1384 (!entry->has_children)) {
1385 hist_entry_init_inline_node(entry);
1386 folded_sign = hist_entry__folded(entry);
1387 }
1388
1231 if (row_offset == 0) { 1389 if (row_offset == 0) {
1232 struct hpp_arg arg = { 1390 struct hpp_arg arg = {
1233 .b = &browser->b, 1391 .b = &browser->b,
@@ -1259,7 +1417,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1259 } 1417 }
1260 1418
1261 if (first) { 1419 if (first) {
1262 if (symbol_conf.use_callchain) { 1420 if (symbol_conf.use_callchain ||
1421 symbol_conf.inline_name) {
1263 ui_browser__printf(&browser->b, "%c ", folded_sign); 1422 ui_browser__printf(&browser->b, "%c ", folded_sign);
1264 width -= 2; 1423 width -= 2;
1265 } 1424 }
@@ -1301,8 +1460,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1301 .is_current_entry = current_entry, 1460 .is_current_entry = current_entry,
1302 }; 1461 };
1303 1462
1304 printed += hist_browser__show_callchain(browser, entry, 1, row, 1463 if (entry->inline_node)
1305 hist_browser__show_callchain_entry, &arg, 1464 printed += hist_browser__show_inline(browser,
1465 entry->inline_node, row, 0);
1466 else
1467 printed += hist_browser__show_callchain(browser,
1468 entry, 1, row,
1469 hist_browser__show_callchain_entry,
1470 &arg,
1306 hist_browser__check_output_full); 1471 hist_browser__check_output_full);
1307 } 1472 }
1308 1473
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 668f4aecf2e6..d52d5f64ea89 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -17,6 +17,67 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
17 return ret; 17 return ret;
18} 18}
19 19
20static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
21 int depth, int depth_mask, FILE *fp)
22{
23 struct dso *dso;
24 struct inline_node *node;
25 struct inline_list *ilist;
26 int ret = 0, i;
27
28 if (map == NULL)
29 return 0;
30
31 dso = map->dso;
32 if (dso == NULL)
33 return 0;
34
35 if (dso->kernel != DSO_TYPE_USER)
36 return 0;
37
38 node = dso__parse_addr_inlines(dso,
39 map__rip_2objdump(map, ip));
40 if (node == NULL)
41 return 0;
42
43 list_for_each_entry(ilist, &node->val, list) {
44 if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
45 ret += callchain__fprintf_left_margin(fp, left_margin);
46
47 for (i = 0; i < depth; i++) {
48 if (depth_mask & (1 << i))
49 ret += fprintf(fp, "|");
50 else
51 ret += fprintf(fp, " ");
52 ret += fprintf(fp, " ");
53 }
54
55 if (callchain_param.key == CCKEY_ADDRESS ||
56 callchain_param.key == CCKEY_SRCLINE) {
57 if (ilist->filename != NULL)
58 ret += fprintf(fp, "%s:%d (inline)",
59 ilist->filename,
60 ilist->line_nr);
61 else
62 ret += fprintf(fp, "??");
63 } else if (ilist->funcname != NULL)
64 ret += fprintf(fp, "%s (inline)",
65 ilist->funcname);
66 else if (ilist->filename != NULL)
67 ret += fprintf(fp, "%s:%d (inline)",
68 ilist->filename,
69 ilist->line_nr);
70 else
71 ret += fprintf(fp, "??");
72
73 ret += fprintf(fp, "\n");
74 }
75 }
76
77 inline_node__delete(node);
78 return ret;
79}
80
20static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, 81static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
21 int left_margin) 82 int left_margin)
22{ 83{
@@ -78,6 +139,10 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
78 fputs(str, fp); 139 fputs(str, fp);
79 fputc('\n', fp); 140 fputc('\n', fp);
80 free(alloc_str); 141 free(alloc_str);
142
143 if (symbol_conf.inline_name)
144 ret += inline__fprintf(chain->ms.map, chain->ip,
145 left_margin, depth, depth_mask, fp);
81 return ret; 146 return ret;
82} 147}
83 148
@@ -229,6 +294,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
229 if (!i++ && field_order == NULL && 294 if (!i++ && field_order == NULL &&
230 sort_order && !prefixcmp(sort_order, "sym")) 295 sort_order && !prefixcmp(sort_order, "sym"))
231 continue; 296 continue;
297
232 if (!printed) { 298 if (!printed) {
233 ret += callchain__fprintf_left_margin(fp, left_margin); 299 ret += callchain__fprintf_left_margin(fp, left_margin);
234 ret += fprintf(fp, "|\n"); 300 ret += fprintf(fp, "|\n");
@@ -251,6 +317,13 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
251 317
252 if (++entries_printed == callchain_param.print_limit) 318 if (++entries_printed == callchain_param.print_limit)
253 break; 319 break;
320
321 if (symbol_conf.inline_name)
322 ret += inline__fprintf(chain->ms.map,
323 chain->ip,
324 left_margin,
325 0, 0,
326 fp);
254 } 327 }
255 root = &cnode->rb_root; 328 root = &cnode->rb_root;
256 } 329 }
@@ -529,6 +602,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
529 bool use_callchain) 602 bool use_callchain)
530{ 603{
531 int ret; 604 int ret;
605 int callchain_ret = 0;
606 int inline_ret = 0;
532 struct perf_hpp hpp = { 607 struct perf_hpp hpp = {
533 .buf = bf, 608 .buf = bf,
534 .size = size, 609 .size = size,
@@ -547,7 +622,16 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
547 ret = fprintf(fp, "%s\n", bf); 622 ret = fprintf(fp, "%s\n", bf);
548 623
549 if (use_callchain) 624 if (use_callchain)
550 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); 625 callchain_ret = hist_entry_callchain__fprintf(he, total_period,
626 0, fp);
627
628 if (callchain_ret == 0 && symbol_conf.inline_name) {
629 inline_ret = inline__fprintf(he->ms.map, he->ip, 0, 0, 0, fp);
630 ret += inline_ret;
631 if (inline_ret > 0)
632 ret += fprintf(fp, "\n");
633 } else
634 ret += callchain_ret;
551 635
552 return ret; 636 return ret;
553} 637}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 22cd1dbe724b..11af5f0d56cc 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1307,6 +1307,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1307{ 1307{
1308 char linkname[PATH_MAX]; 1308 char linkname[PATH_MAX];
1309 char *build_id_filename; 1309 char *build_id_filename;
1310 char *build_id_path = NULL;
1310 1311
1311 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1312 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1312 !dso__is_kcore(dso)) 1313 !dso__is_kcore(dso))
@@ -1322,8 +1323,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1322 goto fallback; 1323 goto fallback;
1323 } 1324 }
1324 1325
1326 build_id_path = strdup(filename);
1327 if (!build_id_path)
1328 return -1;
1329
1330 dirname(build_id_path);
1331
1325 if (dso__is_kcore(dso) || 1332 if (dso__is_kcore(dso) ||
1326 readlink(filename, linkname, sizeof(linkname)) < 0 || 1333 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
1327 strstr(linkname, DSO__NAME_KALLSYMS) || 1334 strstr(linkname, DSO__NAME_KALLSYMS) ||
1328 access(filename, R_OK)) { 1335 access(filename, R_OK)) {
1329fallback: 1336fallback:
@@ -1335,6 +1342,7 @@ fallback:
1335 __symbol__join_symfs(filename, filename_size, dso->long_name); 1342 __symbol__join_symfs(filename, filename_size, dso->long_name);
1336 } 1343 }
1337 1344
1345 free(build_id_path);
1338 return 0; 1346 return 0;
1339} 1347}
1340 1348
@@ -1663,18 +1671,23 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1663 src_line->nr_pcnt = nr_pcnt; 1671 src_line->nr_pcnt = nr_pcnt;
1664 1672
1665 for (k = 0; k < nr_pcnt; k++) { 1673 for (k = 0; k < nr_pcnt; k++) {
1674 double percent = 0.0;
1675
1666 h = annotation__histogram(notes, evidx + k); 1676 h = annotation__histogram(notes, evidx + k);
1667 src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum; 1677 if (h->sum)
1678 percent = 100.0 * h->addr[i] / h->sum;
1668 1679
1669 if (src_line->samples[k].percent > percent_max) 1680 if (percent > percent_max)
1670 percent_max = src_line->samples[k].percent; 1681 percent_max = percent;
1682 src_line->samples[k].percent = percent;
1671 } 1683 }
1672 1684
1673 if (percent_max <= 0.5) 1685 if (percent_max <= 0.5)
1674 goto next; 1686 goto next;
1675 1687
1676 offset = start + i; 1688 offset = start + i;
1677 src_line->path = get_srcline(map->dso, offset, NULL, false); 1689 src_line->path = get_srcline(map->dso, offset, NULL,
1690 false, true);
1678 insert_source_line(&tmp_root, src_line); 1691 insert_source_line(&tmp_root, src_line);
1679 1692
1680 next: 1693 next:
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c5a6e0b12452..78bd632f144d 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -1826,7 +1826,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1826 filt->addr = start; 1826 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) { 1827 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size; 1828 filt->size = size;
1829 no_size = !!size; 1829 no_size = !size;
1830 } 1830 }
1831 } 1831 }
1832 1832
@@ -1840,7 +1840,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1840 if (err) 1840 if (err)
1841 return err; 1841 return err;
1842 filt->size = start + size - filt->addr; 1842 filt->size = start + size - filt->addr;
1843 no_size = !!size; 1843 no_size = !size;
1844 } 1844 }
1845 1845
1846 /* The very last symbol in kallsyms does not imply a particular size */ 1846 /* The very last symbol in kallsyms does not imply a particular size */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e528c40739cc..33af67530d30 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -182,13 +182,17 @@ char *build_id_cache__origname(const char *sbuild_id)
182 char buf[PATH_MAX]; 182 char buf[PATH_MAX];
183 char *ret = NULL, *p; 183 char *ret = NULL, *p;
184 size_t offs = 5; /* == strlen("../..") */ 184 size_t offs = 5; /* == strlen("../..") */
185 ssize_t len;
185 186
186 linkname = build_id_cache__linkname(sbuild_id, NULL, 0); 187 linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
187 if (!linkname) 188 if (!linkname)
188 return NULL; 189 return NULL;
189 190
190 if (readlink(linkname, buf, PATH_MAX) < 0) 191 len = readlink(linkname, buf, sizeof(buf) - 1);
192 if (len <= 0)
191 goto out; 193 goto out;
194 buf[len] = '\0';
195
192 /* The link should be "../..<origpath>/<sbuild_id>" */ 196 /* The link should be "../..<origpath>/<sbuild_id>" */
193 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */ 197 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */
194 if (p && (p > buf + offs)) { 198 if (p && (p > buf + offs)) {
@@ -690,7 +694,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
690 err = 0; 694 err = 0;
691 695
692 /* Update SDT cache : error is just warned */ 696 /* Update SDT cache : error is just warned */
693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 697 if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
694 pr_debug4("Failed to update/scan SDT cache for %s\n", realname); 698 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
695 699
696out_free: 700out_free:
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index aba953421a03..d78776a20e80 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -80,6 +80,10 @@ static int parse_callchain_sort_key(const char *value)
80 callchain_param.key = CCKEY_ADDRESS; 80 callchain_param.key = CCKEY_ADDRESS;
81 return 0; 81 return 0;
82 } 82 }
83 if (!strncmp(value, "srcline", strlen(value))) {
84 callchain_param.key = CCKEY_SRCLINE;
85 return 0;
86 }
83 if (!strncmp(value, "branch", strlen(value))) { 87 if (!strncmp(value, "branch", strlen(value))) {
84 callchain_param.branch_callstack = 1; 88 callchain_param.branch_callstack = 1;
85 return 0; 89 return 0;
@@ -510,14 +514,51 @@ enum match_result {
510 MATCH_GT, 514 MATCH_GT,
511}; 515};
512 516
517static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
518 struct callchain_list *cnode)
519{
520 char *left = get_srcline(cnode->ms.map->dso,
521 map__rip_2objdump(cnode->ms.map, cnode->ip),
522 cnode->ms.sym, true, false);
523 char *right = get_srcline(node->map->dso,
524 map__rip_2objdump(node->map, node->ip),
525 node->sym, true, false);
526 enum match_result ret = MATCH_EQ;
527 int cmp;
528
529 if (left && right)
530 cmp = strcmp(left, right);
531 else if (!left && right)
532 cmp = 1;
533 else if (left && !right)
534 cmp = -1;
535 else if (cnode->ip == node->ip)
536 cmp = 0;
537 else
538 cmp = (cnode->ip < node->ip) ? -1 : 1;
539
540 if (cmp != 0)
541 ret = cmp < 0 ? MATCH_LT : MATCH_GT;
542
543 free_srcline(left);
544 free_srcline(right);
545 return ret;
546}
547
513static enum match_result match_chain(struct callchain_cursor_node *node, 548static enum match_result match_chain(struct callchain_cursor_node *node,
514 struct callchain_list *cnode) 549 struct callchain_list *cnode)
515{ 550{
516 struct symbol *sym = node->sym; 551 struct symbol *sym = node->sym;
517 u64 left, right; 552 u64 left, right;
518 553
519 if (cnode->ms.sym && sym && 554 if (callchain_param.key == CCKEY_SRCLINE) {
520 callchain_param.key == CCKEY_FUNCTION) { 555 enum match_result match = match_chain_srcline(node, cnode);
556
557 if (match != MATCH_ERROR)
558 return match;
559 }
560
561 if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) {
521 left = cnode->ms.sym->start; 562 left = cnode->ms.sym->start;
522 right = sym->start; 563 right = sym->start;
523 } else { 564 } else {
@@ -911,15 +952,16 @@ out:
911char *callchain_list__sym_name(struct callchain_list *cl, 952char *callchain_list__sym_name(struct callchain_list *cl,
912 char *bf, size_t bfsize, bool show_dso) 953 char *bf, size_t bfsize, bool show_dso)
913{ 954{
955 bool show_addr = callchain_param.key == CCKEY_ADDRESS;
956 bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
914 int printed; 957 int printed;
915 958
916 if (cl->ms.sym) { 959 if (cl->ms.sym) {
917 if (callchain_param.key == CCKEY_ADDRESS && 960 if (show_srcline && cl->ms.map && !cl->srcline)
918 cl->ms.map && !cl->srcline)
919 cl->srcline = get_srcline(cl->ms.map->dso, 961 cl->srcline = get_srcline(cl->ms.map->dso,
920 map__rip_2objdump(cl->ms.map, 962 map__rip_2objdump(cl->ms.map,
921 cl->ip), 963 cl->ip),
922 cl->ms.sym, false); 964 cl->ms.sym, false, show_addr);
923 if (cl->srcline) 965 if (cl->srcline)
924 printed = scnprintf(bf, bfsize, "%s %s", 966 printed = scnprintf(bf, bfsize, "%s %s",
925 cl->ms.sym->name, cl->srcline); 967 cl->ms.sym->name, cl->srcline);
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 4f4b60f1558a..c56c23dbbf72 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -77,7 +77,8 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
77 77
78enum chain_key { 78enum chain_key {
79 CCKEY_FUNCTION, 79 CCKEY_FUNCTION,
80 CCKEY_ADDRESS 80 CCKEY_ADDRESS,
81 CCKEY_SRCLINE
81}; 82};
82 83
83enum chain_value { 84enum chain_value {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 05714d548584..ef09f26e67da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -370,15 +370,11 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
370 struct perf_evlist *evlist __maybe_unused) 370 struct perf_evlist *evlist __maybe_unused)
371{ 371{
372 char buf[MAXPATHLEN]; 372 char buf[MAXPATHLEN];
373 char proc[32];
374 u32 n; 373 u32 n;
375 int i, ret; 374 int i, ret;
376 375
377 /* 376 /* actual path to perf binary */
378 * actual atual path to perf binary 377 ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
379 */
380 sprintf(proc, "/proc/%d/exe", getpid());
381 ret = readlink(proc, buf, sizeof(buf));
382 if (ret <= 0) 378 if (ret <= 0)
383 return -1; 379 return -1;
384 380
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index e3b38f629504..3c4d4d00cb2c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1136,6 +1136,11 @@ void hist_entry__delete(struct hist_entry *he)
1136 zfree(&he->mem_info); 1136 zfree(&he->mem_info);
1137 } 1137 }
1138 1138
1139 if (he->inline_node) {
1140 inline_node__delete(he->inline_node);
1141 he->inline_node = NULL;
1142 }
1143
1139 zfree(&he->stat_acc); 1144 zfree(&he->stat_acc);
1140 free_srcline(he->srcline); 1145 free_srcline(he->srcline);
1141 if (he->srcfile && he->srcfile[0]) 1146 if (he->srcfile && he->srcfile[0])
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 1d9ebcf9e38e..c1870ac365a3 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -405,7 +405,8 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
405 405
406 if (map && map->dso) { 406 if (map && map->dso) {
407 srcline = get_srcline(map->dso, 407 srcline = get_srcline(map->dso,
408 map__rip_2objdump(map, addr), NULL, true); 408 map__rip_2objdump(map, addr), NULL,
409 true, true);
409 if (srcline != SRCLINE_UNKNOWN) 410 if (srcline != SRCLINE_UNKNOWN)
410 ret = fprintf(fp, "%s%s", prefix, srcline); 411 ret = fprintf(fp, "%s%s", prefix, srcline);
411 free_srcline(srcline); 412 free_srcline(srcline);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8b0d4e39f640..73f3ec1cf2a0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -323,7 +323,7 @@ char *hist_entry__get_srcline(struct hist_entry *he)
323 return SRCLINE_UNKNOWN; 323 return SRCLINE_UNKNOWN;
324 324
325 return get_srcline(map->dso, map__rip_2objdump(map, he->ip), 325 return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
326 he->ms.sym, true); 326 he->ms.sym, true, true);
327} 327}
328 328
329static int64_t 329static int64_t
@@ -366,7 +366,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
366 left->branch_info->srcline_from = get_srcline(map->dso, 366 left->branch_info->srcline_from = get_srcline(map->dso,
367 map__rip_2objdump(map, 367 map__rip_2objdump(map,
368 left->branch_info->from.al_addr), 368 left->branch_info->from.al_addr),
369 left->branch_info->from.sym, true); 369 left->branch_info->from.sym,
370 true, true);
370 } 371 }
371 if (!right->branch_info->srcline_from) { 372 if (!right->branch_info->srcline_from) {
372 struct map *map = right->branch_info->from.map; 373 struct map *map = right->branch_info->from.map;
@@ -376,7 +377,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
376 right->branch_info->srcline_from = get_srcline(map->dso, 377 right->branch_info->srcline_from = get_srcline(map->dso,
377 map__rip_2objdump(map, 378 map__rip_2objdump(map,
378 right->branch_info->from.al_addr), 379 right->branch_info->from.al_addr),
379 right->branch_info->from.sym, true); 380 right->branch_info->from.sym,
381 true, true);
380 } 382 }
381 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); 383 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
382} 384}
@@ -407,7 +409,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
407 left->branch_info->srcline_to = get_srcline(map->dso, 409 left->branch_info->srcline_to = get_srcline(map->dso,
408 map__rip_2objdump(map, 410 map__rip_2objdump(map,
409 left->branch_info->to.al_addr), 411 left->branch_info->to.al_addr),
410 left->branch_info->from.sym, true); 412 left->branch_info->from.sym,
413 true, true);
411 } 414 }
412 if (!right->branch_info->srcline_to) { 415 if (!right->branch_info->srcline_to) {
413 struct map *map = right->branch_info->to.map; 416 struct map *map = right->branch_info->to.map;
@@ -417,7 +420,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
417 right->branch_info->srcline_to = get_srcline(map->dso, 420 right->branch_info->srcline_to = get_srcline(map->dso,
418 map__rip_2objdump(map, 421 map__rip_2objdump(map,
419 right->branch_info->to.al_addr), 422 right->branch_info->to.al_addr),
420 right->branch_info->to.sym, true); 423 right->branch_info->to.sym,
424 true, true);
421 } 425 }
422 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); 426 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
423} 427}
@@ -448,7 +452,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e)
448 return no_srcfile; 452 return no_srcfile;
449 453
450 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), 454 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
451 e->ms.sym, false, true); 455 e->ms.sym, false, true, true);
452 if (!strcmp(sf, SRCLINE_UNKNOWN)) 456 if (!strcmp(sf, SRCLINE_UNKNOWN))
453 return no_srcfile; 457 return no_srcfile;
454 p = strchr(sf, ':'); 458 p = strchr(sf, ':');
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index baf20a399f34..e35fb186d048 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -128,6 +128,7 @@ struct hist_entry {
128 }; 128 };
129 char *srcline; 129 char *srcline;
130 char *srcfile; 130 char *srcfile;
131 struct inline_node *inline_node;
131 struct symbol *parent; 132 struct symbol *parent;
132 struct branch_info *branch_info; 133 struct branch_info *branch_info;
133 struct hists *hists; 134 struct hists *hists;
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index b4db3f48e3b0..778ccb5d99d1 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -7,11 +7,58 @@
7#include "util/dso.h" 7#include "util/dso.h"
8#include "util/util.h" 8#include "util/util.h"
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/callchain.h"
10 11
11#include "symbol.h" 12#include "symbol.h"
12 13
13bool srcline_full_filename; 14bool srcline_full_filename;
14 15
16static const char *dso__name(struct dso *dso)
17{
18 const char *dso_name;
19
20 if (dso->symsrc_filename)
21 dso_name = dso->symsrc_filename;
22 else
23 dso_name = dso->long_name;
24
25 if (dso_name[0] == '[')
26 return NULL;
27
28 if (!strncmp(dso_name, "/tmp/perf-", 10))
29 return NULL;
30
31 return dso_name;
32}
33
34static int inline_list__append(char *filename, char *funcname, int line_nr,
35 struct inline_node *node, struct dso *dso)
36{
37 struct inline_list *ilist;
38 char *demangled;
39
40 ilist = zalloc(sizeof(*ilist));
41 if (ilist == NULL)
42 return -1;
43
44 ilist->filename = filename;
45 ilist->line_nr = line_nr;
46
47 if (dso != NULL) {
48 demangled = dso__demangle_sym(dso, 0, funcname);
49 if (demangled == NULL) {
50 ilist->funcname = funcname;
51 } else {
52 ilist->funcname = demangled;
53 free(funcname);
54 }
55 }
56
57 list_add_tail(&ilist->list, &node->val);
58
59 return 0;
60}
61
15#ifdef HAVE_LIBBFD_SUPPORT 62#ifdef HAVE_LIBBFD_SUPPORT
16 63
17/* 64/*
@@ -151,9 +198,17 @@ static void addr2line_cleanup(struct a2l_data *a2l)
151 198
152#define MAX_INLINE_NEST 1024 199#define MAX_INLINE_NEST 1024
153 200
201static void inline_list__reverse(struct inline_node *node)
202{
203 struct inline_list *ilist, *n;
204
205 list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
206 list_move_tail(&ilist->list, &node->val);
207}
208
154static int addr2line(const char *dso_name, u64 addr, 209static int addr2line(const char *dso_name, u64 addr,
155 char **file, unsigned int *line, struct dso *dso, 210 char **file, unsigned int *line, struct dso *dso,
156 bool unwind_inlines) 211 bool unwind_inlines, struct inline_node *node)
157{ 212{
158 int ret = 0; 213 int ret = 0;
159 struct a2l_data *a2l = dso->a2l; 214 struct a2l_data *a2l = dso->a2l;
@@ -178,8 +233,21 @@ static int addr2line(const char *dso_name, u64 addr,
178 233
179 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 234 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
180 &a2l->funcname, &a2l->line) && 235 &a2l->funcname, &a2l->line) &&
181 cnt++ < MAX_INLINE_NEST) 236 cnt++ < MAX_INLINE_NEST) {
182 ; 237
238 if (node != NULL) {
239 if (inline_list__append(strdup(a2l->filename),
240 strdup(a2l->funcname),
241 a2l->line, node,
242 dso) != 0)
243 return 0;
244 }
245 }
246
247 if ((node != NULL) &&
248 (callchain_param.order != ORDER_CALLEE)) {
249 inline_list__reverse(node);
250 }
183 } 251 }
184 252
185 if (a2l->found && a2l->filename) { 253 if (a2l->found && a2l->filename) {
@@ -205,18 +273,68 @@ void dso__free_a2l(struct dso *dso)
205 dso->a2l = NULL; 273 dso->a2l = NULL;
206} 274}
207 275
276static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
277 struct dso *dso)
278{
279 char *file = NULL;
280 unsigned int line = 0;
281 struct inline_node *node;
282
283 node = zalloc(sizeof(*node));
284 if (node == NULL) {
285 perror("not enough memory for the inline node");
286 return NULL;
287 }
288
289 INIT_LIST_HEAD(&node->val);
290 node->addr = addr;
291
292 if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
293 goto out_free_inline_node;
294
295 if (list_empty(&node->val))
296 goto out_free_inline_node;
297
298 return node;
299
300out_free_inline_node:
301 inline_node__delete(node);
302 return NULL;
303}
304
208#else /* HAVE_LIBBFD_SUPPORT */ 305#else /* HAVE_LIBBFD_SUPPORT */
209 306
307static int filename_split(char *filename, unsigned int *line_nr)
308{
309 char *sep;
310
311 sep = strchr(filename, '\n');
312 if (sep)
313 *sep = '\0';
314
315 if (!strcmp(filename, "??:0"))
316 return 0;
317
318 sep = strchr(filename, ':');
319 if (sep) {
320 *sep++ = '\0';
321 *line_nr = strtoul(sep, NULL, 0);
322 return 1;
323 }
324
325 return 0;
326}
327
210static int addr2line(const char *dso_name, u64 addr, 328static int addr2line(const char *dso_name, u64 addr,
211 char **file, unsigned int *line_nr, 329 char **file, unsigned int *line_nr,
212 struct dso *dso __maybe_unused, 330 struct dso *dso __maybe_unused,
213 bool unwind_inlines __maybe_unused) 331 bool unwind_inlines __maybe_unused,
332 struct inline_node *node __maybe_unused)
214{ 333{
215 FILE *fp; 334 FILE *fp;
216 char cmd[PATH_MAX]; 335 char cmd[PATH_MAX];
217 char *filename = NULL; 336 char *filename = NULL;
218 size_t len; 337 size_t len;
219 char *sep;
220 int ret = 0; 338 int ret = 0;
221 339
222 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, 340 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
@@ -233,23 +351,14 @@ static int addr2line(const char *dso_name, u64 addr,
233 goto out; 351 goto out;
234 } 352 }
235 353
236 sep = strchr(filename, '\n'); 354 ret = filename_split(filename, line_nr);
237 if (sep) 355 if (ret != 1) {
238 *sep = '\0';
239
240 if (!strcmp(filename, "??:0")) {
241 pr_debug("no debugging info in %s\n", dso_name);
242 free(filename); 356 free(filename);
243 goto out; 357 goto out;
244 } 358 }
245 359
246 sep = strchr(filename, ':'); 360 *file = filename;
247 if (sep) { 361
248 *sep++ = '\0';
249 *file = filename;
250 *line_nr = strtoul(sep, NULL, 0);
251 ret = 1;
252 }
253out: 362out:
254 pclose(fp); 363 pclose(fp);
255 return ret; 364 return ret;
@@ -259,6 +368,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
259{ 368{
260} 369}
261 370
371static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
372 struct dso *dso __maybe_unused)
373{
374 FILE *fp;
375 char cmd[PATH_MAX];
376 struct inline_node *node;
377 char *filename = NULL;
378 size_t len;
379 unsigned int line_nr = 0;
380
381 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
382 dso_name, addr);
383
384 fp = popen(cmd, "r");
385 if (fp == NULL) {
386 pr_err("popen failed for %s\n", dso_name);
387 return NULL;
388 }
389
390 node = zalloc(sizeof(*node));
391 if (node == NULL) {
392 perror("not enough memory for the inline node");
393 goto out;
394 }
395
396 INIT_LIST_HEAD(&node->val);
397 node->addr = addr;
398
399 while (getline(&filename, &len, fp) != -1) {
400 if (filename_split(filename, &line_nr) != 1) {
401 free(filename);
402 goto out;
403 }
404
405 if (inline_list__append(filename, NULL, line_nr, node,
406 NULL) != 0)
407 goto out;
408
409 filename = NULL;
410 }
411
412out:
413 pclose(fp);
414
415 if (list_empty(&node->val)) {
416 inline_node__delete(node);
417 return NULL;
418 }
419
420 return node;
421}
422
262#endif /* HAVE_LIBBFD_SUPPORT */ 423#endif /* HAVE_LIBBFD_SUPPORT */
263 424
264/* 425/*
@@ -268,7 +429,7 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
268#define A2L_FAIL_LIMIT 123 429#define A2L_FAIL_LIMIT 123
269 430
270char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 431char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
271 bool show_sym, bool unwind_inlines) 432 bool show_sym, bool show_addr, bool unwind_inlines)
272{ 433{
273 char *file = NULL; 434 char *file = NULL;
274 unsigned line = 0; 435 unsigned line = 0;
@@ -278,18 +439,11 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
278 if (!dso->has_srcline) 439 if (!dso->has_srcline)
279 goto out; 440 goto out;
280 441
281 if (dso->symsrc_filename) 442 dso_name = dso__name(dso);
282 dso_name = dso->symsrc_filename; 443 if (dso_name == NULL)
283 else
284 dso_name = dso->long_name;
285
286 if (dso_name[0] == '[')
287 goto out;
288
289 if (!strncmp(dso_name, "/tmp/perf-", 10))
290 goto out; 444 goto out;
291 445
292 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines)) 446 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
293 goto out; 447 goto out;
294 448
295 if (asprintf(&srcline, "%s:%u", 449 if (asprintf(&srcline, "%s:%u",
@@ -309,6 +463,11 @@ out:
309 dso->has_srcline = 0; 463 dso->has_srcline = 0;
310 dso__free_a2l(dso); 464 dso__free_a2l(dso);
311 } 465 }
466
467 if (!show_addr)
468 return (show_sym && sym) ?
469 strndup(sym->name, sym->namelen) : NULL;
470
312 if (sym) { 471 if (sym) {
313 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", 472 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
314 addr - sym->start) < 0) 473 addr - sym->start) < 0)
@@ -325,7 +484,32 @@ void free_srcline(char *srcline)
325} 484}
326 485
327char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 486char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
328 bool show_sym) 487 bool show_sym, bool show_addr)
488{
489 return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
490}
491
492struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
329{ 493{
330 return __get_srcline(dso, addr, sym, show_sym, false); 494 const char *dso_name;
495
496 dso_name = dso__name(dso);
497 if (dso_name == NULL)
498 return NULL;
499
500 return addr2inlines(dso_name, addr, dso);
501}
502
503void inline_node__delete(struct inline_node *node)
504{
505 struct inline_list *ilist, *tmp;
506
507 list_for_each_entry_safe(ilist, tmp, &node->val, list) {
508 list_del_init(&ilist->list);
509 zfree(&ilist->filename);
510 zfree(&ilist->funcname);
511 free(ilist);
512 }
513
514 free(node);
331} 515}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 0e660dba58ad..d1a40bb642ff 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -390,6 +390,11 @@ out_elf_end:
390 return 0; 390 return 0;
391} 391}
392 392
393char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name)
394{
395 return demangle_sym(dso, kmodule, elf_name);
396}
397
393/* 398/*
394 * Align offset to 4 bytes as needed for note name and descriptor data. 399 * Align offset to 4 bytes as needed for note name and descriptor data.
395 */ 400 */
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 11cdde980545..870ef0f0659c 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -373,3 +373,10 @@ int kcore_copy(const char *from_dir __maybe_unused,
373void symbol__elf_init(void) 373void symbol__elf_init(void)
374{ 374{
375} 375}
376
377char *dso__demangle_sym(struct dso *dso __maybe_unused,
378 int kmodule __maybe_unused,
379 char *elf_name __maybe_unused)
380{
381 return NULL;
382}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9222c7e702f3..5245d2fb1a0a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -118,7 +118,8 @@ struct symbol_conf {
118 show_ref_callgraph, 118 show_ref_callgraph,
119 hide_unresolved, 119 hide_unresolved,
120 raw_trace, 120 raw_trace,
121 report_hierarchy; 121 report_hierarchy,
122 inline_name;
122 const char *vmlinux_name, 123 const char *vmlinux_name,
123 *kallsyms_name, 124 *kallsyms_name,
124 *source_prefix, 125 *source_prefix,
@@ -305,6 +306,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
305int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 306int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
306 struct map *map); 307 struct map *map);
307 308
309char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name);
310
308void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel); 311void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
309void symbols__insert(struct rb_root *symbols, struct symbol *sym); 312void symbols__insert(struct rb_root *symbols, struct symbol *sym);
310void symbols__fixup_duplicate(struct rb_root *symbols); 313void symbols__fixup_duplicate(struct rb_root *symbols);
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 27420159bf69..8a9a677f7576 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -192,7 +192,7 @@ static int read_ftrace_printk(struct pevent *pevent)
192 if (!size) 192 if (!size)
193 return 0; 193 return 0;
194 194
195 buf = malloc(size); 195 buf = malloc(size + 1);
196 if (buf == NULL) 196 if (buf == NULL)
197 return -1; 197 return -1;
198 198
@@ -201,6 +201,8 @@ static int read_ftrace_printk(struct pevent *pevent)
201 return -1; 201 return -1;
202 } 202 }
203 203
204 buf[size] = '\0';
205
204 parse_ftrace_printk(pevent, buf, size); 206 parse_ftrace_printk(pevent, buf, size);
205 207
206 free(buf); 208 free(buf);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b2cfa47990dc..7cf5752b38fd 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -287,9 +287,9 @@ struct symbol;
287 287
288extern bool srcline_full_filename; 288extern bool srcline_full_filename;
289char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 289char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
290 bool show_sym); 290 bool show_sym, bool show_addr);
291char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 291char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
292 bool show_sym, bool unwind_inlines); 292 bool show_sym, bool show_addr, bool unwind_inlines);
293void free_srcline(char *srcline); 293void free_srcline(char *srcline);
294 294
295int perf_event_paranoid(void); 295int perf_event_paranoid(void);
@@ -364,4 +364,20 @@ int is_printable_array(char *p, unsigned int len);
364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 364int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
365 365
366int unit_number__scnprintf(char *buf, size_t size, u64 n); 366int unit_number__scnprintf(char *buf, size_t size, u64 n);
367
368struct inline_list {
369 char *filename;
370 char *funcname;
371 unsigned int line_nr;
372 struct list_head list;
373};
374
375struct inline_node {
376 u64 addr;
377 struct list_head val;
378};
379
380struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr);
381void inline_node__delete(struct inline_node *node);
382
367#endif /* GIT_COMPAT_UTIL_H */ 383#endif /* GIT_COMPAT_UTIL_H */