Merge tag 'perf-tools-fixes-for-v5.14-2021-07-18' of git://git.kernel.org/pub/scm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Jul 2021 19:20:27 +0000 (12:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 18 Jul 2021 19:20:27 +0000 (12:20 -0700)
Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Skip invalid hybrid PMU on hybrid systems when the atom (little) CPUs
   are offlined.

 - Fix 'perf test' problems related to the recently added hybrid
   (BIG/little) code.

 - Split ARM's coresight (hw tracing) decode by aux records to avoid
   fatal decoding errors.

 - Fix add event failure in 'perf probe' when running 32-bit perf in a
   64-bit kernel.

 - Fix 'perf sched record' failure when CONFIG_SCHEDSTATS is not set.

 - Fix memory and refcount leaks detected by ASAn when running 'perf
   test', should be clean of warnings now.

 - Remove broken definition of __LITTLE_ENDIAN from tools'
   linux/kconfig.h, which was breaking the build in some systems.

 - Cast PTHREAD_STACK_MIN to int as it may turn into 'long
   sysconf(__SC_THREAD_STACK_MIN_VALUE), breaking the build in some
   systems.

 - Fix libperf build error with LIBPFM4=1.

 - Sync UAPI files changed by the memfd_secret new syscall.

* tag 'perf-tools-fixes-for-v5.14-2021-07-18' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (35 commits)
  perf sched: Fix record failure when CONFIG_SCHEDSTATS is not set
  perf probe: Fix add event failure when running 32-bit perf in a 64-bit kernel
  perf data: Close all files in close_dir()
  perf probe-file: Delete namelist in del_events() on the error path
  perf test bpf: Free obj_buf
  perf trace: Free strings in trace__parse_events_option()
  perf trace: Free syscall tp fields in evsel->priv
  perf trace: Free syscall->arg_fmt
  perf trace: Free malloc'd trace fields on exit
  perf lzma: Close lzma stream on exit
  perf script: Fix memory 'threads' and 'cpus' leaks on exit
  perf script: Release zstd data
  perf session: Cleanup trace_event
  perf inject: Close inject.output on exit
  perf report: Free generated help strings for sort option
  perf env: Fix memory leak of cpu_pmu_caps
  perf test maps__merge_in: Fix memory leak of maps
  perf dso: Fix memory leak in dso__new_map()
  perf test event_update: Fix memory leak of unit
  perf test event_update: Fix memory leak of evlist
  ...

36 files changed:
tools/arch/arm64/include/uapi/asm/unistd.h
tools/include/linux/kconfig.h
tools/include/uapi/asm-generic/unistd.h
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/builtin-inject.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-trace.c
tools/perf/tests/bpf.c
tools/perf/tests/event_update.c
tools/perf/tests/evsel-roundtrip-name.c
tools/perf/tests/maps.c
tools/perf/tests/parse-events.c
tools/perf/tests/perf-time-to-tsc.c
tools/perf/tests/topology.c
tools/perf/util/cs-etm.c
tools/perf/util/data.c
tools/perf/util/dso.c
tools/perf/util/dwarf-aux.c
tools/perf/util/dwarf-aux.h
tools/perf/util/env.c
tools/perf/util/lzma.c
tools/perf/util/map.c
tools/perf/util/pfm.c
tools/perf/util/pmu.c
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-file.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/session.c
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/stat-display.c

index f83a70e..ce2ee8f 100644 (file)
@@ -20,5 +20,6 @@
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
 #define __ARCH_WANT_SYS_CLONE3
+#define __ARCH_WANT_MEMFD_SECRET
 
 #include <asm-generic/unistd.h>
index 1555a0c..13b86bd 100644 (file)
@@ -4,12 +4,6 @@
 
 /* CONFIG_CC_VERSION_TEXT (Do not delete this comment. See help in Kconfig) */
 
-#ifdef CONFIG_CPU_BIG_ENDIAN
-#define __BIG_ENDIAN 4321
-#else
-#define __LITTLE_ENDIAN 1234
-#endif
-
 #define __ARG_PLACEHOLDER_1 0,
 #define __take_second_arg(__ignored, val, ...) val
 
index f211961..a9d6fcd 100644 (file)
@@ -873,8 +873,13 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
 #define __NR_landlock_restrict_self 446
 __SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
 
+#ifdef __ARCH_WANT_MEMFD_SECRET
+#define __NR_memfd_secret 447
+__SYSCALL(__NR_memfd_secret, sys_memfd_secret)
+#endif
+
 #undef __NR_syscalls
-#define __NR_syscalls 447
+#define __NR_syscalls 448
 
 /*
  * 32 bit systems traditionally used different
index af973e4..f6b5779 100644 (file)
 444    common  landlock_create_ruleset sys_landlock_create_ruleset
 445    common  landlock_add_rule       sys_landlock_add_rule
 446    common  landlock_restrict_self  sys_landlock_restrict_self
+447    common  memfd_secret            sys_memfd_secret
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
index 5d6f583..c88c61e 100644 (file)
@@ -361,9 +361,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
                dso = machine__findnew_dso_id(machine, filename, id);
        }
 
-       if (dso)
+       if (dso) {
+               nsinfo__put(dso->nsinfo);
                dso->nsinfo = nsi;
-       else
+       else
                nsinfo__put(nsi);
 
        thread__put(thread);
@@ -992,8 +993,10 @@ int cmd_inject(int argc, const char **argv)
 
        data.path = inject.input_name;
        inject.session = perf_session__new(&data, inject.output.is_pipe, &inject.tool);
-       if (IS_ERR(inject.session))
-               return PTR_ERR(inject.session);
+       if (IS_ERR(inject.session)) {
+               ret = PTR_ERR(inject.session);
+               goto out_close_output;
+       }
 
        if (zstd_init(&(inject.session->zstd_data), 0) < 0)
                pr_warning("Decompression initialization failed.\n");
@@ -1035,6 +1038,8 @@ int cmd_inject(int argc, const char **argv)
 out_delete:
        zstd_fini(&(inject.session->zstd_data));
        perf_session__delete(inject.session);
+out_close_output:
+       perf_data__close(&inject.output);
        free(inject.itrace_synth_opts.vm_tm_corr_args);
        return ret;
 }
index 6386af6..dc0364f 100644 (file)
@@ -1175,6 +1175,8 @@ int cmd_report(int argc, const char **argv)
                .annotation_opts         = annotation__default_options,
                .skip_empty              = true,
        };
+       char *sort_order_help = sort_help("sort by key(s):");
+       char *field_order_help = sort_help("output field(s): overhead period sample ");
        const struct option options[] = {
        OPT_STRING('i', "input", &input_name, "file",
                    "input file name"),
@@ -1209,9 +1211,9 @@ int cmd_report(int argc, const char **argv)
        OPT_BOOLEAN(0, "header-only", &report.header_only,
                    "Show only data header."),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
-                  sort_help("sort by key(s):")),
+                  sort_order_help),
        OPT_STRING('F', "fields", &field_order, "key[,keys...]",
-                  sort_help("output field(s): overhead period sample ")),
+                  field_order_help),
        OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
                    "Show sample percentage for different cpu modes"),
        OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -1344,11 +1346,11 @@ int cmd_report(int argc, const char **argv)
        char sort_tmp[128];
 
        if (ret < 0)
-               return ret;
+               goto exit;
 
        ret = perf_config(report__config, &report);
        if (ret)
-               return ret;
+               goto exit;
 
        argc = parse_options(argc, argv, options, report_usage, 0);
        if (argc) {
@@ -1362,8 +1364,10 @@ int cmd_report(int argc, const char **argv)
                report.symbol_filter_str = argv[0];
        }
 
-       if (annotate_check_args(&report.annotation_opts) < 0)
-               return -EINVAL;
+       if (annotate_check_args(&report.annotation_opts) < 0) {
+               ret = -EINVAL;
+               goto exit;
+       }
 
        if (report.mmaps_mode)
                report.tasks_mode = true;
@@ -1377,12 +1381,14 @@ int cmd_report(int argc, const char **argv)
        if (symbol_conf.vmlinux_name &&
            access(symbol_conf.vmlinux_name, R_OK)) {
                pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto exit;
        }
        if (symbol_conf.kallsyms_name &&
            access(symbol_conf.kallsyms_name, R_OK)) {
                pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto exit;
        }
 
        if (report.inverted_callchain)
@@ -1406,12 +1412,14 @@ int cmd_report(int argc, const char **argv)
 
 repeat:
        session = perf_session__new(&data, false, &report.tool);
-       if (IS_ERR(session))
-               return PTR_ERR(session);
+       if (IS_ERR(session)) {
+               ret = PTR_ERR(session);
+               goto exit;
+       }
 
        ret = evswitch__init(&report.evswitch, session->evlist, stderr);
        if (ret)
-               return ret;
+               goto exit;
 
        if (zstd_init(&(session->zstd_data), 0) < 0)
                pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
@@ -1646,5 +1654,8 @@ error:
 
        zstd_fini(&(session->zstd_data));
        perf_session__delete(session);
+exit:
+       free(sort_order_help);
+       free(field_order_help);
        return ret;
 }
index 954ce2f..1ff10d4 100644 (file)
@@ -670,7 +670,7 @@ static void create_tasks(struct perf_sched *sched)
        err = pthread_attr_init(&attr);
        BUG_ON(err);
        err = pthread_attr_setstacksize(&attr,
-                       (size_t) max(16 * 1024, PTHREAD_STACK_MIN));
+                       (size_t) max(16 * 1024, (int)PTHREAD_STACK_MIN));
        BUG_ON(err);
        err = pthread_mutex_lock(&sched->start_work_mutex);
        BUG_ON(err);
@@ -3335,6 +3335,16 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options
        sort_dimension__add("pid", &sched->cmp_pid);
 }
 
+static bool schedstat_events_exposed(void)
+{
+       /*
+        * Select "sched:sched_stat_wait" event to check
+        * whether schedstat tracepoints are exposed.
+        */
+       return IS_ERR(trace_event__tp_format("sched", "sched_stat_wait")) ?
+               false : true;
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
        unsigned int rec_argc, i, j;
@@ -3346,21 +3356,33 @@ static int __cmd_record(int argc, const char **argv)
                "-m", "1024",
                "-c", "1",
                "-e", "sched:sched_switch",
-               "-e", "sched:sched_stat_wait",
-               "-e", "sched:sched_stat_sleep",
-               "-e", "sched:sched_stat_iowait",
                "-e", "sched:sched_stat_runtime",
                "-e", "sched:sched_process_fork",
                "-e", "sched:sched_wakeup_new",
                "-e", "sched:sched_migrate_task",
        };
+
+       /*
+        * The tracepoints trace_sched_stat_{wait, sleep, iowait}
+        * are not exposed to user if CONFIG_SCHEDSTATS is not set,
+        * to prevent "perf sched record" execution failure, determine
+        * whether to record schedstat events according to actual situation.
+        */
+       const char * const schedstat_args[] = {
+               "-e", "sched:sched_stat_wait",
+               "-e", "sched:sched_stat_sleep",
+               "-e", "sched:sched_stat_iowait",
+       };
+       unsigned int schedstat_argc = schedstat_events_exposed() ?
+               ARRAY_SIZE(schedstat_args) : 0;
+
        struct tep_event *waking_event;
 
        /*
         * +2 for either "-e", "sched:sched_wakeup" or
         * "-e", "sched:sched_waking"
         */
-       rec_argc = ARRAY_SIZE(record_args) + 2 + argc - 1;
+       rec_argc = ARRAY_SIZE(record_args) + 2 + schedstat_argc + argc - 1;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
        if (rec_argv == NULL)
@@ -3376,6 +3398,9 @@ static int __cmd_record(int argc, const char **argv)
        else
                rec_argv[i++] = strdup("sched:sched_wakeup");
 
+       for (j = 0; j < schedstat_argc; j++)
+               rec_argv[i++] = strdup(schedstat_args[j]);
+
        for (j = 1; j < (unsigned int)argc; j++, i++)
                rec_argv[i] = argv[j];
 
index 8c03a98..064da7f 100644 (file)
@@ -2601,6 +2601,12 @@ static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
        }
 }
 
+static void perf_script__exit(struct perf_script *script)
+{
+       perf_thread_map__put(script->threads);
+       perf_cpu_map__put(script->cpus);
+}
+
 static int __cmd_script(struct perf_script *script)
 {
        int ret;
@@ -4143,8 +4149,10 @@ out_delete:
                zfree(&script.ptime_range);
        }
 
+       zstd_fini(&(session->zstd_data));
        evlist__free_stats(session->evlist);
        perf_session__delete(session);
+       perf_script__exit(&script);
 
        if (script_started)
                cleanup_scripting();
index d25cb80..6343759 100644 (file)
@@ -2445,9 +2445,6 @@ int cmd_stat(int argc, const char **argv)
 
        evlist__check_cpu_maps(evsel_list);
 
-       if (perf_pmu__has_hybrid())
-               stat_config.no_merge = true;
-
        /*
         * Initialize thread_map with comm names,
         * so we could print it out on output.
index 7ec18ff..9c265fa 100644 (file)
@@ -2266,6 +2266,14 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
        return augmented_args;
 }
 
+static void syscall__exit(struct syscall *sc)
+{
+       if (!sc)
+               return;
+
+       free(sc->arg_fmt);
+}
+
 static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
                            union perf_event *event __maybe_unused,
                            struct perf_sample *sample)
@@ -3095,6 +3103,21 @@ static struct evsel *evsel__new_pgfault(u64 config)
        return evsel;
 }
 
+static void evlist__free_syscall_tp_fields(struct evlist *evlist)
+{
+       struct evsel *evsel;
+
+       evlist__for_each_entry(evlist, evsel) {
+               struct evsel_trace *et = evsel->priv;
+
+               if (!et || !evsel->tp_format || strcmp(evsel->tp_format->system, "syscalls"))
+                       continue;
+
+               free(et->fmt);
+               free(et);
+       }
+}
+
 static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
 {
        const u32 type = event->header.type;
@@ -4130,7 +4153,7 @@ out_disable:
 
 out_delete_evlist:
        trace__symbols__exit(trace);
-
+       evlist__free_syscall_tp_fields(evlist);
        evlist__delete(evlist);
        cgroup__put(trace->cgroup);
        trace->evlist = NULL;
@@ -4636,6 +4659,9 @@ do_concat:
                err = parse_events_option(&o, lists[0], 0);
        }
 out:
+       free(strace_groups_dir);
+       free(lists[0]);
+       free(lists[1]);
        if (sep)
                *sep = ',';
 
@@ -4701,6 +4727,21 @@ out:
        return err;
 }
 
+static void trace__exit(struct trace *trace)
+{
+       int i;
+
+       strlist__delete(trace->ev_qualifier);
+       free(trace->ev_qualifier_ids.entries);
+       if (trace->syscalls.table) {
+               for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
+                       syscall__exit(&trace->syscalls.table[i]);
+               free(trace->syscalls.table);
+       }
+       syscalltbl__delete(trace->sctbl);
+       zfree(&trace->perfconfig_events);
+}
+
 int cmd_trace(int argc, const char **argv)
 {
        const char *trace_usage[] = {
@@ -5135,6 +5176,6 @@ out_close:
        if (output_name != NULL)
                fclose(trace.output);
 out:
-       zfree(&trace.perfconfig_events);
+       trace__exit(&trace);
        return err;
 }
index 33bda9c..dbf5f52 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/epoll.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -276,6 +277,7 @@ static int __test__bpf(int idx)
        }
 
 out:
+       free(obj_buf);
        bpf__clear();
        return ret;
 }
index 6562181..44a5052 100644 (file)
@@ -88,6 +88,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
        struct evsel *evsel;
        struct event_name tmp;
        struct evlist *evlist = evlist__new_default();
+       char *unit = strdup("KRAVA");
 
        TEST_ASSERT_VAL("failed to get evlist", evlist);
 
@@ -98,7 +99,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
 
        perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123);
 
-       evsel->unit = strdup("KRAVA");
+       evsel->unit = unit;
 
        TEST_ASSERT_VAL("failed to synthesize attr update unit",
                        !perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
@@ -118,6 +119,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
        TEST_ASSERT_VAL("failed to synthesize attr update cpus",
                        !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
 
-       perf_cpu_map__put(evsel->core.own_cpus);
+       free(unit);
+       evlist__delete(evlist);
        return 0;
 }
index 5ebf563..4e09f0a 100644 (file)
@@ -5,6 +5,7 @@
 #include "tests.h"
 #include "debug.h"
 #include "pmu.h"
+#include "pmu-hybrid.h"
 #include <errno.h>
 #include <linux/kernel.h>
 
@@ -102,7 +103,7 @@ int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int
 {
        int err = 0, ret = 0;
 
-       if (perf_pmu__has_hybrid())
+       if (perf_pmu__has_hybrid() && perf_pmu__hybrid_mounted("cpu_atom"))
                return perf_evsel__name_array_test(evsel__hw_names, 2);
 
        err = perf_evsel__name_array_test(evsel__hw_names, 1);
index edcbc70..1ac7291 100644 (file)
@@ -116,5 +116,7 @@ int test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unus
 
        ret = check_maps(merged3, ARRAY_SIZE(merged3), &maps);
        TEST_ASSERT_VAL("merge check failed", !ret);
+
+       maps__exit(&maps);
        return TEST_OK;
 }
index 56a7b6a..8d48667 100644 (file)
@@ -6,6 +6,7 @@
 #include "tests.h"
 #include "debug.h"
 #include "pmu.h"
+#include "pmu-hybrid.h"
 #include <dirent.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -1596,6 +1597,13 @@ static int test__hybrid_raw1(struct evlist *evlist)
 {
        struct evsel *evsel = evlist__first(evlist);
 
+       if (!perf_pmu__hybrid_mounted("cpu_atom")) {
+               TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
+               TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
+               TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config);
+               return 0;
+       }
+
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
        TEST_ASSERT_VAL("wrong config", 0x1a == evsel->core.attr.config);
@@ -1620,13 +1628,9 @@ static int test__hybrid_cache_event(struct evlist *evlist)
 {
        struct evsel *evsel = evlist__first(evlist);
 
-       TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
+       TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type);
        TEST_ASSERT_VAL("wrong config", 0x2 == (evsel->core.attr.config & 0xffffffff));
-
-       evsel = evsel__next(evsel);
-       TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type);
-       TEST_ASSERT_VAL("wrong config", 0x10002 == (evsel->core.attr.config & 0xffffffff));
        return 0;
 }
 
@@ -2028,7 +2032,7 @@ static struct evlist_test test__hybrid_events[] = {
                .id    = 7,
        },
        {
-               .name  = "cpu_core/LLC-loads/,cpu_atom/LLC-load-misses/",
+               .name  = "cpu_core/LLC-loads/",
                .check = test__hybrid_cache_event,
                .id    = 8,
        },
index 85d75b9..7c56bc1 100644 (file)
@@ -21,6 +21,7 @@
 #include "mmap.h"
 #include "tests.h"
 #include "pmu.h"
+#include "pmu-hybrid.h"
 
 #define CHECK__(x) {                           \
        while ((x) < 0) {                       \
@@ -93,7 +94,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
         * For hybrid "cycles:u", it creates two events.
         * Init the second evsel here.
         */
-       if (perf_pmu__has_hybrid()) {
+       if (perf_pmu__has_hybrid() && perf_pmu__hybrid_mounted("cpu_atom")) {
                evsel = evsel__next(evsel);
                evsel->core.attr.comm = 1;
                evsel->core.attr.disabled = 1;
index ec4e3b2..b5efe67 100644 (file)
@@ -61,6 +61,7 @@ static int session_write_header(char *path)
        TEST_ASSERT_VAL("failed to write header",
                        !perf_session__write_header(session, session->evlist, data.file.fd, true));
 
+       evlist__delete(session->evlist);
        perf_session__delete(session);
 
        return 0;
index 32ad92d..22f8326 100644 (file)
@@ -2683,6 +2683,172 @@ static u64 *cs_etm__create_meta_blk(u64 *buff_in, int *buff_in_offset,
        return metadata;
 }
 
+/**
+ * Puts a fragment of an auxtrace buffer into the auxtrace queues based
+ * on the bounds of aux_event, if it matches with the buffer that's at
+ * file_offset.
+ *
+ * Normally, whole auxtrace buffers would be added to the queue. But we
+ * want to reset the decoder for every PERF_RECORD_AUX event, and the decoder
+ * is reset across each buffer, so splitting the buffers up in advance has
+ * the same effect.
+ */
+static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_offset, size_t sz,
+                                     struct perf_record_aux *aux_event, struct perf_sample *sample)
+{
+       int err;
+       char buf[PERF_SAMPLE_MAX_SIZE];
+       union perf_event *auxtrace_event_union;
+       struct perf_record_auxtrace *auxtrace_event;
+       union perf_event auxtrace_fragment;
+       __u64 aux_offset, aux_size;
+
+       struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
+                                                  struct cs_etm_auxtrace,
+                                                  auxtrace);
+
+       /*
+        * There should be a PERF_RECORD_AUXTRACE event at the file_offset that we got
+        * from looping through the auxtrace index.
+        */
+       err = perf_session__peek_event(session, file_offset, buf,
+                                      PERF_SAMPLE_MAX_SIZE, &auxtrace_event_union, NULL);
+       if (err)
+               return err;
+       auxtrace_event = &auxtrace_event_union->auxtrace;
+       if (auxtrace_event->header.type != PERF_RECORD_AUXTRACE)
+               return -EINVAL;
+
+       if (auxtrace_event->header.size < sizeof(struct perf_record_auxtrace) ||
+               auxtrace_event->header.size != sz) {
+               return -EINVAL;
+       }
+
+       /*
+        * In per-thread mode, CPU is set to -1, but TID will be set instead. See
+        * auxtrace_mmap_params__set_idx(). Return 'not found' if neither CPU nor TID match.
+        */
+       if ((auxtrace_event->cpu == (__u32) -1 && auxtrace_event->tid != sample->tid) ||
+                       auxtrace_event->cpu != sample->cpu)
+               return 1;
+
+       if (aux_event->flags & PERF_AUX_FLAG_OVERWRITE) {
+               /*
+                * Clamp size in snapshot mode. The buffer size is clamped in
+                * __auxtrace_mmap__read() for snapshots, so the aux record size doesn't reflect
+                * the buffer size.
+                */
+               aux_size = min(aux_event->aux_size, auxtrace_event->size);
+
+               /*
+                * In this mode, the head also points to the end of the buffer so aux_offset
+                * needs to have the size subtracted so it points to the beginning as in normal mode
+                */
+               aux_offset = aux_event->aux_offset - aux_size;
+       } else {
+               aux_size = aux_event->aux_size;
+               aux_offset = aux_event->aux_offset;
+       }
+
+       if (aux_offset >= auxtrace_event->offset &&
+           aux_offset + aux_size <= auxtrace_event->offset + auxtrace_event->size) {
+               /*
+                * If this AUX event was inside this buffer somewhere, create a new auxtrace event
+                * based on the sizes of the aux event, and queue that fragment.
+                */
+               auxtrace_fragment.auxtrace = *auxtrace_event;
+               auxtrace_fragment.auxtrace.size = aux_size;
+               auxtrace_fragment.auxtrace.offset = aux_offset;
+               file_offset += aux_offset - auxtrace_event->offset + auxtrace_event->header.size;
+
+               pr_debug3("CS ETM: Queue buffer size: %#"PRI_lx64" offset: %#"PRI_lx64
+                         " tid: %d cpu: %d\n", aux_size, aux_offset, sample->tid, sample->cpu);
+               return auxtrace_queues__add_event(&etm->queues, session, &auxtrace_fragment,
+                                                 file_offset, NULL);
+       }
+
+       /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */
+       return 1;
+}
+
+static int cs_etm__queue_aux_records_cb(struct perf_session *session, union perf_event *event,
+                                       u64 offset __maybe_unused, void *data __maybe_unused)
+{
+       struct perf_sample sample;
+       int ret;
+       struct auxtrace_index_entry *ent;
+       struct auxtrace_index *auxtrace_index;
+       struct evsel *evsel;
+       size_t i;
+
+       /* Don't care about any other events, we're only queuing buffers for AUX events */
+       if (event->header.type != PERF_RECORD_AUX)
+               return 0;
+
+       if (event->header.size < sizeof(struct perf_record_aux))
+               return -EINVAL;
+
+       /* Truncated Aux records can have 0 size and shouldn't result in anything being queued. */
+       if (!event->aux.aux_size)
+               return 0;
+
+       /*
+        * Parse the sample, we need the sample_id_all data that comes after the event so that the
+        * CPU or PID can be matched to an AUXTRACE buffer's CPU or PID.
+        */
+       evsel = evlist__event2evsel(session->evlist, event);
+       if (!evsel)
+               return -EINVAL;
+       ret = evsel__parse_sample(evsel, event, &sample);
+       if (ret)
+               return ret;
+
+       /*
+        * Loop through the auxtrace index to find the buffer that matches up with this aux event.
+        */
+       list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
+               for (i = 0; i < auxtrace_index->nr; i++) {
+                       ent = &auxtrace_index->entries[i];
+                       ret = cs_etm__queue_aux_fragment(session, ent->file_offset,
+                                                        ent->sz, &event->aux, &sample);
+                       /*
+                        * Stop search on error or successful values. Continue search on
+                        * 1 ('not found')
+                        */
+                       if (ret != 1)
+                               return ret;
+               }
+       }
+
+       /*
+        * Couldn't find the buffer corresponding to this aux record, something went wrong. Warn but
+        * don't exit with an error because it will still be possible to decode other aux records.
+        */
+       pr_err("CS ETM: Couldn't find auxtrace buffer for aux_offset: %#"PRI_lx64
+              " tid: %d cpu: %d\n", event->aux.aux_offset, sample.tid, sample.cpu);
+       return 0;
+}
+
+static int cs_etm__queue_aux_records(struct perf_session *session)
+{
+       struct auxtrace_index *index = list_first_entry_or_null(&session->auxtrace_index,
+                                                               struct auxtrace_index, list);
+       if (index && index->nr > 0)
+               return perf_session__peek_events(session, session->header.data_offset,
+                                                session->header.data_size,
+                                                cs_etm__queue_aux_records_cb, NULL);
+
+       /*
+        * We would get here if there are no entries in the index (either no auxtrace
+        * buffers or no index at all). Fail silently as there is the possibility of
+        * queueing them in cs_etm__process_auxtrace_event() if etm->data_queued is still
+        * false.
+        *
+        * In that scenario, buffers will not be split by AUX records.
+        */
+       return 0;
+}
+
 int cs_etm__process_auxtrace_info(union perf_event *event,
                                  struct perf_session *session)
 {
@@ -2883,7 +3049,7 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
        if (err)
                goto err_delete_thread;
 
-       err = auxtrace_queues__process_index(&etm->queues, session);
+       err = cs_etm__queue_aux_records(session);
        if (err)
                goto err_delete_thread;
 
index a9c102e..f5d260b 100644 (file)
@@ -20,7 +20,7 @@
 
 static void close_dir(struct perf_data_file *files, int nr)
 {
-       while (--nr >= 1) {
+       while (--nr >= 0) {
                close(files[nr].fd);
                zfree(&files[nr].path);
        }
index d786cf6..ee15db2 100644 (file)
@@ -1154,8 +1154,10 @@ struct map *dso__new_map(const char *name)
        struct map *map = NULL;
        struct dso *dso = dso__new(name);
 
-       if (dso)
+       if (dso) {
                map = map__new2(0, dso);
+               dso__put(dso);
+       }
 
        return map;
 }
index 7d2ba84..609ca16 100644 (file)
@@ -113,14 +113,14 @@ static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
  *
  * Find a line number and file name for @addr in @cu_die.
  */
-int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
-                   const char **fname, int *lineno)
+int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr,
+                    const char **fname, int *lineno)
 {
        Dwarf_Line *line;
        Dwarf_Die die_mem;
        Dwarf_Addr faddr;
 
-       if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
+       if (die_find_realfunc(cu_die, addr, &die_mem)
            && die_entrypc(&die_mem, &faddr) == 0 &&
            faddr == addr) {
                *fname = dwarf_decl_file(&die_mem);
@@ -128,7 +128,7 @@ int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
                goto out;
        }
 
-       line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
+       line = cu_getsrc_die(cu_die, addr);
        if (line && dwarf_lineno(line, lineno) == 0) {
                *fname = dwarf_linesrc(line, NULL, NULL);
                if (!*fname)
index cb99646..7ee0fa1 100644 (file)
@@ -19,7 +19,7 @@ const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
 const char *cu_get_comp_dir(Dwarf_Die *cu_die);
 
 /* Get a line number and file name for given address */
-int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
+int cu_find_lineinfo(Dwarf_Die *cudie, Dwarf_Addr addr,
                     const char **fname, int *lineno);
 
 /* Walk on functions at given address */
index ebc5e9a..cec2e6c 100644 (file)
@@ -186,10 +186,12 @@ void perf_env__exit(struct perf_env *env)
        zfree(&env->cpuid);
        zfree(&env->cmdline);
        zfree(&env->cmdline_argv);
+       zfree(&env->sibling_dies);
        zfree(&env->sibling_cores);
        zfree(&env->sibling_threads);
        zfree(&env->pmu_mappings);
        zfree(&env->cpu);
+       zfree(&env->cpu_pmu_caps);
        zfree(&env->numa_map);
 
        for (i = 0; i < env->nr_numa_nodes; i++)
index 39062df..51424cd 100644 (file)
@@ -69,7 +69,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
 
                        if (ferror(infile)) {
                                pr_err("lzma: read error: %s\n", strerror(errno));
-                               goto err_fclose;
+                               goto err_lzma_end;
                        }
 
                        if (feof(infile))
@@ -83,7 +83,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
 
                        if (writen(output_fd, buf_out, write_size) != write_size) {
                                pr_err("lzma: write error: %s\n", strerror(errno));
-                               goto err_fclose;
+                               goto err_lzma_end;
                        }
 
                        strm.next_out  = buf_out;
@@ -95,11 +95,13 @@ int lzma_decompress_to_file(const char *input, int output_fd)
                                break;
 
                        pr_err("lzma: failed %s\n", lzma_strerror(ret));
-                       goto err_fclose;
+                       goto err_lzma_end;
                }
        }
 
        err = 0;
+err_lzma_end:
+       lzma_end(&strm);
 err_fclose:
        fclose(infile);
        return err;
index 8af693d..72e7f36 100644 (file)
@@ -192,6 +192,8 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
                        if (!(prot & PROT_EXEC))
                                dso__set_loaded(dso);
                }
+
+               nsinfo__put(dso->nsinfo);
                dso->nsinfo = nsi;
 
                if (build_id__is_defined(bid))
index dd9ed56..756295d 100644 (file)
@@ -99,7 +99,7 @@ int parse_libpfm_events_option(const struct option *opt, const char *str,
                        grp_leader = evsel;
 
                if (grp_evt > -1) {
-                       evsel->leader = grp_leader;
+                       evsel__set_leader(evsel, grp_leader);
                        grp_leader->core.nr_members++;
                        grp_evt++;
                }
index 44b90d6..a1bd700 100644 (file)
@@ -950,6 +950,13 @@ static struct perf_pmu *pmu_lookup(const char *name)
        LIST_HEAD(format);
        LIST_HEAD(aliases);
        __u32 type;
+       bool is_hybrid = perf_pmu__hybrid_mounted(name);
+
+       /*
+        * Check pmu name for hybrid and the pmu may be invalid in sysfs
+        */
+       if (!strncmp(name, "cpu_", 4) && !is_hybrid)
+               return NULL;
 
        /*
         * The pmu data we store & need consists of the pmu
@@ -978,7 +985,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
        pmu->is_uncore = pmu_is_uncore(name);
        if (pmu->is_uncore)
                pmu->id = pmu_id(name);
-       pmu->is_hybrid = perf_pmu__hybrid_mounted(name);
+       pmu->is_hybrid = is_hybrid;
        pmu->max_precise = pmu_max_precise(name);
        pmu_add_cpu_aliases(&aliases, pmu);
        pmu_add_sys_aliases(&aliases, pmu);
index c14e1d2..b2a02c9 100644 (file)
@@ -179,8 +179,10 @@ struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
                struct map *map;
 
                map = dso__new_map(target);
-               if (map && map->dso)
+               if (map && map->dso) {
+                       nsinfo__put(map->dso->nsinfo);
                        map->dso->nsinfo = nsinfo__get(nsi);
+               }
                return map;
        } else {
                return kernel_get_module_map(target);
@@ -237,8 +239,8 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
                clear_probe_trace_event(tevs + i);
 }
 
-static bool kprobe_blacklist__listed(unsigned long address);
-static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
+static bool kprobe_blacklist__listed(u64 address);
+static bool kprobe_warn_out_range(const char *symbol, u64 address)
 {
        struct map *map;
        bool ret = false;
@@ -398,8 +400,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
        pr_debug("Symbol %s address found : %" PRIx64 "\n",
                        pp->function, address);
 
-       ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
-                                         result);
+       ret = debuginfo__find_probe_point(dinfo, address, result);
        if (ret <= 0)
                ret = (!ret) ? -ENOENT : ret;
        else {
@@ -587,7 +588,7 @@ static void debuginfo_cache__exit(void)
 }
 
 
-static int get_text_start_address(const char *exec, unsigned long *address,
+static int get_text_start_address(const char *exec, u64 *address,
                                  struct nsinfo *nsi)
 {
        Elf *elf;
@@ -632,7 +633,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
                                            bool is_kprobe)
 {
        struct debuginfo *dinfo = NULL;
-       unsigned long stext = 0;
+       u64 stext = 0;
        u64 addr = tp->address;
        int ret = -ENOENT;
 
@@ -660,8 +661,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
 
        dinfo = debuginfo_cache__open(tp->module, verbose <= 0);
        if (dinfo)
-               ret = debuginfo__find_probe_point(dinfo,
-                                                (unsigned long)addr, pp);
+               ret = debuginfo__find_probe_point(dinfo, addr, pp);
        else
                ret = -ENOENT;
 
@@ -676,7 +676,7 @@ error:
 
 /* Adjust symbol name and address */
 static int post_process_probe_trace_point(struct probe_trace_point *tp,
-                                          struct map *map, unsigned long offs)
+                                          struct map *map, u64 offs)
 {
        struct symbol *sym;
        u64 addr = tp->address - offs;
@@ -719,7 +719,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
                                        int ntevs, const char *pathname)
 {
        struct map *map;
-       unsigned long stext = 0;
+       u64 stext = 0;
        int i, ret = 0;
 
        /* Prepare a map for offline binary */
@@ -745,7 +745,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
                                          struct nsinfo *nsi)
 {
        int i, ret = 0;
-       unsigned long stext = 0;
+       u64 stext = 0;
 
        if (!exec)
                return 0;
@@ -790,7 +790,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
        mod_name = find_module_name(module);
        for (i = 0; i < ntevs; i++) {
                ret = post_process_probe_trace_point(&tevs[i].point,
-                                               map, (unsigned long)text_offs);
+                                               map, text_offs);
                if (ret < 0)
                        break;
                tevs[i].point.module =
@@ -1534,7 +1534,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
                 * so tmp[1] should always valid (but could be '\0').
                 */
                if (tmp && !strncmp(tmp, "0x", 2)) {
-                       pp->abs_address = strtoul(pp->function, &tmp, 0);
+                       pp->abs_address = strtoull(pp->function, &tmp, 0);
                        if (*tmp != '\0') {
                                semantic_error("Invalid absolute address.\n");
                                return -EINVAL;
@@ -1909,7 +1909,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
                        argv[i] = NULL;
                        argc -= 1;
                } else
-                       tp->address = strtoul(fmt1_str, NULL, 0);
+                       tp->address = strtoull(fmt1_str, NULL, 0);
        } else {
                /* Only the symbol-based probe has offset */
                tp->symbol = strdup(fmt1_str);
@@ -2155,7 +2155,7 @@ synthesize_uprobe_trace_def(struct probe_trace_point *tp, struct strbuf *buf)
                return -EINVAL;
 
        /* Use the tp->address for uprobes */
-       err = strbuf_addf(buf, "%s:0x%lx", tp->module, tp->address);
+       err = strbuf_addf(buf, "%s:0x%" PRIx64, tp->module, tp->address);
 
        if (err >= 0 && tp->ref_ctr_offset) {
                if (!uprobe_ref_ctr_is_supported())
@@ -2170,7 +2170,7 @@ synthesize_kprobe_trace_def(struct probe_trace_point *tp, struct strbuf *buf)
 {
        if (!strncmp(tp->symbol, "0x", 2)) {
                /* Absolute address. See try_to_find_absolute_address() */
-               return strbuf_addf(buf, "%s%s0x%lx", tp->module ?: "",
+               return strbuf_addf(buf, "%s%s0x%" PRIx64, tp->module ?: "",
                                  tp->module ? ":" : "", tp->address);
        } else {
                return strbuf_addf(buf, "%s%s%s+%lu", tp->module ?: "",
@@ -2269,7 +2269,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
                pp->function = strdup(tp->symbol);
                pp->offset = tp->offset;
        } else {
-               ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
+               ret = e_snprintf(buf, 128, "0x%" PRIx64, tp->address);
                if (ret < 0)
                        return ret;
                pp->function = strdup(buf);
@@ -2450,8 +2450,8 @@ void clear_probe_trace_event(struct probe_trace_event *tev)
 
 struct kprobe_blacklist_node {
        struct list_head list;
-       unsigned long start;
-       unsigned long end;
+       u64 start;
+       u64 end;
        char *symbol;
 };
 
@@ -2496,7 +2496,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
                }
                INIT_LIST_HEAD(&node->list);
                list_add_tail(&node->list, blacklist);
-               if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
+               if (sscanf(buf, "0x%" PRIx64 "-0x%" PRIx64, &node->start, &node->end) != 2) {
                        ret = -EINVAL;
                        break;
                }
@@ -2512,7 +2512,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
                        ret = -ENOMEM;
                        break;
                }
-               pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
+               pr_debug2("Blacklist: 0x%" PRIx64 "-0x%" PRIx64 ", %s\n",
                          node->start, node->end, node->symbol);
                ret++;
        }
@@ -2524,8 +2524,7 @@ static int kprobe_blacklist__load(struct list_head *blacklist)
 }
 
 static struct kprobe_blacklist_node *
-kprobe_blacklist__find_by_address(struct list_head *blacklist,
-                                 unsigned long address)
+kprobe_blacklist__find_by_address(struct list_head *blacklist, u64 address)
 {
        struct kprobe_blacklist_node *node;
 
@@ -2553,7 +2552,7 @@ static void kprobe_blacklist__release(void)
        kprobe_blacklist__delete(&kprobe_blacklist);
 }
 
-static bool kprobe_blacklist__listed(unsigned long address)
+static bool kprobe_blacklist__listed(u64 address)
 {
        return !!kprobe_blacklist__find_by_address(&kprobe_blacklist, address);
 }
@@ -3221,7 +3220,7 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
         * In __add_probe_trace_events, a NULL symbol is interpreted as
         * invalid.
         */
-       if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
+       if (asprintf(&tp->symbol, "0x%" PRIx64, tp->address) < 0)
                goto errout;
 
        /* For kprobe, check range */
@@ -3232,7 +3231,7 @@ static int try_to_find_absolute_address(struct perf_probe_event *pev,
                goto errout;
        }
 
-       if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
+       if (asprintf(&tp->realname, "abs_%" PRIx64, tp->address) < 0)
                goto errout;
 
        if (pev->target) {
index 65769d7..8ad5b15 100644 (file)
@@ -33,7 +33,7 @@ struct probe_trace_point {
        char            *module;        /* Module name */
        unsigned long   offset;         /* Offset from symbol */
        unsigned long   ref_ctr_offset; /* SDT reference counter offset */
-       unsigned long   address;        /* Actual address of the trace point */
+       u64             address;        /* Actual address of the trace point */
        bool            retprobe;       /* Return probe flag */
 };
 
@@ -70,7 +70,7 @@ struct perf_probe_point {
        bool            retprobe;       /* Return probe flag */
        char            *lazy_line;     /* Lazy matching pattern */
        unsigned long   offset;         /* Offset from function entry */
-       unsigned long   abs_address;    /* Absolute address of the point */
+       u64             abs_address;    /* Absolute address of the point */
 };
 
 /* Perf probe probing argument field chain */
index f9a6cbc..3d50de3 100644 (file)
@@ -377,11 +377,11 @@ int probe_file__del_events(int fd, struct strfilter *filter)
 
        ret = probe_file__get_events(fd, filter, namelist);
        if (ret < 0)
-               return ret;
+               goto out;
 
        ret = probe_file__del_strlist(fd, namelist);
+out:
        strlist__delete(namelist);
-
        return ret;
 }
 
index 02ef0d7..50d861a 100644 (file)
@@ -668,7 +668,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
        }
 
        tp->offset = (unsigned long)(paddr - eaddr);
-       tp->address = (unsigned long)paddr;
+       tp->address = paddr;
        tp->symbol = strdup(symbol);
        if (!tp->symbol)
                return -ENOMEM;
@@ -1707,7 +1707,7 @@ int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
 }
 
 /* Reverse search */
-int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
+int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
                                struct perf_probe_point *ppt)
 {
        Dwarf_Die cudie, spdie, indie;
@@ -1720,14 +1720,14 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
                addr += baseaddr;
        /* Find cu die */
        if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
-               pr_warning("Failed to find debug information for address %lx\n",
+               pr_warning("Failed to find debug information for address %" PRIx64 "\n",
                           addr);
                ret = -EINVAL;
                goto end;
        }
 
        /* Find a corresponding line (filename and lineno) */
-       cu_find_lineinfo(&cudie, addr, &fname, &lineno);
+       cu_find_lineinfo(&cudie, (Dwarf_Addr)addr, &fname, &lineno);
        /* Don't care whether it failed or not */
 
        /* Find a corresponding function (name, baseline and baseaddr) */
@@ -1742,7 +1742,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
                }
 
                fname = dwarf_decl_file(&spdie);
-               if (addr == (unsigned long)baseaddr) {
+               if (addr == baseaddr) {
                        /* Function entry - Relative line number is 0 */
                        lineno = baseline;
                        goto post;
@@ -1788,7 +1788,7 @@ post:
        if (lineno)
                ppt->line = lineno - baseline;
        else if (basefunc) {
-               ppt->offset = addr - (unsigned long)baseaddr;
+               ppt->offset = addr - baseaddr;
                func = basefunc;
        }
 
@@ -1828,8 +1828,7 @@ static int line_range_add_line(const char *src, unsigned int lineno,
 }
 
 static int line_range_walk_cb(const char *fname, int lineno,
-                             Dwarf_Addr addr __maybe_unused,
-                             void *data)
+                             Dwarf_Addr addr, void *data)
 {
        struct line_finder *lf = data;
        const char *__fname;
index 2febb58..8bc1c80 100644 (file)
@@ -46,7 +46,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
                                 struct probe_trace_event **tevs);
 
 /* Find a perf_probe_point from debuginfo */
-int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
+int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
                                struct perf_probe_point *ppt);
 
 int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
index e9c929a..51f7274 100644 (file)
@@ -306,6 +306,7 @@ void perf_session__delete(struct perf_session *session)
                        evlist__delete(session->evlist);
                perf_data__close(session->data);
        }
+       trace_event__cleanup(&session->tevent);
        free(session);
 }
 
index 88ce47f..568a88c 100644 (file)
@@ -3370,7 +3370,7 @@ static void add_hpp_sort_string(struct strbuf *sb, struct hpp_dimension *s, int
                add_key(sb, s[i].name, llen);
 }
 
-const char *sort_help(const char *prefix)
+char *sort_help(const char *prefix)
 {
        struct strbuf sb;
        char *s;
index 87a0926..b67c469 100644 (file)
@@ -302,7 +302,7 @@ void reset_output_field(void);
 void sort__setup_elide(FILE *fp);
 void perf_hpp__set_elide(int idx, bool elide);
 
-const char *sort_help(const char *prefix);
+char *sort_help(const char *prefix);
 
 int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
 
index 83a2bc0..5886010 100644 (file)
@@ -596,6 +596,18 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c
        }
 }
 
+static bool is_uncore(struct evsel *evsel)
+{
+       struct perf_pmu *pmu = evsel__find_pmu(evsel);
+
+       return pmu && pmu->is_uncore;
+}
+
+static bool hybrid_uniquify(struct evsel *evsel)
+{
+       return perf_pmu__has_hybrid() && !is_uncore(evsel);
+}
+
 static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
                            void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
                                       bool first),
@@ -604,7 +616,7 @@ static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
        if (counter->merged_stat)
                return false;
        cb(config, counter, data, true);
-       if (config->no_merge)
+       if (config->no_merge || hybrid_uniquify(counter))
                uniquify_event_name(counter);
        else if (counter->auto_merge_stats)
                collect_all_aliases(config, counter, cb, data);