Commit cc612d81 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

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: default avatarArnaldo 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: default avatarIngo Molnar <mingo@elte.hu>
parent 1b290d67
...@@ -37,6 +37,7 @@ static bool use_modules; ...@@ -37,6 +37,7 @@ static bool use_modules;
static unsigned long page_size; static unsigned long page_size;
static unsigned long mmap_window = 32; static unsigned long mmap_window = 32;
const char *vmlinux_name;
struct sym_hist { struct sym_hist {
u64 sum; u64 sum;
...@@ -637,7 +638,7 @@ static int __cmd_annotate(void) ...@@ -637,7 +638,7 @@ static int __cmd_annotate(void)
exit(0); exit(0);
} }
if (kernel_maps__init(use_modules) < 0) { if (kernel_maps__init(vmlinux_name, true, use_modules) < 0) {
pr_err("failed to create kernel maps for symbol resolution\b"); pr_err("failed to create kernel maps for symbol resolution\b");
return -1; return -1;
} }
......
...@@ -291,7 +291,7 @@ static int read_events(void) ...@@ -291,7 +291,7 @@ static int read_events(void)
register_idle_thread(); register_idle_thread();
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, 0, 0, return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0,
&cwdlen, &cwd); &cwdlen, &cwd);
} }
......
...@@ -52,6 +52,7 @@ static char *pretty_printing_style = default_pretty_printing_style; ...@@ -52,6 +52,7 @@ static char *pretty_printing_style = default_pretty_printing_style;
static int exclude_other = 1; static int exclude_other = 1;
static char callchain_default_opt[] = "fractal,0.5"; static char callchain_default_opt[] = "fractal,0.5";
const char *vmlinux_name;
static char *cwd; static char *cwd;
static int cwdlen; static int cwdlen;
...@@ -925,8 +926,9 @@ static int __cmd_report(void) ...@@ -925,8 +926,9 @@ static int __cmd_report(void)
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths, ret = mmap_dispatch_perf_file(&header, input_name, vmlinux_name,
&cwdlen, &cwd); !vmlinux_name, force,
full_paths, &cwdlen, &cwd);
if (ret) if (ret)
return ret; return ret;
......
...@@ -1718,7 +1718,8 @@ static int read_events(void) ...@@ -1718,7 +1718,8 @@ static int read_events(void)
register_idle_thread(); register_idle_thread();
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd); return mmap_dispatch_perf_file(&header, input_name, NULL, false, 0, 0,
&cwdlen, &cwd);
} }
static void print_bad_events(void) static void print_bad_events(void)
......
...@@ -79,6 +79,7 @@ static int dump_symtab = 0; ...@@ -79,6 +79,7 @@ static int dump_symtab = 0;
static bool hide_kernel_symbols = false; static bool hide_kernel_symbols = false;
static bool hide_user_symbols = false; static bool hide_user_symbols = false;
static struct winsize winsize; static struct winsize winsize;
const char *vmlinux_name;
static const char *graph_line = static const char *graph_line =
"_____________________________________________________________________" "_____________________________________________________________________"
"_____________________________________________________________________"; "_____________________________________________________________________";
...@@ -1341,7 +1342,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) ...@@ -1341,7 +1342,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
if (delay_secs < 1) if (delay_secs < 1)
delay_secs = 1; delay_secs = 1;
err = kernel_maps__init(true); err = kernel_maps__init(vmlinux_name, !vmlinux_name, true);
if (err < 0) if (err < 0)
return err; return err;
parse_source(sym_filter_entry); parse_source(sym_filter_entry);
......
...@@ -131,7 +131,8 @@ static int __cmd_trace(void) ...@@ -131,7 +131,8 @@ static int __cmd_trace(void)
register_idle_thread(); register_idle_thread();
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd); return mmap_dispatch_perf_file(&header, input_name, NULL, false,
0, 0, &cwdlen, &cwd);
} }
static const char * const annotate_usage[] = { static const char * const annotate_usage[] = {
......
...@@ -101,6 +101,8 @@ int perf_header__read_build_ids(int input, off_t offset, off_t size) ...@@ -101,6 +101,8 @@ int perf_header__read_build_ids(int input, off_t offset, off_t size)
int mmap_dispatch_perf_file(struct perf_header **pheader, int mmap_dispatch_perf_file(struct perf_header **pheader,
const char *input_name, const char *input_name,
const char *vmlinux_name,
bool try_vmlinux_path,
int force, int force,
int full_paths, int full_paths,
int *cwdlen, int *cwdlen,
...@@ -171,7 +173,7 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, ...@@ -171,7 +173,7 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
goto out_delete; goto out_delete;
err = -ENOMEM; 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"); pr_err("failed to setup the kernel maps to resolve symbols\n");
goto out_delete; goto out_delete;
} }
......
...@@ -23,6 +23,8 @@ struct perf_file_handler { ...@@ -23,6 +23,8 @@ struct perf_file_handler {
void register_perf_file_handler(struct perf_file_handler *handler); void register_perf_file_handler(struct perf_file_handler *handler);
int mmap_dispatch_perf_file(struct perf_header **pheader, int mmap_dispatch_perf_file(struct perf_header **pheader,
const char *input_name, const char *input_name,
const char *vmlinux_name,
bool try_vmlinux_path,
int force, int force,
int full_paths, int full_paths,
int *cwdlen, int *cwdlen,
......
...@@ -257,7 +257,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) ...@@ -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 * Read the kernel buildid nad the list of loaded modules with
* its build_ids: * its build_ids:
*/ */
kernel_maps__init(true); kernel_maps__init(NULL, false, true);
/* Write build-ids */ /* Write build-ids */
buildid_sec->offset = lseek(fd, 0, SEEK_CUR); buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
......
...@@ -34,6 +34,8 @@ static void kernel_maps__insert(struct map *map); ...@@ -34,6 +34,8 @@ static void kernel_maps__insert(struct map *map);
static int dso__load_kernel_sym(struct dso *self, struct map *map, static int dso__load_kernel_sym(struct dso *self, struct map *map,
symbol_filter_t filter); symbol_filter_t filter);
unsigned int symbol__priv_size; unsigned int symbol__priv_size;
static int vmlinux_path__nr_entries;
static char **vmlinux_path;
static struct rb_root kernel_maps; static struct rb_root kernel_maps;
...@@ -1386,15 +1388,43 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, ...@@ -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, static int dso__load_kernel_sym(struct dso *self, struct map *map,
symbol_filter_t filter) 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) { 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); err = kernel_maps__load_kallsyms(filter);
if (err > 0) if (err > 0 && !is_kallsyms)
dso__set_long_name(self, strdup("[kernel.kallsyms]")); dso__set_long_name(self, strdup("[kernel.kallsyms]"));
} }
if (err > 0) { if (err > 0) {
out_fixup:
map__fixup_start(map); map__fixup_start(map);
map__fixup_end(map); map__fixup_end(map);
} }
...@@ -1405,8 +1435,6 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, ...@@ -1405,8 +1435,6 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
LIST_HEAD(dsos); LIST_HEAD(dsos);
struct dso *vdso; struct dso *vdso;
const char *vmlinux_name = "vmlinux";
static void dsos__add(struct dso *dso) static void dsos__add(struct dso *dso)
{ {
list_add_tail(&dso->node, &dsos); list_add_tail(&dso->node, &dsos);
...@@ -1457,9 +1485,9 @@ size_t dsos__fprintf_buildid(FILE *fp) ...@@ -1457,9 +1485,9 @@ size_t dsos__fprintf_buildid(FILE *fp)
return ret; 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) if (kernel == NULL)
return -1; return -1;
...@@ -1469,9 +1497,9 @@ static int kernel_maps__create_kernel_map(void) ...@@ -1469,9 +1497,9 @@ static int kernel_maps__create_kernel_map(void)
goto out_delete_kernel_dso; 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->short_name = "[kernel]";
kernel->kernel = 1; kernel->kernel = 1;
vdso = dso__new("[vdso]"); vdso = dso__new("[vdso]");
if (vdso == NULL) if (vdso == NULL)
goto out_delete_kernel_map; goto out_delete_kernel_map;
...@@ -1494,10 +1522,71 @@ static int kernel_maps__create_kernel_map(void) ...@@ -1494,10 +1522,71 @@ static int kernel_maps__create_kernel_map(void)
return -1; 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)
{ {
if (kernel_maps__create_kernel_map() < 0) 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; return -1;
}
if (use_modules && kernel_maps__create_module_maps() < 0) if (use_modules && kernel_maps__create_module_maps() < 0)
pr_debug("Failed to load list of modules in use, " pr_debug("Failed to load list of modules in use, "
......
...@@ -93,7 +93,8 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size); ...@@ -93,7 +93,8 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
bool dsos__read_build_ids(void); bool dsos__read_build_ids(void);
int build_id__sprintf(u8 *self, int len, char *bf); 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); size_t kernel_maps__fprintf(FILE *fp);
void symbol__init(unsigned int priv_size); void symbol__init(unsigned int priv_size);
...@@ -101,5 +102,4 @@ 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 list_head dsos;
extern struct map *kernel_map; extern struct map *kernel_map;
extern struct dso *vdso; extern struct dso *vdso;
extern const char *vmlinux_name;
#endif /* __PERF_SYMBOL */ #endif /* __PERF_SYMBOL */
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