perf/urgent fixes:
- 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: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJZNvv8AAoJENZQFvNTUqpAyvsP/01nEOO/fcIo3IDaTNFUxpHN olGvfk4C0Nxh0Nvus4Clf2z1i5GpWmAPBJ8EJkVzx3dHM7r1KBH2KITOzUf5ifok JY9h2mHkGT7wGXme0NqlElWNk3LyKbLYirWCdyZ1ZIRCW/XftcZLbWZn+KMxPbbS +PouuSUzlpCUvCd3KpmiMZMY5BmTRIF+xOVoChXFvrdqP4tZcBjPqPXTDlVl+/sp 9DtBARXAGDssEElhcNJi1XfXXwh/tf8AqQNV67WtUJZUTDQEBqRE8ctY1fek4+qm 0EzQvVirVlV/NFB3llgQ64XfY+ehhUVMtx+Zdqf3+1D8j+ovR0m9mjsXPKfzPwS8 ml49zWP5slr33OEhGIkkLxS2DQIisFz0PJ8C/tZrCqQS+oDPjJNiLb2u3hISmwdS n6HfMbrxyfqRQ5rFNUeo9EyHERAEZJFOEt6sBUDVfHsNdKBObGjUjWR4fKf8Bn3G UKgDdpAmYoZgd2fwmsXP2GcfZu9FBFAGFyfZRNNbwb11a0Ozb8KAqxm0Y1ETwbnj XOeFZ+pE4anoBJ0BzQpD8nYXfZFT9GLVa+v8VbRxnuVTg/Ccmf6UgWFkUZc7gxmL gT94HpEnsbCAg+JI+Z2S5KhdcjYM9GPCBxE1HtjxaJFv5iSc8S4PnrzuTTOGG3/T g+Mp4KKEyazvDHM/tt0S =Oasi -----END PGP SIGNATURE----- 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: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Коммит
3e411b0ee7
|
@ -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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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 {
|
||||||
{ .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)
|
||||||
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[] = {
|
||||||
{
|
{
|
||||||
.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)
|
||||||
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 {
|
||||||
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);
|
||||||
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
|
||||||
const char *s = strchr(ops->raw, '+');
|
const char *s = strchr(ops->raw, '+');
|
||||||
const char *c = strchr(ops->raw, ',');
|
const char *c = strchr(ops->raw, ',');
|
||||||
|
|
||||||
if (c++ != NULL)
|
/*
|
||||||
|
* 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);
|
ops->target.addr = strtoull(c, NULL, 16);
|
||||||
else
|
if (!ops->target.addr) {
|
||||||
|
c = strchr(c, ',');
|
||||||
|
if (c++ != NULL)
|
||||||
|
ops->target.addr = strtoull(c, NULL, 16);
|
||||||
|
}
|
||||||
|
} 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
|
||||||
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
|
||||||
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,
|
||||||
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,
|
||||||
#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,8 +1469,16 @@ 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) {
|
||||||
dso->kernel = dso_type;
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче