aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-05-20 13:37:43 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-20 13:37:43 -0400
commit408cf677073a5d1a7343bc6430a7297ba7b280d4 (patch)
treec6313e48e965a21ddc7d47052f3b3744c94fae63
parent1ab94188e4923629f296eb065ebf56d64ef3324a (diff)
parenta706670900073d236938d539d1109338d64b47bb (diff)
Merge tag 'perf-core-for-mingo-20160520' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - We should not use the current value of the kernel.perf_event_max_stack as the default value for --max-stack in tools that can process perf.data files, they will only match if that sysctl wasn't changed from its default value at the time the perf.data file was recorded, fix it. This fixes a bug where a 'perf record -a --call-graph dwarf ; perf report' produces a glibc invalid free backtrace (Arnaldo Carvalho de Melo) - Provide a better warning when running 'perf trace' on a system where the kernel.kptr_restrict is set to 1, similar to the one produced by 'perf record', noticed on ubuntu 16.04 where this is the default kptr_restrict setting. (Arnaldo Carvalho de Melo) - Fix ordering of instructions in the annotation code, noticed when annotating ARM binaries, now that table is auto-ordered at first use, to avoid more such problems (Chris Ryder) - Set buildid dir under symfs when --symfs is provided (He Kuang) - Fix the 'exit_group()' syscall output in 'perf trace' (Arnaldo Carvalho de Melo) - Only auto set call-graph to "dwarf" in 'perf trace' when syscalls are being traced (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt3
-rw-r--r--tools/perf/builtin-annotate.c5
-rw-r--r--tools/perf/builtin-diff.c5
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/builtin-script.c7
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/builtin-trace.c26
-rw-r--r--tools/perf/util/annotate.c30
-rw-r--r--tools/perf/util/db-export.c3
-rw-r--r--tools/perf/util/dso.c4
-rw-r--r--tools/perf/util/machine.c35
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c3
-rw-r--r--tools/perf/util/symbol.c23
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/top.h1
19 files changed, 109 insertions, 61 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ebaf849e30ef..496d42cdf02b 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -248,7 +248,7 @@ OPTIONS
248 Note that when using the --itrace option the synthesized callchain size 248 Note that when using the --itrace option the synthesized callchain size
249 will override this value if the synthesized callchain size is bigger. 249 will override this value if the synthesized callchain size is bigger.
250 250
251 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. 251 Default: 127
252 252
253-G:: 253-G::
254--inverted:: 254--inverted::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index a856a1095893..4fc44c75263f 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -267,7 +267,7 @@ include::itrace.txt[]
267 Note that when using the --itrace option the synthesized callchain size 267 Note that when using the --itrace option the synthesized callchain size
268 will override this value if the synthesized callchain size is bigger. 268 will override this value if the synthesized callchain size is bigger.
269 269
270 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. 270 Default: 127
271 271
272--ns:: 272--ns::
273 Use 9 decimal places when displaying time (i.e. show the nanoseconds) 273 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 6afe20121bc0..1ab0782369b1 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -143,7 +143,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
143 Implies '--call-graph dwarf' when --call-graph not present on the 143 Implies '--call-graph dwarf' when --call-graph not present on the
144 command line, on systems where DWARF unwinding was built in. 144 command line, on systems where DWARF unwinding was built in.
145 145
146 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. 146 Default: /proc/sys/kernel/perf_event_max_stack when present for
147 live sessions (without --input/-i), 127 otherwise.
147 148
148--min-stack:: 149--min-stack::
149 Set the stack depth limit when parsing the callchain, anything 150 Set the stack depth limit when parsing the callchain, anything
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 814158393656..25c81734a950 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
325 "Skip symbols that cannot be annotated"), 325 "Skip symbols that cannot be annotated"),
326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), 326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
327 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 327 OPT_CALLBACK(0, "symfs", NULL, "directory",
328 "Look for files with symbols relative to this directory"), 328 "Look for files with symbols relative to this directory",
329 symbol__config_symfs),
329 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 330 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
330 "Interleave source code with assembly code (default)"), 331 "Interleave source code with assembly code (default)"),
331 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 332 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9ce354f469dc..f7645a42708e 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -812,8 +812,9 @@ static const struct option options[] = {
812 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", 812 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
813 "separator for columns, no spaces will be added between " 813 "separator for columns, no spaces will be added between "
814 "columns '.' is reserved."), 814 "columns '.' is reserved."),
815 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 815 OPT_CALLBACK(0, "symfs", NULL, "directory",
816 "Look for files with symbols relative to this directory"), 816 "Look for files with symbols relative to this directory",
817 symbol__config_symfs),
817 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 818 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
818 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 819 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
819 "How to display percentage of filtered entries", parse_filter_percentage), 820 "How to display percentage of filtered entries", parse_filter_percentage),
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 87d40e3c4078..a87cb338bdf1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
691 .ordered_events = true, 691 .ordered_events = true,
692 .ordering_requires_timestamps = true, 692 .ordering_requires_timestamps = true,
693 }, 693 },
694 .max_stack = sysctl_perf_event_max_stack, 694 .max_stack = PERF_MAX_STACK_DEPTH,
695 .pretty_printing_style = "normal", 695 .pretty_printing_style = "normal",
696 .socket_filter = -1, 696 .socket_filter = -1,
697 }; 697 };
@@ -770,8 +770,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
770 "columns '.' is reserved."), 770 "columns '.' is reserved."),
771 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved, 771 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
772 "Only display entries resolved to a symbol"), 772 "Only display entries resolved to a symbol"),
773 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 773 OPT_CALLBACK(0, "symfs", NULL, "directory",
774 "Look for files with symbols relative to this directory"), 774 "Look for files with symbols relative to this directory",
775 symbol__config_symfs),
775 OPT_STRING('C', "cpu", &report.cpu_list, "cpu", 776 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
776 "list of cpus to profile"), 777 "list of cpus to profile"),
777 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 778 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index efca81679bb3..e3ce2f34d3ad 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2010,8 +2010,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2010 "file", "kallsyms pathname"), 2010 "file", "kallsyms pathname"),
2011 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, 2011 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
2012 "When printing symbols do not display call chain"), 2012 "When printing symbols do not display call chain"),
2013 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 2013 OPT_CALLBACK(0, "symfs", NULL, "directory",
2014 "Look for files with symbols relative to this directory"), 2014 "Look for files with symbols relative to this directory",
2015 symbol__config_symfs),
2015 OPT_CALLBACK('F', "fields", NULL, "str", 2016 OPT_CALLBACK('F', "fields", NULL, "str",
2016 "comma separated output fields prepend with 'type:'. " 2017 "comma separated output fields prepend with 'type:'. "
2017 "Valid types: hw,sw,trace,raw. " 2018 "Valid types: hw,sw,trace,raw. "
@@ -2067,8 +2068,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2067 NULL 2068 NULL
2068 }; 2069 };
2069 2070
2070 scripting_max_stack = sysctl_perf_event_max_stack;
2071
2072 setup_scripting(); 2071 setup_scripting();
2073 2072
2074 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 2073 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 40cc9bb3506c..733a55422d03 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv,
1945 OPT_CALLBACK('p', "process", NULL, "process", 1945 OPT_CALLBACK('p', "process", NULL, "process",
1946 "process selector. Pass a pid or process name.", 1946 "process selector. Pass a pid or process name.",
1947 parse_process), 1947 parse_process),
1948 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1948 OPT_CALLBACK(0, "symfs", NULL, "directory",
1949 "Look for files with symbols relative to this directory"), 1949 "Look for files with symbols relative to this directory",
1950 symbol__config_symfs),
1950 OPT_INTEGER('n', "proc-num", &tchart.proc_num, 1951 OPT_INTEGER('n', "proc-num", &tchart.proc_num,
1951 "min. number of tasks to print"), 1952 "min. number of tasks to print"),
1952 OPT_BOOLEAN('t', "topology", &tchart.topology, 1953 OPT_BOOLEAN('t', "topology", &tchart.topology,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 1793da585676..2a6cc254ad0c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -732,7 +732,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
732 if (machine__resolve(machine, &al, sample) < 0) 732 if (machine__resolve(machine, &al, sample) < 0)
733 return; 733 return;
734 734
735 if (!top->kptr_restrict_warned && 735 if (!machine->kptr_restrict_warned &&
736 symbol_conf.kptr_restrict && 736 symbol_conf.kptr_restrict &&
737 al.cpumode == PERF_RECORD_MISC_KERNEL) { 737 al.cpumode == PERF_RECORD_MISC_KERNEL) {
738 ui__warning( 738 ui__warning(
@@ -743,7 +743,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
743 " modules" : ""); 743 " modules" : "");
744 if (use_browser <= 0) 744 if (use_browser <= 0)
745 sleep(5); 745 sleep(5);
746 top->kptr_restrict_warned = true; 746 machine->kptr_restrict_warned = true;
747 } 747 }
748 748
749 if (al.sym == NULL) { 749 if (al.sym == NULL) {
@@ -759,7 +759,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
759 * --hide-kernel-symbols, even if the user specifies an 759 * --hide-kernel-symbols, even if the user specifies an
760 * invalid --vmlinux ;-) 760 * invalid --vmlinux ;-)
761 */ 761 */
762 if (!top->kptr_restrict_warned && !top->vmlinux_warned && 762 if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
763 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 763 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
764 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 764 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
765 if (symbol_conf.vmlinux_name) { 765 if (symbol_conf.vmlinux_name) {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 6e5c325148e4..487c10401d46 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1160,6 +1160,24 @@ static int trace__tool_process(struct perf_tool *tool,
1160 return trace__process_event(trace, machine, event, sample); 1160 return trace__process_event(trace, machine, event, sample);
1161} 1161}
1162 1162
1163static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
1164{
1165 struct machine *machine = vmachine;
1166
1167 if (machine->kptr_restrict_warned)
1168 return NULL;
1169
1170 if (symbol_conf.kptr_restrict) {
1171 pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
1172 "Check /proc/sys/kernel/kptr_restrict.\n\n"
1173 "Kernel samples will not be resolved.\n");
1174 machine->kptr_restrict_warned = true;
1175 return NULL;
1176 }
1177
1178 return machine__resolve_kernel_addr(vmachine, addrp, modp);
1179}
1180
1163static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1181static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1164{ 1182{
1165 int err = symbol__init(NULL); 1183 int err = symbol__init(NULL);
@@ -1171,7 +1189,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1171 if (trace->host == NULL) 1189 if (trace->host == NULL)
1172 return -ENOMEM; 1190 return -ENOMEM;
1173 1191
1174 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0) 1192 if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
1175 return -errno; 1193 return -errno;
1176 1194
1177 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, 1195 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
@@ -1534,7 +1552,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1534 if (sc->is_exit) { 1552 if (sc->is_exit) {
1535 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1553 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
1536 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 1554 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
1537 fprintf(trace->output, "%-70s\n", ttrace->entry_str); 1555 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
1538 } 1556 }
1539 } else { 1557 } else {
1540 ttrace->entry_pending = true; 1558 ttrace->entry_pending = true;
@@ -2887,12 +2905,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2887 mmap_pages_user_set = false; 2905 mmap_pages_user_set = false;
2888 2906
2889 if (trace.max_stack == UINT_MAX) { 2907 if (trace.max_stack == UINT_MAX) {
2890 trace.max_stack = sysctl_perf_event_max_stack; 2908 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
2891 max_stack_user_set = false; 2909 max_stack_user_set = false;
2892 } 2910 }
2893 2911
2894#ifdef HAVE_DWARF_UNWIND_SUPPORT 2912#ifdef HAVE_DWARF_UNWIND_SUPPORT
2895 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled) 2913 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
2896 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); 2914 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2897#endif 2915#endif
2898 2916
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b811924e5e1b..7e5a1e8874ce 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -354,9 +354,6 @@ static struct ins_ops nop_ops = {
354 .scnprintf = nop__scnprintf, 354 .scnprintf = nop__scnprintf,
355}; 355};
356 356
357/*
358 * Must be sorted by name!
359 */
360static struct ins instructions[] = { 357static struct ins instructions[] = {
361 { .name = "add", .ops = &mov_ops, }, 358 { .name = "add", .ops = &mov_ops, },
362 { .name = "addl", .ops = &mov_ops, }, 359 { .name = "addl", .ops = &mov_ops, },
@@ -372,8 +369,8 @@ static struct ins instructions[] = {
372 { .name = "bgt", .ops = &jump_ops, }, 369 { .name = "bgt", .ops = &jump_ops, },
373 { .name = "bhi", .ops = &jump_ops, }, 370 { .name = "bhi", .ops = &jump_ops, },
374 { .name = "bl", .ops = &call_ops, }, 371 { .name = "bl", .ops = &call_ops, },
375 { .name = "blt", .ops = &jump_ops, },
376 { .name = "bls", .ops = &jump_ops, }, 372 { .name = "bls", .ops = &jump_ops, },
373 { .name = "blt", .ops = &jump_ops, },
377 { .name = "blx", .ops = &call_ops, }, 374 { .name = "blx", .ops = &call_ops, },
378 { .name = "bne", .ops = &jump_ops, }, 375 { .name = "bne", .ops = &jump_ops, },
379#endif 376#endif
@@ -449,18 +446,39 @@ static struct ins instructions[] = {
449 { .name = "xbeginq", .ops = &jump_ops, }, 446 { .name = "xbeginq", .ops = &jump_ops, },
450}; 447};
451 448
452static int ins__cmp(const void *name, const void *insp) 449static int ins__key_cmp(const void *name, const void *insp)
453{ 450{
454 const struct ins *ins = insp; 451 const struct ins *ins = insp;
455 452
456 return strcmp(name, ins->name); 453 return strcmp(name, ins->name);
457} 454}
458 455
456static int ins__cmp(const void *a, const void *b)
457{
458 const struct ins *ia = a;
459 const struct ins *ib = b;
460
461 return strcmp(ia->name, ib->name);
462}
463
464static void ins__sort(void)
465{
466 const int nmemb = ARRAY_SIZE(instructions);
467
468 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
469}
470
459static struct ins *ins__find(const char *name) 471static struct ins *ins__find(const char *name)
460{ 472{
461 const int nmemb = ARRAY_SIZE(instructions); 473 const int nmemb = ARRAY_SIZE(instructions);
474 static bool sorted;
475
476 if (!sorted) {
477 ins__sort();
478 sorted = true;
479 }
462 480
463 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); 481 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
464} 482}
465 483
466int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) 484int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 8d96c80cc67e..c9a6dc173e74 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -298,8 +298,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
298 */ 298 */
299 callchain_param.order = ORDER_CALLER; 299 callchain_param.order = ORDER_CALLER;
300 err = thread__resolve_callchain(thread, &callchain_cursor, evsel, 300 err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
301 sample, NULL, NULL, 301 sample, NULL, NULL, PERF_MAX_STACK_DEPTH);
302 sysctl_perf_event_max_stack);
303 if (err) { 302 if (err) {
304 callchain_param.order = saved_order; 303 callchain_param.order = saved_order;
305 return NULL; 304 return NULL;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 75b75615e2f8..5d286f5d7906 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -63,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
63 } 63 }
64 break; 64 break;
65 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 65 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
66 /* skip the locally configured cache if a symfs is given */ 66 if (dso__build_id_filename(dso, filename, size) == NULL)
67 if (symbol_conf.symfs[0] ||
68 (dso__build_id_filename(dso, filename, size) == NULL))
69 ret = -1; 67 ret = -1;
70 break; 68 break;
71 69
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 7ba9fadb68af..205d27017361 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -43,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
43 43
44 machine->symbol_filter = NULL; 44 machine->symbol_filter = NULL;
45 machine->id_hdr_size = 0; 45 machine->id_hdr_size = 0;
46 machine->kptr_restrict_warned = false;
46 machine->comm_exec = false; 47 machine->comm_exec = false;
47 machine->kernel_start = 0; 48 machine->kernel_start = 0;
48 49
@@ -1135,10 +1136,10 @@ int machine__create_kernel_maps(struct machine *machine)
1135{ 1136{
1136 struct dso *kernel = machine__get_kernel(machine); 1137 struct dso *kernel = machine__get_kernel(machine);
1137 const char *name; 1138 const char *name;
1138 u64 addr = machine__get_running_kernel_start(machine, &name); 1139 u64 addr;
1139 int ret; 1140 int ret;
1140 1141
1141 if (!addr || kernel == NULL) 1142 if (kernel == NULL)
1142 return -1; 1143 return -1;
1143 1144
1144 ret = __machine__create_kernel_maps(machine, kernel); 1145 ret = __machine__create_kernel_maps(machine, kernel);
@@ -1160,8 +1161,9 @@ int machine__create_kernel_maps(struct machine *machine)
1160 */ 1161 */
1161 map_groups__fixup_end(&machine->kmaps); 1162 map_groups__fixup_end(&machine->kmaps);
1162 1163
1163 if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, 1164 addr = machine__get_running_kernel_start(machine, &name);
1164 addr)) { 1165 if (!addr) {
1166 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1165 machine__destroy_kernel_maps(machine); 1167 machine__destroy_kernel_maps(machine);
1166 return -1; 1168 return -1;
1167 } 1169 }
@@ -1769,11 +1771,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1769 */ 1771 */
1770 int mix_chain_nr = i + 1 + lbr_nr + 1; 1772 int mix_chain_nr = i + 1 + lbr_nr + 1;
1771 1773
1772 if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) {
1773 pr_warning("corrupted callchain. skipping...\n");
1774 return 0;
1775 }
1776
1777 for (j = 0; j < mix_chain_nr; j++) { 1774 for (j = 0; j < mix_chain_nr; j++) {
1778 if (callchain_param.order == ORDER_CALLEE) { 1775 if (callchain_param.order == ORDER_CALLEE) {
1779 if (j < i + 1) 1776 if (j < i + 1)
@@ -1813,7 +1810,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1813 struct ip_callchain *chain = sample->callchain; 1810 struct ip_callchain *chain = sample->callchain;
1814 int chain_nr = chain->nr; 1811 int chain_nr = chain->nr;
1815 u8 cpumode = PERF_RECORD_MISC_USER; 1812 u8 cpumode = PERF_RECORD_MISC_USER;
1816 int i, j, err, nr_entries, nr_contexts; 1813 int i, j, err, nr_entries;
1817 int skip_idx = -1; 1814 int skip_idx = -1;
1818 int first_call = 0; 1815 int first_call = 0;
1819 1816
@@ -1828,8 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1828 * Based on DWARF debug information, some architectures skip 1825 * Based on DWARF debug information, some architectures skip
1829 * a callchain entry saved by the kernel. 1826 * a callchain entry saved by the kernel.
1830 */ 1827 */
1831 if (chain_nr < sysctl_perf_event_max_stack) 1828 skip_idx = arch_skip_callchain_idx(thread, chain);
1832 skip_idx = arch_skip_callchain_idx(thread, chain);
1833 1829
1834 /* 1830 /*
1835 * Add branches to call stack for easier browsing. This gives 1831 * Add branches to call stack for easier browsing. This gives
@@ -1889,7 +1885,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1889 } 1885 }
1890 1886
1891check_calls: 1887check_calls:
1892 for (i = first_call, nr_entries = 0, nr_contexts = 0; 1888 for (i = first_call, nr_entries = 0;
1893 i < chain_nr && nr_entries < max_stack; i++) { 1889 i < chain_nr && nr_entries < max_stack; i++) {
1894 u64 ip; 1890 u64 ip;
1895 1891
@@ -1904,13 +1900,8 @@ check_calls:
1904#endif 1900#endif
1905 ip = chain->ips[j]; 1901 ip = chain->ips[j];
1906 1902
1907 if (ip >= PERF_CONTEXT_MAX) { 1903 if (ip < PERF_CONTEXT_MAX)
1908 if (++nr_contexts > sysctl_perf_event_max_contexts_per_stack) 1904 ++nr_entries;
1909 goto out_corrupted_callchain;
1910 } else {
1911 if (++nr_entries > sysctl_perf_event_max_stack)
1912 goto out_corrupted_callchain;
1913 }
1914 1905
1915 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); 1906 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1916 1907
@@ -1919,10 +1910,6 @@ check_calls:
1919 } 1910 }
1920 1911
1921 return 0; 1912 return 0;
1922
1923out_corrupted_callchain:
1924 pr_warning("corrupted callchain. skipping...\n");
1925 return 0;
1926} 1913}
1927 1914
1928static int unwind_entry(struct unwind_entry *entry, void *arg) 1915static int unwind_entry(struct unwind_entry *entry, void *arg)
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 83f46790c52f..41ac9cfd416b 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -28,6 +28,7 @@ struct machine {
28 pid_t pid; 28 pid_t pid;
29 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec; 30 bool comm_exec;
31 bool kptr_restrict_warned;
31 char *root_dir; 32 char *root_dir;
32 struct rb_root threads; 33 struct rb_root threads;
33 pthread_rwlock_t threads_lock; 34 pthread_rwlock_t threads_lock;
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 62c7f6988e0e..5d1eb1ccd96c 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -264,8 +264,7 @@ static SV *perl_process_callchain(struct perf_sample *sample,
264 goto exit; 264 goto exit;
265 265
266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, 266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
267 sample, NULL, NULL, 267 sample, NULL, NULL, scripting_max_stack) != 0) {
268 sysctl_perf_event_max_stack) != 0) {
269 pr_err("Failed to resolve callchain. Skipping\n"); 268 pr_err("Failed to resolve callchain. Skipping\n");
270 goto exit; 269 goto exit;
271 } 270 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2252b545ff43..20f9cb32b703 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2033,3 +2033,26 @@ void symbol__exit(void)
2033 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 2033 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
2034 symbol_conf.initialized = false; 2034 symbol_conf.initialized = false;
2035} 2035}
2036
2037int symbol__config_symfs(const struct option *opt __maybe_unused,
2038 const char *dir, int unset __maybe_unused)
2039{
2040 char *bf = NULL;
2041 int ret;
2042
2043 symbol_conf.symfs = strdup(dir);
2044 if (symbol_conf.symfs == NULL)
2045 return -ENOMEM;
2046
2047 /* skip the locally configured cache if a symfs is given, and
2048 * config buildid dir to symfs/.debug
2049 */
2050 ret = asprintf(&bf, "%s/%s", dir, ".debug");
2051 if (ret < 0)
2052 return -ENOMEM;
2053
2054 set_buildid_dir(bf);
2055
2056 free(bf);
2057 return 0;
2058}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 25f2fd672c2e..fa415347dbf9 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -290,6 +290,8 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);
290bool symbol__restricted_filename(const char *filename, 290bool symbol__restricted_filename(const char *filename,
291 const char *restricted_filename); 291 const char *restricted_filename);
292bool symbol__is_idle(struct symbol *sym); 292bool symbol__is_idle(struct symbol *sym);
293int symbol__config_symfs(const struct option *opt __maybe_unused,
294 const char *dir, int unset __maybe_unused);
293 295
294int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 296int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
295 struct symsrc *runtime_ss, symbol_filter_t filter, 297 struct symsrc *runtime_ss, symbol_filter_t filter,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index f92c37abb0a8..b2940c88734a 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -27,7 +27,6 @@ struct perf_top {
27 int max_stack; 27 int max_stack;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool use_tui, use_stdio; 29 bool use_tui, use_stdio;
30 bool kptr_restrict_warned;
31 bool vmlinux_warned; 30 bool vmlinux_warned;
32 bool dump_symtab; 31 bool dump_symtab;
33 struct hist_entry *sym_filter_entry; 32 struct hist_entry *sym_filter_entry;