Commit 2cb26c15 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v5.13-2021-06-04' of...

Merge tag 'perf-tools-fixes-for-v5.13-2021-06-04' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Fix NULL pointer dereference in 'perf probe' when handling
   DW_AT_const_value when looking for a variable, which is valid.

 - Fix for capability querying of perf_event_attr.cgroup support in
   older kernels.

 - Add missing cloning of evsel->use_config_name.

 - Honor event config name on --no-merge in 'perf stat'.

 - Fix some memory leaks found using ASAN.

 - Fix the perf entry for perf_event_attr setup with make LIBPFM4=1 on
   s390 z/VM.

 - Update MIPS UAPI perf_regs.h file.

 - Fix 'perf stat' BPF counter load return check.

* tag 'perf-tools-fixes-for-v5.13-2021-06-04' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf env: Fix memory leak of bpf_prog_info_linear member
  perf symbol-elf: Fix memory leak by freeing sdt_note.args
  perf stat: Honor event config name on --no-merge
  perf evsel: Add missing cloning of evsel->use_config_name
  perf test: Test 17 fails with make LIBPFM4=1 on s390 z/VM
  perf stat: Fix error return code in bperf__load()
  perf record: Move probing cgroup sampling support
  perf probe: Fix NULL pointer dereference in convert_variable_location()
  perf tools: Copy uapi/asm/perf_regs.h from the kernel for MIPS
parents ff609107 67069a1f
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_MIPS_PERF_REGS_H
#define _ASM_MIPS_PERF_REGS_H
enum perf_event_mips_regs {
PERF_REG_MIPS_PC,
PERF_REG_MIPS_R1,
PERF_REG_MIPS_R2,
PERF_REG_MIPS_R3,
PERF_REG_MIPS_R4,
PERF_REG_MIPS_R5,
PERF_REG_MIPS_R6,
PERF_REG_MIPS_R7,
PERF_REG_MIPS_R8,
PERF_REG_MIPS_R9,
PERF_REG_MIPS_R10,
PERF_REG_MIPS_R11,
PERF_REG_MIPS_R12,
PERF_REG_MIPS_R13,
PERF_REG_MIPS_R14,
PERF_REG_MIPS_R15,
PERF_REG_MIPS_R16,
PERF_REG_MIPS_R17,
PERF_REG_MIPS_R18,
PERF_REG_MIPS_R19,
PERF_REG_MIPS_R20,
PERF_REG_MIPS_R21,
PERF_REG_MIPS_R22,
PERF_REG_MIPS_R23,
PERF_REG_MIPS_R24,
PERF_REG_MIPS_R25,
PERF_REG_MIPS_R26,
PERF_REG_MIPS_R27,
PERF_REG_MIPS_R28,
PERF_REG_MIPS_R29,
PERF_REG_MIPS_R30,
PERF_REG_MIPS_R31,
PERF_REG_MIPS_MAX = PERF_REG_MIPS_R31 + 1,
};
#endif /* _ASM_MIPS_PERF_REGS_H */
...@@ -90,7 +90,6 @@ endif ...@@ -90,7 +90,6 @@ endif
ifeq ($(ARCH),mips) ifeq ($(ARCH),mips)
NO_PERF_REGS := 0 NO_PERF_REGS := 0
CFLAGS += -I$(OUTPUT)arch/mips/include/generated CFLAGS += -I$(OUTPUT)arch/mips/include/generated
CFLAGS += -I../../arch/mips/include/uapi -I../../arch/mips/include/generated/uapi
LIBUNWIND_LIBS = -lunwind -lunwind-mips LIBUNWIND_LIBS = -lunwind -lunwind-mips
endif endif
......
...@@ -2714,6 +2714,12 @@ int cmd_record(int argc, const char **argv) ...@@ -2714,6 +2714,12 @@ int cmd_record(int argc, const char **argv)
rec->no_buildid = true; rec->no_buildid = true;
} }
if (rec->opts.record_cgroup && !perf_can_record_cgroup()) {
pr_err("Kernel has no cgroup sampling support.\n");
err = -EINVAL;
goto out_opts;
}
if (rec->opts.kcore) if (rec->opts.kcore)
rec->data.is_dir = true; rec->data.is_dir = true;
......
...@@ -39,6 +39,7 @@ arch/x86/lib/x86-opcode-map.txt ...@@ -39,6 +39,7 @@ arch/x86/lib/x86-opcode-map.txt
arch/x86/tools/gen-insn-attr-x86.awk arch/x86/tools/gen-insn-attr-x86.awk
arch/arm/include/uapi/asm/perf_regs.h arch/arm/include/uapi/asm/perf_regs.h
arch/arm64/include/uapi/asm/perf_regs.h arch/arm64/include/uapi/asm/perf_regs.h
arch/mips/include/uapi/asm/perf_regs.h
arch/powerpc/include/uapi/asm/perf_regs.h arch/powerpc/include/uapi/asm/perf_regs.h
arch/s390/include/uapi/asm/perf_regs.h arch/s390/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/perf_regs.h arch/x86/include/uapi/asm/perf_regs.h
......
...@@ -16,7 +16,7 @@ pinned=0 ...@@ -16,7 +16,7 @@ pinned=0
exclusive=0 exclusive=0
exclude_user=0 exclude_user=0
exclude_kernel=0|1 exclude_kernel=0|1
exclude_hv=0 exclude_hv=0|1
exclude_idle=0 exclude_idle=0
mmap=1 mmap=1
comm=1 comm=1
......
...@@ -521,9 +521,10 @@ static int bperf__load(struct evsel *evsel, struct target *target) ...@@ -521,9 +521,10 @@ static int bperf__load(struct evsel *evsel, struct target *target)
evsel->bperf_leader_link_fd = bpf_link_get_fd_by_id(entry.link_id); evsel->bperf_leader_link_fd = bpf_link_get_fd_by_id(entry.link_id);
if (evsel->bperf_leader_link_fd < 0 && if (evsel->bperf_leader_link_fd < 0 &&
bperf_reload_leader_program(evsel, attr_map_fd, &entry)) bperf_reload_leader_program(evsel, attr_map_fd, &entry)) {
err = -1;
goto out; goto out;
}
/* /*
* The bpf_link holds reference to the leader program, and the * The bpf_link holds reference to the leader program, and the
* leader program holds reference to the maps. Therefore, if * leader program holds reference to the maps. Therefore, if
...@@ -550,6 +551,7 @@ static int bperf__load(struct evsel *evsel, struct target *target) ...@@ -550,6 +551,7 @@ static int bperf__load(struct evsel *evsel, struct target *target)
/* Step 2: load the follower skeleton */ /* Step 2: load the follower skeleton */
evsel->follower_skel = bperf_follower_bpf__open(); evsel->follower_skel = bperf_follower_bpf__open();
if (!evsel->follower_skel) { if (!evsel->follower_skel) {
err = -1;
pr_err("Failed to open follower skeleton\n"); pr_err("Failed to open follower skeleton\n");
goto out; goto out;
} }
......
...@@ -975,9 +975,13 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) ...@@ -975,9 +975,13 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
if ((tag == DW_TAG_formal_parameter || if ((tag == DW_TAG_formal_parameter ||
tag == DW_TAG_variable) && tag == DW_TAG_variable) &&
die_compare_name(die_mem, fvp->name) && die_compare_name(die_mem, fvp->name) &&
/* Does the DIE have location information or external instance? */ /*
* Does the DIE have location information or const value
* or external instance?
*/
(dwarf_attr(die_mem, DW_AT_external, &attr) || (dwarf_attr(die_mem, DW_AT_external, &attr) ||
dwarf_attr(die_mem, DW_AT_location, &attr))) dwarf_attr(die_mem, DW_AT_location, &attr) ||
dwarf_attr(die_mem, DW_AT_const_value, &attr)))
return DIE_FIND_CB_END; return DIE_FIND_CB_END;
if (dwarf_haspc(die_mem, fvp->addr)) if (dwarf_haspc(die_mem, fvp->addr))
return DIE_FIND_CB_CONTINUE; return DIE_FIND_CB_CONTINUE;
......
...@@ -144,6 +144,7 @@ static void perf_env__purge_bpf(struct perf_env *env) ...@@ -144,6 +144,7 @@ static void perf_env__purge_bpf(struct perf_env *env)
node = rb_entry(next, struct bpf_prog_info_node, rb_node); node = rb_entry(next, struct bpf_prog_info_node, rb_node);
next = rb_next(&node->rb_node); next = rb_next(&node->rb_node);
rb_erase(&node->rb_node, root); rb_erase(&node->rb_node, root);
free(node->info_linear);
free(node); free(node);
} }
......
...@@ -428,6 +428,7 @@ struct evsel *evsel__clone(struct evsel *orig) ...@@ -428,6 +428,7 @@ struct evsel *evsel__clone(struct evsel *orig)
evsel->auto_merge_stats = orig->auto_merge_stats; evsel->auto_merge_stats = orig->auto_merge_stats;
evsel->collect_stat = orig->collect_stat; evsel->collect_stat = orig->collect_stat;
evsel->weak_group = orig->weak_group; evsel->weak_group = orig->weak_group;
evsel->use_config_name = orig->use_config_name;
if (evsel__copy_config_terms(evsel, orig) < 0) if (evsel__copy_config_terms(evsel, orig) < 0)
goto out_err; goto out_err;
......
...@@ -83,8 +83,10 @@ struct evsel { ...@@ -83,8 +83,10 @@ struct evsel {
bool collect_stat; bool collect_stat;
bool weak_group; bool weak_group;
bool bpf_counter; bool bpf_counter;
bool use_config_name;
int bpf_fd; int bpf_fd;
struct bpf_object *bpf_obj; struct bpf_object *bpf_obj;
struct list_head config_terms;
}; };
/* /*
...@@ -116,10 +118,8 @@ struct evsel { ...@@ -116,10 +118,8 @@ struct evsel {
bool merged_stat; bool merged_stat;
bool reset_group; bool reset_group;
bool errored; bool errored;
bool use_config_name;
struct hashmap *per_pkg_mask; struct hashmap *per_pkg_mask;
struct evsel *leader; struct evsel *leader;
struct list_head config_terms;
int err; int err;
int cpu_iter; int cpu_iter;
struct { struct {
......
...@@ -103,6 +103,11 @@ static void perf_probe_build_id(struct evsel *evsel) ...@@ -103,6 +103,11 @@ static void perf_probe_build_id(struct evsel *evsel)
evsel->core.attr.build_id = 1; evsel->core.attr.build_id = 1;
} }
static void perf_probe_cgroup(struct evsel *evsel)
{
evsel->core.attr.cgroup = 1;
}
bool perf_can_sample_identifier(void) bool perf_can_sample_identifier(void)
{ {
return perf_probe_api(perf_probe_sample_identifier); return perf_probe_api(perf_probe_sample_identifier);
...@@ -182,3 +187,8 @@ bool perf_can_record_build_id(void) ...@@ -182,3 +187,8 @@ bool perf_can_record_build_id(void)
{ {
return perf_probe_api(perf_probe_build_id); return perf_probe_api(perf_probe_build_id);
} }
bool perf_can_record_cgroup(void)
{
return perf_probe_api(perf_probe_cgroup);
}
...@@ -12,5 +12,6 @@ bool perf_can_record_switch_events(void); ...@@ -12,5 +12,6 @@ bool perf_can_record_switch_events(void);
bool perf_can_record_text_poke_events(void); bool perf_can_record_text_poke_events(void);
bool perf_can_sample_identifier(void); bool perf_can_sample_identifier(void);
bool perf_can_record_build_id(void); bool perf_can_record_build_id(void);
bool perf_can_record_cgroup(void);
#endif // __PERF_API_PROBE_H #endif // __PERF_API_PROBE_H
...@@ -190,6 +190,9 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, ...@@ -190,6 +190,9 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
immediate_value_is_supported()) { immediate_value_is_supported()) {
Dwarf_Sword snum; Dwarf_Sword snum;
if (!tvar)
return 0;
dwarf_formsdata(&attr, &snum); dwarf_formsdata(&attr, &snum);
ret = asprintf(&tvar->value, "\\%ld", (long)snum); ret = asprintf(&tvar->value, "\\%ld", (long)snum);
......
...@@ -541,7 +541,7 @@ static void uniquify_event_name(struct evsel *counter) ...@@ -541,7 +541,7 @@ static void uniquify_event_name(struct evsel *counter)
char *config; char *config;
int ret = 0; int ret = 0;
if (counter->uniquified_name || if (counter->uniquified_name || counter->use_config_name ||
!counter->pmu_name || !strncmp(counter->name, counter->pmu_name, !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
strlen(counter->pmu_name))) strlen(counter->pmu_name)))
return; return;
...@@ -555,10 +555,8 @@ static void uniquify_event_name(struct evsel *counter) ...@@ -555,10 +555,8 @@ static void uniquify_event_name(struct evsel *counter)
} }
} else { } else {
if (perf_pmu__has_hybrid()) { if (perf_pmu__has_hybrid()) {
if (!counter->use_config_name) {
ret = asprintf(&new_name, "%s/%s/", ret = asprintf(&new_name, "%s/%s/",
counter->pmu_name, counter->name); counter->pmu_name, counter->name);
}
} else { } else {
ret = asprintf(&new_name, "%s [%s]", ret = asprintf(&new_name, "%s [%s]",
counter->name, counter->pmu_name); counter->name, counter->pmu_name);
......
...@@ -2412,6 +2412,7 @@ int cleanup_sdt_note_list(struct list_head *sdt_notes) ...@@ -2412,6 +2412,7 @@ int cleanup_sdt_note_list(struct list_head *sdt_notes)
list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) { list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
list_del_init(&pos->note_list); list_del_init(&pos->note_list);
zfree(&pos->args);
zfree(&pos->name); zfree(&pos->name);
zfree(&pos->provider); zfree(&pos->provider);
free(pos); free(pos);
......
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