perf annotate: Introduce strerror for handling symbol__disassemble() errors
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 29 Jul 2016 19:27:18 +0000 (16:27 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 1 Aug 2016 21:18:16 +0000 (18:18 -0300)
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 <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-dgd22zl2xg7x4vcnoa83jxfb@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-top.c
tools/perf/ui/browsers/annotate.c
tools/perf/ui/gtk/annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h

index 823dbbbf82a9c7b267d024559a45edb29e9e09a7..418ed94756d357f5101713945ae37b77178acb38 100644 (file)
@@ -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(&notes->lock);
index f4d6a8a962afd403c72954abbf8e54e9ce3c6dbd..2e2d10022355ba0303f4462a21758eec773986d0 100644 (file)
@@ -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;
        }
 
index 35e4b9e28c8d32d5ca6f4960c9b0b500b2ee01d6..42d319927762503b68a83c350fe3d5cec97e3355 100644 (file)
@@ -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;
        }
 
index 4f47b6069197d6361809ae66388cdaf85e65d245..4982ed487e962378a01d125262164d9654414256 100644 (file)
@@ -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 @@ fallback:
 
        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;
        }
 
index b0750d8bee1ffd8787294c7aa79ad79d723887a9..f67ccb0275615c1632d86eb5f09815eaf596b905 100644 (file)
@@ -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,