perf top: Properly notify the user that vmlinux is missing

Before this patch this message would very briefly appear on the
screen and then the screen would get updates only on the top,
for number of interrupts received, etc, but no annotation would
be performed:

 [root@doppio linux-2.6-tip]# perf top -s n_tty_write > /tmp/bla
 objdump: '[kernel.kallsyms]': No such file

Now this is what the user gets:

 [root@doppio linux-2.6-tip]# perf top -s n_tty_write
 Can't annotate n_tty_write: No vmlinux file was found in the
 path: [0] vmlinux
 [1] /boot/vmlinux
 [2] /boot/vmlinux-2.6.33-rc5
 [3] /lib/modules/2.6.33-rc5/build/vmlinux
 [4] /usr/lib/debug/lib/modules/2.6.33-rc5/vmlinux
 [root@doppio linux-2.6-tip]#

This bug was introduced when we added automatic search for
vmlinux, before that time the user had to specify a vmlinux
file.

Reported-by: David S. Miller <davem@davemloft.net>
Reported-by: Ingo Molnar <mingo@elte.hu>
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>
Cc: <stable@kernel.org>
LKML-Reference: <1268664418-28328-2-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Arnaldo Carvalho de Melo 2010-03-15 11:46:58 -03:00 committed by Ingo Molnar
parent bedbfdea31
commit b0a9ab62ab
3 changed files with 52 additions and 21 deletions

View file

@ -169,7 +169,7 @@ static void sig_winch_handler(int sig __used)
update_print_entries(&winsize); update_print_entries(&winsize);
} }
static void parse_source(struct sym_entry *syme) static int parse_source(struct sym_entry *syme)
{ {
struct symbol *sym; struct symbol *sym;
struct sym_entry_source *source; struct sym_entry_source *source;
@ -180,12 +180,21 @@ static void parse_source(struct sym_entry *syme)
u64 len; u64 len;
if (!syme) if (!syme)
return; return -1;
sym = sym_entry__symbol(syme);
map = syme->map;
/*
* We can't annotate with just /proc/kallsyms
*/
if (map->dso->origin == DSO__ORIG_KERNEL)
return -1;
if (syme->src == NULL) { if (syme->src == NULL) {
syme->src = zalloc(sizeof(*source)); syme->src = zalloc(sizeof(*source));
if (syme->src == NULL) if (syme->src == NULL)
return; return -1;
pthread_mutex_init(&syme->src->lock, NULL); pthread_mutex_init(&syme->src->lock, NULL);
} }
@ -195,9 +204,6 @@ static void parse_source(struct sym_entry *syme)
pthread_mutex_lock(&source->lock); pthread_mutex_lock(&source->lock);
goto out_assign; goto out_assign;
} }
sym = sym_entry__symbol(syme);
map = syme->map;
path = map->dso->long_name; path = map->dso->long_name;
len = sym->end - sym->start; len = sym->end - sym->start;
@ -209,7 +215,7 @@ static void parse_source(struct sym_entry *syme)
file = popen(command, "r"); file = popen(command, "r");
if (!file) if (!file)
return; return -1;
pthread_mutex_lock(&source->lock); pthread_mutex_lock(&source->lock);
source->lines_tail = &source->lines; source->lines_tail = &source->lines;
@ -245,6 +251,7 @@ static void parse_source(struct sym_entry *syme)
out_assign: out_assign:
sym_filter_entry = syme; sym_filter_entry = syme;
pthread_mutex_unlock(&source->lock); pthread_mutex_unlock(&source->lock);
return 0;
} }
static void __zero_source_counters(struct sym_entry *syme) static void __zero_source_counters(struct sym_entry *syme)
@ -991,7 +998,17 @@ static void event__process_sample(const event_t *self,
if (sym_filter_entry_sched) { if (sym_filter_entry_sched) {
sym_filter_entry = sym_filter_entry_sched; sym_filter_entry = sym_filter_entry_sched;
sym_filter_entry_sched = NULL; sym_filter_entry_sched = NULL;
parse_source(sym_filter_entry); if (parse_source(sym_filter_entry) < 0) {
struct symbol *sym = sym_entry__symbol(sym_filter_entry);
pr_err("Can't annotate %s", sym->name);
if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
pr_err(": No vmlinux file was found in the path:\n");
vmlinux_path__fprintf(stderr);
} else
pr_err(".\n");
exit(1);
}
} }
syme = symbol__priv(al.sym); syme = symbol__priv(al.sym);

View file

@ -18,18 +18,6 @@
#define NT_GNU_BUILD_ID 3 #define NT_GNU_BUILD_ID 3
#endif #endif
enum dso_origin {
DSO__ORIG_KERNEL = 0,
DSO__ORIG_JAVA_JIT,
DSO__ORIG_BUILD_ID_CACHE,
DSO__ORIG_FEDORA,
DSO__ORIG_UBUNTU,
DSO__ORIG_BUILDID,
DSO__ORIG_DSO,
DSO__ORIG_KMODULE,
DSO__ORIG_NOT_FOUND,
};
static void dsos__add(struct list_head *head, struct dso *dso); static void dsos__add(struct list_head *head, struct dso *dso);
static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
static int dso__load_kernel_sym(struct dso *self, struct map *map, static int dso__load_kernel_sym(struct dso *self, struct map *map,
@ -1017,7 +1005,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
} }
curr_map->map_ip = identity__map_ip; curr_map->map_ip = identity__map_ip;
curr_map->unmap_ip = identity__map_ip; curr_map->unmap_ip = identity__map_ip;
curr_dso->origin = DSO__ORIG_KERNEL; curr_dso->origin = self->origin;
map_groups__insert(kmap->kmaps, curr_map); map_groups__insert(kmap->kmaps, curr_map);
dsos__add(&dsos__kernel, curr_dso); dsos__add(&dsos__kernel, curr_dso);
dso__set_loaded(curr_dso, map->type); dso__set_loaded(curr_dso, map->type);
@ -1887,6 +1875,17 @@ out_fail:
return -1; return -1;
} }
size_t vmlinux_path__fprintf(FILE *fp)
{
int i;
size_t printed = 0;
for (i = 0; i < vmlinux_path__nr_entries; ++i)
printed += fprintf(fp, "[%d] %s\n", i, vmlinux_path[i]);
return printed;
}
static int setup_list(struct strlist **list, const char *list_str, static int setup_list(struct strlist **list, const char *list_str,
const char *list_name) const char *list_name)
{ {

View file

@ -149,6 +149,19 @@ size_t dsos__fprintf_buildid(FILE *fp, bool with_hits);
size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
enum dso_origin {
DSO__ORIG_KERNEL = 0,
DSO__ORIG_JAVA_JIT,
DSO__ORIG_BUILD_ID_CACHE,
DSO__ORIG_FEDORA,
DSO__ORIG_UBUNTU,
DSO__ORIG_BUILDID,
DSO__ORIG_DSO,
DSO__ORIG_KMODULE,
DSO__ORIG_NOT_FOUND,
};
char dso__symtab_origin(const struct dso *self); char dso__symtab_origin(const struct dso *self);
void dso__set_long_name(struct dso *self, char *name); void dso__set_long_name(struct dso *self, char *name);
void dso__set_build_id(struct dso *self, void *build_id); void dso__set_build_id(struct dso *self, void *build_id);
@ -168,4 +181,6 @@ int kallsyms__parse(const char *filename, void *arg,
int symbol__init(void); int symbol__init(void);
bool symbol_type__is_a(char symbol_type, enum map_type map_type); bool symbol_type__is_a(char symbol_type, enum map_type map_type);
size_t vmlinux_path__fprintf(FILE *fp);
#endif /* __PERF_SYMBOL */ #endif /* __PERF_SYMBOL */