perf tools: Check recorded kernel version when finding vmlinux
authorNamhyung Kim <namhyung@kernel.org>
Tue, 12 Aug 2014 06:40:45 +0000 (15:40 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 13 Aug 2014 19:42:21 +0000 (16:42 -0300)
Currently vmlinux_path__init() only tries to find vmlinux file from
current directory, /boot and some canonical directories with version
number of the running kernel.  This can be a problem when reporting old
data recorded on a kernel version not running currently.

We can use --symfs option for this but it's annoying for user to do it
always.  As we already have the info in the perf.data file, it can be
changed to use it for the search automatically.

Before:

  $ perf report
  ...
  # Samples: 4K of event 'cpu-clock'
  # Event count (approx.): 1067250000
  #
  # Overhead  Command     Shared Object      Symbol
  # ........  ..........  .................  ..............................
      71.87%     swapper  [kernel.kallsyms]  [k] recover_probed_instruction

After:

  # Overhead  Command     Shared Object      Symbol
  # ........  ..........  .................  ....................
      71.87%     swapper  [kernel.kallsyms]  [k] native_safe_halt

This requires to change signature of symbol__init() to receive struct
perf_session_env *.

Reported-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1407825645-24586-14-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
19 files changed:
tools/perf/builtin-annotate.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-lock.c
tools/perf/builtin-mem.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/tests/builtin-test.c
tools/perf/util/probe-event.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index c0464dc380576625ee50cf5c98bd82cfc8c790c7..d4da6929597fa5fa5cafd049c74cffb2fd77ba5c 100644 (file)
@@ -345,7 +345,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
        symbol_conf.priv_size = sizeof(struct annotation);
        symbol_conf.try_vmlinux_path = true;
 
-       ret = symbol__init();
+       ret = symbol__init(&annotate.session->header.env);
        if (ret < 0)
                goto out_delete;
 
index d91bfa6632e8a1ee96986a9a4b180c0190039d36..ac5838e0b1bdc01e1481ba7ff11c5e454c7a96ad 100644 (file)
@@ -329,7 +329,7 @@ int cmd_buildid_cache(int argc, const char **argv,
                        return -1;
        }
 
-       if (symbol__init() < 0)
+       if (symbol__init(session ? &session->header.env : NULL) < 0)
                goto out;
 
        setup_pager();
index c10cc44bae19dd3af8cd043ee0745e81d1d57abe..190d0b6b28cce61c364919adcc9c41fa8899ec40 100644 (file)
@@ -1143,7 +1143,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 
        argc = parse_options(argc, argv, options, diff_usage, 0);
 
-       if (symbol__init() < 0)
+       if (symbol__init(NULL) < 0)
                return -1;
 
        if (data_init(argc, argv) < 0)
index 18eaefd3cd0c431a1970b8e31335cc73487e7ff8..3a62b6b3c8fdcc2dd308791dc14d5bd18a6ed087 100644 (file)
@@ -462,7 +462,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
        if (inject.session == NULL)
                return -ENOMEM;
 
-       if (symbol__init() < 0)
+       if (symbol__init(&inject.session->header.env) < 0)
                return -1;
 
        ret = __cmd_inject(&inject);
index 349d9b46098ec6b45633e86a56214d64f71de31e..23762187a2191dc98bf68a35b2103d73df0aea78 100644 (file)
@@ -692,7 +692,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
                usage_with_options(kmem_usage, kmem_options);
 
        if (!strncmp(argv[0], "rec", 3)) {
-               symbol__init();
+               symbol__init(NULL);
                return __cmd_record(argc, argv);
        }
 
@@ -700,7 +700,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
        if (session == NULL)
                return -ENOMEM;
 
-       symbol__init();
+       symbol__init(&session->header.env);
 
        if (!strcmp(argv[0], "stat")) {
                if (cpu__setup_cpunode_map())
index 7f2b5551386396d9963df091cd0ff1fdee17f020..14d03edc81c2b242e80283129ff085ee45fa84c0 100644 (file)
@@ -1064,7 +1064,7 @@ static int read_events(struct perf_kvm_stat *kvm)
                return -EINVAL;
        }
 
-       symbol__init();
+       symbol__init(&kvm->session->header.env);
 
        if (!perf_session__has_traces(kvm->session, "kvm record"))
                return -EINVAL;
@@ -1314,7 +1314,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
        kvm->opts.target.uid_str = NULL;
        kvm->opts.target.uid = UINT_MAX;
 
-       symbol__init();
+       symbol__init(NULL);
        disable_buildid_cache();
 
        use_browser = 0;
index d73580b399084248dae43c3a30c64b1456710990..92790ed7af45d4376e2d95c10e515601bdbb70e1 100644 (file)
@@ -865,7 +865,7 @@ static int __cmd_report(bool display_info)
                return -ENOMEM;
        }
 
-       symbol__init();
+       symbol__init(&session->header.env);
 
        if (!perf_session__has_traces(session, "lock record"))
                goto out_delete;
index 80e57c84adefdaec2e6356d20abf46ad44982fa9..8b4a87fe3858367235168e27ab2601f3788ece11 100644 (file)
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem)
                        goto out_delete;
        }
 
-       if (symbol__init() < 0)
+       if (symbol__init(&session->header.env) < 0)
                return -1;
 
        printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
index ca0251e8470d0d12a01e32f6b3e6a1253c47393c..4db670d4b8da56421e548cd97668e4ed9d3fbb2d 100644 (file)
@@ -908,7 +908,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
                usage_with_options(record_usage, record_options);
        }
 
-       symbol__init();
+       symbol__init(NULL);
 
        if (symbol_conf.kptr_restrict)
                pr_warning(
index 041e93da13e453dfb0c377d6fe46f34ed3345d34..b9e0fcac4d71ed1266107eeba3754635d4e0e4f7 100644 (file)
@@ -798,7 +798,7 @@ repeat:
                }
        }
 
-       if (symbol__init() < 0)
+       if (symbol__init(&session->header.env) < 0)
                goto error;
 
        if (argc) {
index dcd9ebf5a7dfbd17d0a51a6ab99b1bb39c0439ab..f5874a27b34658dbd026c5f94d5e353c63722937 100644 (file)
@@ -1462,7 +1462,7 @@ static int perf_sched__read_events(struct perf_sched *sched,
                return -1;
        }
 
-       symbol__init();
+       symbol__init(&session->header.env);
 
        if (perf_session__set_tracepoints_handlers(session, handlers))
                goto out_delete;
index 9ca7a2d03f1781859671b9af4d0d898cac3789e9..37d2b608d3887e292bff19b91b7ea840dd4133c8 100644 (file)
@@ -1732,7 +1732,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        goto out_delete;
        }
 
-       if (symbol__init() < 0)
+       if (symbol__init(&session->header.env) < 0)
                goto out_delete;
 
        script.session = session;
index df3b1c5ae7b987c47fa3a830a61ce7a7dfab583b..48eea6cd2f5be475088e0c55d053ab4bd4e66246 100644 (file)
@@ -1607,7 +1607,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
        if (session == NULL)
                return -ENOMEM;
 
-       symbol__init();
+       symbol__init(&session->header.env);
 
        (void)perf_header__process_sections(&session->header,
                                            perf_data_file__fd(session->file),
index 0ab3ea7f75254c225ab93c22804857d8a57d3783..4b0e15c2b2a835d0930c5ac7e739300cb8006cc3 100644 (file)
@@ -1234,7 +1234,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        symbol_conf.priv_size = sizeof(struct annotation);
 
        symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
-       if (symbol__init() < 0)
+       if (symbol__init(NULL) < 0)
                return -1;
 
        sort__setup_elide(stdout);
index 8a83bd83532752f494ae608ae22f2234f5ea000f..d080b9cf0354fa2b20bd13aadccaf12480cebd77 100644 (file)
@@ -1411,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool,
 
 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
 {
-       int err = symbol__init();
+       int err = symbol__init(NULL);
 
        if (err)
                return err;
@@ -2245,7 +2245,7 @@ static int trace__replay(struct trace *trace)
        if (session == NULL)
                return -ENOMEM;
 
-       if (symbol__init() < 0)
+       if (symbol__init(&session->header.env) < 0)
                goto out;
 
        trace->host = &session->machines.host;
index 6f8b01bc60330c71722e4d22a7d40b83c32fac25..c6796d22423a69b5e231b911aca8d4d46b3e13c9 100644 (file)
@@ -297,7 +297,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
        symbol_conf.sort_by_name = true;
        symbol_conf.try_vmlinux_path = true;
 
-       if (symbol__init() < 0)
+       if (symbol__init(NULL) < 0)
                return -1;
 
        if (skip != NULL)
index 443225cb62f78ddc03c31bcfec6ff03e3ad09570..784ea42ad8cbd7f099e4e680c7a02b4b0c5c4053 100644 (file)
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
        int ret;
 
        symbol_conf.sort_by_name = true;
-       ret = symbol__init();
+       ret = symbol__init(NULL);
        if (ret < 0) {
                pr_debug("Failed to init symbol map.\n");
                goto out;
index 009a9d064f11d80ca665b6b8734a3065323ad5ec..ac098a3c2a318b0b2b61ea2be31ff32e7d15f216 100644 (file)
@@ -15,6 +15,7 @@
 #include "machine.h"
 #include "symbol.h"
 #include "strlist.h"
+#include "header.h"
 
 #include <elf.h>
 #include <limits.h>
@@ -1749,10 +1750,11 @@ static void vmlinux_path__exit(void)
        zfree(&vmlinux_path);
 }
 
-static int vmlinux_path__init(void)
+static int vmlinux_path__init(struct perf_session_env *env)
 {
        struct utsname uts;
        char bf[PATH_MAX];
+       char *kernel_version;
 
        vmlinux_path = malloc(sizeof(char *) * 5);
        if (vmlinux_path == NULL)
@@ -1767,25 +1769,31 @@ static int vmlinux_path__init(void)
                goto out_fail;
        ++vmlinux_path__nr_entries;
 
-       /* only try running kernel version if no symfs was given */
+       /* only try kernel version if no symfs was given */
        if (symbol_conf.symfs[0] != 0)
                return 0;
 
-       if (uname(&uts) < 0)
-               goto out_fail;
+       if (env) {
+               kernel_version = env->os_release;
+       } else {
+               if (uname(&uts) < 0)
+                       goto out_fail;
+
+               kernel_version = uts.release;
+       }
 
-       snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
+       snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
        vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
        if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
                goto out_fail;
        ++vmlinux_path__nr_entries;
-       snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
+       snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
        vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
        if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
                goto out_fail;
        ++vmlinux_path__nr_entries;
        snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
-                uts.release);
+                kernel_version);
        vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
        if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
                goto out_fail;
@@ -1831,7 +1839,7 @@ static bool symbol__read_kptr_restrict(void)
        return value;
 }
 
-int symbol__init(void)
+int symbol__init(struct perf_session_env *env)
 {
        const char *symfs;
 
@@ -1846,7 +1854,7 @@ int symbol__init(void)
                symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
                                          sizeof(struct symbol));
 
-       if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
+       if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
                return -1;
 
        if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
index 196b29104276c92964d0198e4e86e9e47c0ae586..b95e3a36d6544da912e57d04b9a5b9e19a0116f9 100644 (file)
@@ -262,7 +262,8 @@ int modules__parse(const char *filename, void *arg,
 int filename__read_debuglink(const char *filename, char *debuglink,
                             size_t size);
 
-int symbol__init(void);
+struct perf_session_env;
+int symbol__init(struct perf_session_env *env);
 void symbol__exit(void);
 void symbol__elf_init(void);
 struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);