From ee51d851392e1fe3e8be30b3c5847f34da343424 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 29 Jul 2016 16:27:18 -0300 Subject: [PATCH] perf annotate: Introduce strerror for handling symbol__disassemble() errors We were just using pr_error() which makes it difficult for non stdio UIs to provide errors using its widgets, as they need to somehow catch what was passed to pr_error(). Fix it by introducing a __strerror() interface like the ones used elsewhere, for instance target__strerror(). This is just the initial step, more work will be done, but first some error handling bugs noticed while working on this need to be dealt with. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-dgd22zl2xg7x4vcnoa83jxfb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 4 ++ tools/perf/ui/browsers/annotate.c | 9 ++-- tools/perf/ui/gtk/annotate.c | 8 +++- tools/perf/util/annotate.c | 68 +++++++++++++++++++------------ tools/perf/util/annotate.h | 20 +++++++++ 5 files changed, 78 insertions(+), 31 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 823dbbbf82a9..418ed94756d3 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -132,6 +132,10 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) if (err == 0) { out_assign: top->sym_filter_entry = he; + } else { + char msg[BUFSIZ]; + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); + pr_err("Couldn't annotate %s: %s\n", sym->name, msg); } pthread_mutex_unlock(¬es->lock); diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index f4d6a8a962af..2e2d10022355 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -1026,7 +1026,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, .use_navkeypressed = true, }, }; - int ret = -1; + int ret = -1, err; int nr_pcnt = 1; size_t sizeof_bdl = sizeof(struct browser_disasm_line); @@ -1050,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, (nr_pcnt - 1); } - if (symbol__disassemble(sym, map, sizeof_bdl) < 0) { - ui__error("%s", ui_helpline__last_msg); + err = symbol__disassemble(sym, map, sizeof_bdl); + if (err) { + char msg[BUFSIZ]; + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); + ui__error("Couldn't annotate %s:\n%s", sym->name, msg); goto out_free_offsets; } diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 35e4b9e28c8d..42d319927762 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -162,12 +162,16 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, GtkWidget *notebook; GtkWidget *scrolled_window; GtkWidget *tab_label; + int err; if (map->dso->annotate_warned) return -1; - if (symbol__disassemble(sym, map, 0) < 0) { - ui__error("%s", ui_helpline__current); + err = symbol__disassemble(sym, map, 0); + if (err) { + char msg[BUFSIZ]; + symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); + ui__error("Couldn't annotate %s: %s\n", sym->name, msg); return -1; } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4f47b6069197..4982ed487e96 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1123,6 +1123,45 @@ static void delete_last_nop(struct symbol *sym) } } +int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, + int errnum, char *buf, size_t buflen) +{ + struct dso *dso = map->dso; + + BUG_ON(buflen == 0); + + if (errnum >= 0) { + str_error_r(errnum, buf, buflen); + return 0; + } + + switch (errnum) { + case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: { + char bf[SBUILD_ID_SIZE + 15] = " with build id "; + char *build_id_msg = NULL; + + if (dso->has_build_id) { + build_id__sprintf(dso->build_id, + sizeof(dso->build_id), bf + 15); + build_id_msg = bf; + } + scnprintf(buf, buflen, + "No vmlinux file%s\nwas found in the path.\n\n" + "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" + "Please use:\n\n" + " perf buildid-cache -vu vmlinux\n\n" + "or:\n\n" + " --vmlinux vmlinux\n", build_id_msg ?: ""); + } + break; + default: + scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); + break; + } + + return 0; +} + int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) { struct dso *dso = map->dso; @@ -1143,11 +1182,8 @@ int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) symbol__join_symfs(symfs_filename, filename); if (filename == NULL) { - if (dso->has_build_id) { - pr_err("Can't annotate %s: not enough memory\n", - sym->name); - return -ENOMEM; - } + if (dso->has_build_id) + return ENOMEM; goto fallback; } else if (dso__is_kcore(dso)) { goto fallback; @@ -1168,27 +1204,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(dso)) { - char bf[SBUILD_ID_SIZE + 15] = " with build id "; - char *build_id_msg = NULL; - - if (dso->annotate_warned) - goto out_free_filename; - - if (dso->has_build_id) { - build_id__sprintf(dso->build_id, - sizeof(dso->build_id), bf + 15); - build_id_msg = bf; - } - err = -ENOENT; - dso->annotate_warned = 1; - pr_err("Can't annotate %s:\n\n" - "No vmlinux file%s\nwas found in the path.\n\n" - "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" - "Please use:\n\n" - " perf buildid-cache -vu vmlinux\n\n" - "or:\n\n" - " --vmlinux vmlinux\n", - sym->name, build_id_msg ?: ""); + err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; goto out_free_filename; } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index b0750d8bee1f..f67ccb027561 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -157,6 +157,26 @@ void symbol__annotate_zero_histograms(struct symbol *sym); int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize); +enum symbol_disassemble_errno { + SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, + + /* + * Choose an arbitrary negative big number not to clash with standard + * errno since SUS requires the errno has distinct positive values. + * See 'Issue 6' in the link below. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html + */ + __SYMBOL_ANNOTATE_ERRNO__START = -10000, + + SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, + + __SYMBOL_ANNOTATE_ERRNO__END, +}; + +int symbol__strerror_disassemble(struct symbol *sym, struct map *map, + int errnum, char *buf, size_t buflen); + int symbol__annotate_init(struct map *map, struct symbol *sym); int symbol__annotate_printf(struct symbol *sym, struct map *map, struct perf_evsel *evsel, bool full_paths, -- GitLab