Skip to content

Commit

Permalink
perf symbols: Look for vmlinux in more places
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arnaldo Carvalho de Melo authored and Ingo Molnar committed Nov 23, 2009
1 parent 1b290d6 commit cc612d8
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 23 deletions.
3 changes: 2 additions & 1 deletion tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static bool use_modules;

static unsigned long page_size;
static unsigned long mmap_window = 32;
const char *vmlinux_name;

struct sym_hist {
u64 sum;
Expand Down Expand Up @@ -637,7 +638,7 @@ static int __cmd_annotate(void)
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");
return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-kmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ static int read_events(void)
register_idle_thread();
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);
}

Expand Down
6 changes: 4 additions & 2 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static char *pretty_printing_style = default_pretty_printing_style;
static int exclude_other = 1;

static char callchain_default_opt[] = "fractal,0.5";
const char *vmlinux_name;

static char *cwd;
static int cwdlen;
Expand Down Expand Up @@ -925,8 +926,9 @@ static int __cmd_report(void)

register_perf_file_handler(&file_handler);

ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths,
&cwdlen, &cwd);
ret = mmap_dispatch_perf_file(&header, input_name, vmlinux_name,
!vmlinux_name, force,
full_paths, &cwdlen, &cwd);
if (ret)
return ret;

Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1718,7 +1718,8 @@ static int read_events(void)
register_idle_thread();
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)
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ static int dump_symtab = 0;
static bool hide_kernel_symbols = false;
static bool hide_user_symbols = false;
static struct winsize winsize;
const char *vmlinux_name;
static const char *graph_line =
"_____________________________________________________________________"
"_____________________________________________________________________";
Expand Down Expand Up @@ -1341,7 +1342,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
if (delay_secs < 1)
delay_secs = 1;

err = kernel_maps__init(true);
err = kernel_maps__init(vmlinux_name, !vmlinux_name, true);
if (err < 0)
return err;
parse_source(sym_filter_entry);
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ static int __cmd_trace(void)
register_idle_thread();
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[] = {
Expand Down
4 changes: 3 additions & 1 deletion tools/perf/util/data_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
const char *input_name,
const char *vmlinux_name,
bool try_vmlinux_path,
int force,
int full_paths,
int *cwdlen,
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/data_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
113 changes: 101 additions & 12 deletions tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -1494,11 +1522,72 @@ static int kernel_maps__create_kernel_map(void)
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");
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/util/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ 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);

extern struct list_head dsos;
extern struct map *kernel_map;
extern struct dso *vdso;
extern const char *vmlinux_name;
#endif /* __PERF_SYMBOL */

0 comments on commit cc612d8

Please sign in to comment.