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>
This commit is contained in:
Arnaldo Carvalho de Melo
2009-11-23 16:39:10 -02:00
committed by Ingo Molnar
parent 1b290d670f
commit cc612d8199
11 changed files with 122 additions and 23 deletions

View File

@ -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)
{
if (kernel_maps__create_kernel_map() < 0)
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 (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");