Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo-20160520' of git://git.kernel.org/pub/…
Browse files Browse the repository at this point in the history
…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>
  • Loading branch information
Ingo Molnar committed May 20, 2016
2 parents 1ab9418 + a706670 commit 408cf67
Show file tree
Hide file tree
Showing 19 changed files with 109 additions and 61 deletions.
2 changes: 1 addition & 1 deletion tools/perf/Documentation/perf-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ OPTIONS
Note that when using the --itrace option the synthesized callchain size
will override this value if the synthesized callchain size is bigger.

Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
Default: 127

-G::
--inverted::
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/Documentation/perf-script.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ include::itrace.txt[]
Note that when using the --itrace option the synthesized callchain size
will override this value if the synthesized callchain size is bigger.

Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
Default: 127

--ns::
Use 9 decimal places when displaying time (i.e. show the nanoseconds)
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/Documentation/perf-trace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
Implies '--call-graph dwarf' when --call-graph not present on the
command line, on systems where DWARF unwinding was built in.

Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
Default: /proc/sys/kernel/perf_event_max_stack when present for
live sessions (without --input/-i), 127 otherwise.

--min-stack::
Set the stack depth limit when parsing the callchain, anything
Expand Down
5 changes: 3 additions & 2 deletions tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
"Skip symbols that cannot be annotated"),
OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "symfs", NULL, "directory",
"Look for files with symbols relative to this directory",
symbol__config_symfs),
OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
"Interleave source code with assembly code (default)"),
OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
Expand Down
5 changes: 3 additions & 2 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,9 @@ static const struct option options[] = {
OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
"separator for columns, no spaces will be added between "
"columns '.' is reserved."),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "symfs", NULL, "directory",
"Look for files with symbols relative to this directory",
symbol__config_symfs),
OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
"How to display percentage of filtered entries", parse_filter_percentage),
Expand Down
7 changes: 4 additions & 3 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
.ordered_events = true,
.ordering_requires_timestamps = true,
},
.max_stack = sysctl_perf_event_max_stack,
.max_stack = PERF_MAX_STACK_DEPTH,
.pretty_printing_style = "normal",
.socket_filter = -1,
};
Expand Down Expand Up @@ -770,8 +770,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
"columns '.' is reserved."),
OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
"Only display entries resolved to a symbol"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "symfs", NULL, "directory",
"Look for files with symbols relative to this directory",
symbol__config_symfs),
OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
"list of cpus to profile"),
OPT_BOOLEAN('I', "show-info", &report.show_full_info,
Expand Down
7 changes: 3 additions & 4 deletions tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -2010,8 +2010,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"file", "kallsyms pathname"),
OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
"When printing symbols do not display call chain"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "symfs", NULL, "directory",
"Look for files with symbols relative to this directory",
symbol__config_symfs),
OPT_CALLBACK('F', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. "
Expand Down Expand Up @@ -2067,8 +2068,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
NULL
};

scripting_max_stack = sysctl_perf_event_max_stack;

setup_scripting();

argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
Expand Down
5 changes: 3 additions & 2 deletions tools/perf/builtin-timechart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv,
OPT_CALLBACK('p', "process", NULL, "process",
"process selector. Pass a pid or process name.",
parse_process),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "symfs", NULL, "directory",
"Look for files with symbols relative to this directory",
symbol__config_symfs),
OPT_INTEGER('n', "proc-num", &tchart.proc_num,
"min. number of tasks to print"),
OPT_BOOLEAN('t', "topology", &tchart.topology,
Expand Down
6 changes: 3 additions & 3 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (machine__resolve(machine, &al, sample) < 0)
return;

if (!top->kptr_restrict_warned &&
if (!machine->kptr_restrict_warned &&
symbol_conf.kptr_restrict &&
al.cpumode == PERF_RECORD_MISC_KERNEL) {
ui__warning(
Expand All @@ -743,7 +743,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
" modules" : "");
if (use_browser <= 0)
sleep(5);
top->kptr_restrict_warned = true;
machine->kptr_restrict_warned = true;
}

if (al.sym == NULL) {
Expand All @@ -759,7 +759,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
* --hide-kernel-symbols, even if the user specifies an
* invalid --vmlinux ;-)
*/
if (!top->kptr_restrict_warned && !top->vmlinux_warned &&
if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
if (symbol_conf.vmlinux_name) {
Expand Down
26 changes: 22 additions & 4 deletions tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,24 @@ static int trace__tool_process(struct perf_tool *tool,
return trace__process_event(trace, machine, event, sample);
}

static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
{
struct machine *machine = vmachine;

if (machine->kptr_restrict_warned)
return NULL;

if (symbol_conf.kptr_restrict) {
pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict.\n\n"
"Kernel samples will not be resolved.\n");
machine->kptr_restrict_warned = true;
return NULL;
}

return machine__resolve_kernel_addr(vmachine, addrp, modp);
}

static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
{
int err = symbol__init(NULL);
Expand All @@ -1171,7 +1189,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
if (trace->host == NULL)
return -ENOMEM;

if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
return -errno;

err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
Expand Down Expand Up @@ -1534,7 +1552,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
if (sc->is_exit) {
if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
fprintf(trace->output, "%-70s\n", ttrace->entry_str);
fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
}
} else {
ttrace->entry_pending = true;
Expand Down Expand Up @@ -2887,12 +2905,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
mmap_pages_user_set = false;

if (trace.max_stack == UINT_MAX) {
trace.max_stack = sysctl_perf_event_max_stack;
trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
max_stack_user_set = false;
}

#ifdef HAVE_DWARF_UNWIND_SUPPORT
if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
#endif

Expand Down
30 changes: 24 additions & 6 deletions tools/perf/util/annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,6 @@ static struct ins_ops nop_ops = {
.scnprintf = nop__scnprintf,
};

/*
* Must be sorted by name!
*/
static struct ins instructions[] = {
{ .name = "add", .ops = &mov_ops, },
{ .name = "addl", .ops = &mov_ops, },
Expand All @@ -372,8 +369,8 @@ static struct ins instructions[] = {
{ .name = "bgt", .ops = &jump_ops, },
{ .name = "bhi", .ops = &jump_ops, },
{ .name = "bl", .ops = &call_ops, },
{ .name = "blt", .ops = &jump_ops, },
{ .name = "bls", .ops = &jump_ops, },
{ .name = "blt", .ops = &jump_ops, },
{ .name = "blx", .ops = &call_ops, },
{ .name = "bne", .ops = &jump_ops, },
#endif
Expand Down Expand Up @@ -449,18 +446,39 @@ static struct ins instructions[] = {
{ .name = "xbeginq", .ops = &jump_ops, },
};

static int ins__cmp(const void *name, const void *insp)
static int ins__key_cmp(const void *name, const void *insp)
{
const struct ins *ins = insp;

return strcmp(name, ins->name);
}

static int ins__cmp(const void *a, const void *b)
{
const struct ins *ia = a;
const struct ins *ib = b;

return strcmp(ia->name, ib->name);
}

static void ins__sort(void)
{
const int nmemb = ARRAY_SIZE(instructions);

qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
}

static struct ins *ins__find(const char *name)
{
const int nmemb = ARRAY_SIZE(instructions);
static bool sorted;

if (!sorted) {
ins__sort();
sorted = true;
}

return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
}

int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
Expand Down
3 changes: 1 addition & 2 deletions tools/perf/util/db-export.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
*/
callchain_param.order = ORDER_CALLER;
err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
sample, NULL, NULL,
sysctl_perf_event_max_stack);
sample, NULL, NULL, PERF_MAX_STACK_DEPTH);
if (err) {
callchain_param.order = saved_order;
return NULL;
Expand Down
4 changes: 1 addition & 3 deletions tools/perf/util/dso.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
}
break;
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
/* skip the locally configured cache if a symfs is given */
if (symbol_conf.symfs[0] ||
(dso__build_id_filename(dso, filename, size) == NULL))
if (dso__build_id_filename(dso, filename, size) == NULL)
ret = -1;
break;

Expand Down
35 changes: 11 additions & 24 deletions tools/perf/util/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)

machine->symbol_filter = NULL;
machine->id_hdr_size = 0;
machine->kptr_restrict_warned = false;
machine->comm_exec = false;
machine->kernel_start = 0;

Expand Down Expand Up @@ -1135,10 +1136,10 @@ int machine__create_kernel_maps(struct machine *machine)
{
struct dso *kernel = machine__get_kernel(machine);
const char *name;
u64 addr = machine__get_running_kernel_start(machine, &name);
u64 addr;
int ret;

if (!addr || kernel == NULL)
if (kernel == NULL)
return -1;

ret = __machine__create_kernel_maps(machine, kernel);
Expand All @@ -1160,8 +1161,9 @@ int machine__create_kernel_maps(struct machine *machine)
*/
map_groups__fixup_end(&machine->kmaps);

if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
addr)) {
addr = machine__get_running_kernel_start(machine, &name);
if (!addr) {
} else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
machine__destroy_kernel_maps(machine);
return -1;
}
Expand Down Expand Up @@ -1769,11 +1771,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
*/
int mix_chain_nr = i + 1 + lbr_nr + 1;

if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) {
pr_warning("corrupted callchain. skipping...\n");
return 0;
}

for (j = 0; j < mix_chain_nr; j++) {
if (callchain_param.order == ORDER_CALLEE) {
if (j < i + 1)
Expand Down Expand Up @@ -1813,7 +1810,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
struct ip_callchain *chain = sample->callchain;
int chain_nr = chain->nr;
u8 cpumode = PERF_RECORD_MISC_USER;
int i, j, err, nr_entries, nr_contexts;
int i, j, err, nr_entries;
int skip_idx = -1;
int first_call = 0;

Expand All @@ -1828,8 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
* Based on DWARF debug information, some architectures skip
* a callchain entry saved by the kernel.
*/
if (chain_nr < sysctl_perf_event_max_stack)
skip_idx = arch_skip_callchain_idx(thread, chain);
skip_idx = arch_skip_callchain_idx(thread, chain);

/*
* Add branches to call stack for easier browsing. This gives
Expand Down Expand Up @@ -1889,7 +1885,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
}

check_calls:
for (i = first_call, nr_entries = 0, nr_contexts = 0;
for (i = first_call, nr_entries = 0;
i < chain_nr && nr_entries < max_stack; i++) {
u64 ip;

Expand All @@ -1904,13 +1900,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
#endif
ip = chain->ips[j];

if (ip >= PERF_CONTEXT_MAX) {
if (++nr_contexts > sysctl_perf_event_max_contexts_per_stack)
goto out_corrupted_callchain;
} else {
if (++nr_entries > sysctl_perf_event_max_stack)
goto out_corrupted_callchain;
}
if (ip < PERF_CONTEXT_MAX)
++nr_entries;

err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);

Expand All @@ -1919,10 +1910,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
}

return 0;

out_corrupted_callchain:
pr_warning("corrupted callchain. skipping...\n");
return 0;
}

static int unwind_entry(struct unwind_entry *entry, void *arg)
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct machine {
pid_t pid;
u16 id_hdr_size;
bool comm_exec;
bool kptr_restrict_warned;
char *root_dir;
struct rb_root threads;
pthread_rwlock_t threads_lock;
Expand Down
3 changes: 1 addition & 2 deletions tools/perf/util/scripting-engines/trace-event-perl.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,7 @@ static SV *perl_process_callchain(struct perf_sample *sample,
goto exit;

if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
sample, NULL, NULL,
sysctl_perf_event_max_stack) != 0) {
sample, NULL, NULL, scripting_max_stack) != 0) {
pr_err("Failed to resolve callchain. Skipping\n");
goto exit;
}
Expand Down
Loading

0 comments on commit 408cf67

Please sign in to comment.