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:
parent
1b290d670f
commit
cc612d8199
11 changed files with 122 additions and 23 deletions
|
@ -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)
|
||||||
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)
|
||||||
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;
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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;
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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 {
|
||||||
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)
|
||||||
* 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);
|
||||||
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,
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -1403,9 +1433,7 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -1468,10 +1496,10 @@ static int kernel_maps__create_kernel_map(void)
|
||||||
if (kernel_map == NULL)
|
if (kernel_map == NULL)
|
||||||
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->kernel = 1;
|
||||||
|
|
||||||
kernel->short_name = "[kernel]";
|
|
||||||
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,11 +1522,72 @@ 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)
|
||||||
{
|
{
|
||||||
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;
|
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)
|
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, "
|
||||||
"continuing...\n");
|
"continuing...\n");
|
||||||
|
|
|
@ -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);
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in a new issue