summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-23 16:39:10 -0200
committerIngo Molnar <mingo@elte.hu>2009-11-23 19:51:48 +0100
commitcc612d8199089413719397c9d92e5823da578eac (patch)
treeaec84294a839bc82b738326ed5f338e6ebc47a30 /tools/perf/util
parent1b290d670ffa883b7e062177463a8efd00eaa2c1 (diff)
perf symbols: Look for vmlinux in more places
Now that we can check the buildid to see if it really matches, this can be done safely: vmlinux /boot/vmlinux /boot/vmlinux-<uts.release> /lib/modules/<uts.release>/build/vmlinux /usr/lib/debug/lib/modules/%s/vmlinux More can be added - if you know about distros that put the vmlinux somewhere else please let us know. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1259001550-8194-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/data_map.c4
-rw-r--r--tools/perf/util/data_map.h2
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/symbol.c113
-rw-r--r--tools/perf/util/symbol.h4
5 files changed, 109 insertions, 16 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index e7b6c2bea3de..f318d19b2562 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -101,6 +101,8 @@ out:
int mmap_dispatch_perf_file(struct perf_header **pheader,
const char *input_name,
+ const char *vmlinux_name,
+ bool try_vmlinux_path,
int force,
int full_paths,
int *cwdlen,
@@ -171,7 +173,7 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
goto out_delete;
err = -ENOMEM;
- if (kernel_maps__init(true) < 0) {
+ if (kernel_maps__init(vmlinux_name, try_vmlinux_path, true) < 0) {
pr_err("failed to setup the kernel maps to resolve symbols\n");
goto out_delete;
}
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index ae036ecd7625..3f0d21b3819e 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -23,6 +23,8 @@ struct perf_file_handler {
void register_perf_file_handler(struct perf_file_handler *handler);
int mmap_dispatch_perf_file(struct perf_header **pheader,
const char *input_name,
+ const char *vmlinux_name,
+ bool try_vmlinux_path,
int force,
int full_paths,
int *cwdlen,
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ac3410b8e9e3..1332f8ec04aa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -257,7 +257,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
* Read the kernel buildid nad the list of loaded modules with
* its build_ids:
*/
- kernel_maps__init(true);
+ kernel_maps__init(NULL, false, true);
/* Write build-ids */
buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 74b5b8a16951..44d81d5ae8cf 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -34,6 +34,8 @@ static void kernel_maps__insert(struct map *map);
static int dso__load_kernel_sym(struct dso *self, struct map *map,
symbol_filter_t filter);
unsigned int symbol__priv_size;
+static int vmlinux_path__nr_entries;
+static char **vmlinux_path;
static struct rb_root kernel_maps;
@@ -1386,15 +1388,43 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
static int dso__load_kernel_sym(struct dso *self, struct map *map,
symbol_filter_t filter)
{
- int err = dso__load_vmlinux(self, map, self->name, filter);
+ int err;
+ bool is_kallsyms;
+
+ if (vmlinux_path != NULL) {
+ int i;
+ pr_debug("Looking at the vmlinux_path (%d entries long)\n",
+ vmlinux_path__nr_entries);
+ for (i = 0; i < vmlinux_path__nr_entries; ++i) {
+ err = dso__load_vmlinux(self, map, vmlinux_path[i],
+ filter);
+ if (err > 0) {
+ pr_debug("Using %s for symbols\n",
+ vmlinux_path[i]);
+ dso__set_long_name(self,
+ strdup(vmlinux_path[i]));
+ goto out_fixup;
+ }
+ }
+ }
+
+ is_kallsyms = self->long_name[0] == '[';
+ if (is_kallsyms)
+ goto do_kallsyms;
+ err = dso__load_vmlinux(self, map, self->long_name, filter);
if (err <= 0) {
+ pr_info("The file %s cannot be used, "
+ "trying to use /proc/kallsyms...", self->long_name);
+ sleep(2);
+do_kallsyms:
err = kernel_maps__load_kallsyms(filter);
- if (err > 0)
+ if (err > 0 && !is_kallsyms)
dso__set_long_name(self, strdup("[kernel.kallsyms]"));
}
if (err > 0) {
+out_fixup:
map__fixup_start(map);
map__fixup_end(map);
}
@@ -1403,9 +1433,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
}
LIST_HEAD(dsos);
-struct dso *vdso;
-
-const char *vmlinux_name = "vmlinux";
+struct dso *vdso;
static void dsos__add(struct dso *dso)
{
@@ -1457,9 +1485,9 @@ size_t dsos__fprintf_buildid(FILE *fp)
return ret;
}
-static int kernel_maps__create_kernel_map(void)
+static int kernel_maps__create_kernel_map(const char *vmlinux_name)
{
- struct dso *kernel = dso__new(vmlinux_name);
+ struct dso *kernel = dso__new(vmlinux_name ?: "[kernel.kallsyms]");
if (kernel == NULL)
return -1;
@@ -1468,10 +1496,10 @@ static int kernel_maps__create_kernel_map(void)
if (kernel_map == NULL)
goto out_delete_kernel_dso;
- kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
+ kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
+ kernel->short_name = "[kernel]";
+ kernel->kernel = 1;
- kernel->short_name = "[kernel]";
- kernel->kernel = 1;
vdso = dso__new("[vdso]");
if (vdso == NULL)
goto out_delete_kernel_map;
@@ -1494,11 +1522,72 @@ out_delete_kernel_dso:
return -1;
}
-int kernel_maps__init(bool use_modules)
+static void vmlinux_path__exit(void)
+{
+ while (--vmlinux_path__nr_entries >= 0) {
+ free(vmlinux_path[vmlinux_path__nr_entries]);
+ vmlinux_path[vmlinux_path__nr_entries] = NULL;
+ }
+
+ free(vmlinux_path);
+ vmlinux_path = NULL;
+}
+
+static int vmlinux_path__init(void)
+{
+ struct utsname uts;
+ char bf[PATH_MAX];
+
+ if (uname(&uts) < 0)
+ return -1;
+
+ vmlinux_path = malloc(sizeof(char *) * 5);
+ if (vmlinux_path == NULL)
+ return -1;
+
+ vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
+ if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
+ goto out_fail;
+ ++vmlinux_path__nr_entries;
+ vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
+ if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
+ goto out_fail;
+ ++vmlinux_path__nr_entries;
+ snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
+ 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);
+ 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);
+ vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
+ if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
+ goto out_fail;
+ ++vmlinux_path__nr_entries;
+
+ return 0;
+
+out_fail:
+ vmlinux_path__exit();
+ return -1;
+}
+
+int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path,
+ bool use_modules)
{
- if (kernel_maps__create_kernel_map() < 0)
+ if (try_vmlinux_path && vmlinux_path__init() < 0)
return -1;
+ if (kernel_maps__create_kernel_map(vmlinux_name) < 0) {
+ vmlinux_path__exit();
+ return -1;
+ }
+
if (use_modules && kernel_maps__create_module_maps() < 0)
pr_debug("Failed to load list of modules in use, "
"continuing...\n");
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 7a129047c47d..8c4d026e067a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -93,7 +93,8 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
bool dsos__read_build_ids(void);
int build_id__sprintf(u8 *self, int len, char *bf);
-int kernel_maps__init(bool use_modules);
+int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path,
+ bool use_modules);
size_t kernel_maps__fprintf(FILE *fp);
void symbol__init(unsigned int priv_size);
@@ -101,5 +102,4 @@ void symbol__init(unsigned int priv_size);
extern struct list_head dsos;
extern struct map *kernel_map;
extern struct dso *vdso;
-extern const char *vmlinux_name;
#endif /* __PERF_SYMBOL */