Commit 3e411b0e authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-urgent-for-mingo-4.12-20170606' of...

Merge tag 'perf-urgent-for-mingo-4.12-20170606' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 - Only print NMI watchdog hint in 'perf stat' when it is enabled (Andi Kleen)

 - Fix sys_mmap/sys_old_mmap shandling in s390 in 'perf trace' (Jiri Olsa)

 - Disable breakpoint signal tests in powerpc, that lacks the perf kernel
   glue to set breakpoint events and makes 'perf test' always fail (Jiri Olsa)

 - Fix 'perf annotate' for branch instruction with multiple operands (Kim Phillips)

 - Add missing powerpc triplet when disassembling with 'objdump' in 'perf
   annotate' (Kim Phillips)

 - Do not trow away partial unwound stacks when using libdw, making
   callchains produced with it similar to those produced when linked with
   the other DWARF unwind library supported in perf, libunwind (Milian Wolff)

 - Fixes to properly handle kernel modules when processing build-id meta
  events (Namhyung Kim)

 - Fix handling of compressed modules in the build-id cache (Namhyung Kim)

 - Fix 'perf annotate' failure when filename has special chars (Ravi Bangoria)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ba7b2387 2538b9e2
...@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = { ...@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = {
const char *const powerpc_triplets[] = { const char *const powerpc_triplets[] = {
"powerpc-unknown-linux-gnu-", "powerpc-unknown-linux-gnu-",
"powerpc-linux-gnu-",
"powerpc64-unknown-linux-gnu-", "powerpc64-unknown-linux-gnu-",
"powerpc64-linux-gnu-", "powerpc64-linux-gnu-",
"powerpc64le-linux-gnu-", "powerpc64le-linux-gnu-",
......
...@@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv) ...@@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv)
static void print_footer(void) static void print_footer(void)
{ {
FILE *output = stat_config.output; FILE *output = stat_config.output;
int n;
if (!null_run) if (!null_run)
fprintf(output, "\n"); fprintf(output, "\n");
...@@ -1590,7 +1591,9 @@ static void print_footer(void) ...@@ -1590,7 +1591,9 @@ static void print_footer(void)
} }
fprintf(output, "\n\n"); fprintf(output, "\n\n");
if (print_free_counters_hint) if (print_free_counters_hint &&
sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
n > 0)
fprintf(output, fprintf(output,
"Some events weren't counted. Try disabling the NMI watchdog:\n" "Some events weren't counted. Try disabling the NMI watchdog:\n"
" echo 0 > /proc/sys/kernel/nmi_watchdog\n" " echo 0 > /proc/sys/kernel/nmi_watchdog\n"
......
...@@ -681,6 +681,10 @@ static struct syscall_fmt { ...@@ -681,6 +681,10 @@ static struct syscall_fmt {
{ .name = "mlockall", .errmsg = true, { .name = "mlockall", .errmsg = true,
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
{ .name = "mmap", .hexret = true, { .name = "mmap", .hexret = true,
/* The standard mmap maps to old_mmap on s390x */
#if defined(__s390x__)
.alias = "old_mmap",
#endif
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ .arg_scnprintf = { [0] = SCA_HEX, /* addr */
[2] = SCA_MMAP_PROT, /* prot */ [2] = SCA_MMAP_PROT, /* prot */
[3] = SCA_MMAP_FLAGS, /* flags */ }, }, [3] = SCA_MMAP_FLAGS, /* flags */ }, },
......
...@@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused) ...@@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused)
return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ? return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
TEST_OK : TEST_FAIL; TEST_OK : TEST_FAIL;
} }
bool test__bp_signal_is_supported(void)
{
/*
* The powerpc so far does not have support to even create
* instruction breakpoint using the perf event interface.
* Once it's there we can release this.
*/
#ifdef __powerpc__
return false;
#else
return true;
#endif
}
...@@ -97,10 +97,12 @@ static struct test generic_tests[] = { ...@@ -97,10 +97,12 @@ static struct test generic_tests[] = {
{ {
.desc = "Breakpoint overflow signal handler", .desc = "Breakpoint overflow signal handler",
.func = test__bp_signal, .func = test__bp_signal,
.is_supported = test__bp_signal_is_supported,
}, },
{ {
.desc = "Breakpoint overflow sampling", .desc = "Breakpoint overflow sampling",
.func = test__bp_signal_overflow, .func = test__bp_signal_overflow,
.is_supported = test__bp_signal_is_supported,
}, },
{ {
.desc = "Number of exit events of a simple workload", .desc = "Number of exit events of a simple workload",
...@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) ...@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
if (!perf_test__matches(t, curr, argc, argv)) if (!perf_test__matches(t, curr, argc, argv))
continue; continue;
if (t->is_supported && !t->is_supported()) {
pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
continue;
}
pr_info("%2d: %-*s:", i, width, t->desc); pr_info("%2d: %-*s:", i, width, t->desc);
if (intlist__find(skiplist, i)) { if (intlist__find(skiplist, i)) {
......
...@@ -34,6 +34,7 @@ struct test { ...@@ -34,6 +34,7 @@ struct test {
int (*get_nr)(void); int (*get_nr)(void);
const char *(*get_desc)(int subtest); const char *(*get_desc)(int subtest);
} subtest; } subtest;
bool (*is_supported)(void);
}; };
/* Tests */ /* Tests */
...@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest); ...@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest);
int test__clang_subtest_get_nr(void); int test__clang_subtest_get_nr(void);
int test__unit_number__scnprint(int subtest); int test__unit_number__scnprint(int subtest);
bool test__bp_signal_is_supported(void);
#if defined(__arm__) || defined(__aarch64__) #if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT #ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread; struct thread;
......
...@@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op ...@@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
const char *s = strchr(ops->raw, '+'); const char *s = strchr(ops->raw, '+');
const char *c = strchr(ops->raw, ','); const char *c = strchr(ops->raw, ',');
/*
* skip over possible up to 2 operands to get to address, e.g.:
* tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
*/
if (c++ != NULL) {
ops->target.addr = strtoull(c, NULL, 16);
if (!ops->target.addr) {
c = strchr(c, ',');
if (c++ != NULL) if (c++ != NULL)
ops->target.addr = strtoull(c, NULL, 16); ops->target.addr = strtoull(c, NULL, 16);
else }
} else {
ops->target.addr = strtoull(ops->raw, NULL, 16); ops->target.addr = strtoull(ops->raw, NULL, 16);
}
if (s++ != NULL) { if (s++ != NULL) {
ops->target.offset = strtoull(s, NULL, 16); ops->target.offset = strtoull(s, NULL, 16);
...@@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op ...@@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
static int jump__scnprintf(struct ins *ins, char *bf, size_t size, static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops) struct ins_operands *ops)
{ {
const char *c = strchr(ops->raw, ',');
if (!ops->target.addr || ops->target.offset < 0) if (!ops->target.addr || ops->target.offset < 0)
return ins__raw_scnprintf(ins, bf, size, ops); return ins__raw_scnprintf(ins, bf, size, ops);
return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); if (c != NULL) {
const char *c2 = strchr(c + 1, ',');
/* check for 3-op insn */
if (c2 != NULL)
c = c2;
c++;
/* mirror arch objdump's space-after-comma style */
if (*c == ' ')
c++;
}
return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64,
ins->name, c ? c - ops->raw : 0, ops->raw,
ops->target.offset);
} }
static struct ins_ops jump_ops = { static struct ins_ops jump_ops = {
...@@ -1429,7 +1456,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na ...@@ -1429,7 +1456,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
snprintf(command, sizeof(command), snprintf(command, sizeof(command),
"%s %s%s --start-address=0x%016" PRIx64 "%s %s%s --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64
" -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand", " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
objdump_path ? objdump_path : "objdump", objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "", disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "", disassembler_style ? disassembler_style : "",
......
...@@ -335,6 +335,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, ...@@ -335,6 +335,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
return 0; return 0;
} }
void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine)
{
if (machine__is_host(machine))
dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
else
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */
if (m->kmod && m->comp)
dso->symtab_type++;
dso__set_short_name(dso, strdup(m->name), true);
}
/* /*
* Global list of open DSOs and the counter. * Global list of open DSOs and the counter.
*/ */
......
...@@ -259,6 +259,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, ...@@ -259,6 +259,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) #define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine);
/* /*
* The dso__data_* external interface provides following functions: * The dso__data_* external interface provides following functions:
* dso__data_get_fd * dso__data_get_fd
......
...@@ -1469,9 +1469,17 @@ static int __event_process_build_id(struct build_id_event *bev, ...@@ -1469,9 +1469,17 @@ static int __event_process_build_id(struct build_id_event *bev,
dso__set_build_id(dso, &bev->build_id); dso__set_build_id(dso, &bev->build_id);
if (!is_kernel_module(filename, cpumode)) if (dso_type != DSO_TYPE_USER) {
struct kmod_path m = { .name = NULL, };
if (!kmod_path__parse_name(&m, filename) && m.kmod)
dso__set_module_info(dso, &m, machine);
else
dso->kernel = dso_type; dso->kernel = dso_type;
free(m.name);
}
build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id__sprintf(dso->build_id, sizeof(dso->build_id),
sbuild_id); sbuild_id);
pr_debug("build id event received for %s: %s\n", pr_debug("build id event received for %s: %s\n",
......
...@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine, ...@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
if (dso == NULL) if (dso == NULL)
goto out_unlock; goto out_unlock;
if (machine__is_host(machine)) dso__set_module_info(dso, m, machine);
dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
else
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */
if (m->kmod && m->comp)
dso->symtab_type++;
dso__set_short_name(dso, strdup(m->name), true);
dso__set_long_name(dso, strdup(filename), true); dso__set_long_name(dso, strdup(filename), true);
} }
......
...@@ -649,10 +649,7 @@ static int decompress_kmodule(struct dso *dso, const char *name, ...@@ -649,10 +649,7 @@ static int decompress_kmodule(struct dso *dso, const char *name,
type != DSO_BINARY_TYPE__BUILD_ID_CACHE) type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
return -1; return -1;
if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE) if (kmod_path__parse_ext(&m, dso->long_name) || !m.comp)
name = dso->long_name;
if (kmod_path__parse_ext(&m, name) || !m.comp)
return -1; return -1;
fd = mkstemp(tmpbuf); fd = mkstemp(tmpbuf);
......
...@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip, ...@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip,
return 0; return 0;
mod = dwfl_addrmodule(ui->dwfl, ip); mod = dwfl_addrmodule(ui->dwfl, ip);
if (mod) {
Dwarf_Addr s;
dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
if (s != al->map->start)
mod = 0;
}
if (!mod) if (!mod)
mod = dwfl_report_elf(ui->dwfl, dso->short_name, mod = dwfl_report_elf(ui->dwfl, dso->short_name,
dso->long_name, -1, al->map->start, dso->long_name, -1, al->map->start,
...@@ -224,7 +232,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, ...@@ -224,7 +232,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
if (err && !ui->max_stack) if (err && ui->max_stack != max_stack)
err = 0; err = 0;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment