diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-07-29 15:27:18 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-08-01 17:18:16 -0400 |
commit | ee51d851392e1fe3e8be30b3c5847f34da343424 (patch) | |
tree | 995d0ca1d366d17876e5b8d32daef596941dacaa /tools | |
parent | 5cb725a9723aebb248106ff7f8c6c7253b24bbb1 (diff) |
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 <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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-top.c | 4 | ||||
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 9 | ||||
-rw-r--r-- | tools/perf/ui/gtk/annotate.c | 8 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 68 | ||||
-rw-r--r-- | 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) | |||
132 | if (err == 0) { | 132 | if (err == 0) { |
133 | out_assign: | 133 | out_assign: |
134 | top->sym_filter_entry = he; | 134 | top->sym_filter_entry = he; |
135 | } else { | ||
136 | char msg[BUFSIZ]; | ||
137 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
138 | pr_err("Couldn't annotate %s: %s\n", sym->name, msg); | ||
135 | } | 139 | } |
136 | 140 | ||
137 | pthread_mutex_unlock(¬es->lock); | 141 | 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, | |||
1026 | .use_navkeypressed = true, | 1026 | .use_navkeypressed = true, |
1027 | }, | 1027 | }, |
1028 | }; | 1028 | }; |
1029 | int ret = -1; | 1029 | int ret = -1, err; |
1030 | int nr_pcnt = 1; | 1030 | int nr_pcnt = 1; |
1031 | size_t sizeof_bdl = sizeof(struct browser_disasm_line); | 1031 | size_t sizeof_bdl = sizeof(struct browser_disasm_line); |
1032 | 1032 | ||
@@ -1050,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, | |||
1050 | (nr_pcnt - 1); | 1050 | (nr_pcnt - 1); |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | if (symbol__disassemble(sym, map, sizeof_bdl) < 0) { | 1053 | err = symbol__disassemble(sym, map, sizeof_bdl); |
1054 | ui__error("%s", ui_helpline__last_msg); | 1054 | if (err) { |
1055 | char msg[BUFSIZ]; | ||
1056 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
1057 | ui__error("Couldn't annotate %s:\n%s", sym->name, msg); | ||
1055 | goto out_free_offsets; | 1058 | goto out_free_offsets; |
1056 | } | 1059 | } |
1057 | 1060 | ||
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, | |||
162 | GtkWidget *notebook; | 162 | GtkWidget *notebook; |
163 | GtkWidget *scrolled_window; | 163 | GtkWidget *scrolled_window; |
164 | GtkWidget *tab_label; | 164 | GtkWidget *tab_label; |
165 | int err; | ||
165 | 166 | ||
166 | if (map->dso->annotate_warned) | 167 | if (map->dso->annotate_warned) |
167 | return -1; | 168 | return -1; |
168 | 169 | ||
169 | if (symbol__disassemble(sym, map, 0) < 0) { | 170 | err = symbol__disassemble(sym, map, 0); |
170 | ui__error("%s", ui_helpline__current); | 171 | if (err) { |
172 | char msg[BUFSIZ]; | ||
173 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
174 | ui__error("Couldn't annotate %s: %s\n", sym->name, msg); | ||
171 | return -1; | 175 | return -1; |
172 | } | 176 | } |
173 | 177 | ||
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) | |||
1123 | } | 1123 | } |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, | ||
1127 | int errnum, char *buf, size_t buflen) | ||
1128 | { | ||
1129 | struct dso *dso = map->dso; | ||
1130 | |||
1131 | BUG_ON(buflen == 0); | ||
1132 | |||
1133 | if (errnum >= 0) { | ||
1134 | str_error_r(errnum, buf, buflen); | ||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | switch (errnum) { | ||
1139 | case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: { | ||
1140 | char bf[SBUILD_ID_SIZE + 15] = " with build id "; | ||
1141 | char *build_id_msg = NULL; | ||
1142 | |||
1143 | if (dso->has_build_id) { | ||
1144 | build_id__sprintf(dso->build_id, | ||
1145 | sizeof(dso->build_id), bf + 15); | ||
1146 | build_id_msg = bf; | ||
1147 | } | ||
1148 | scnprintf(buf, buflen, | ||
1149 | "No vmlinux file%s\nwas found in the path.\n\n" | ||
1150 | "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" | ||
1151 | "Please use:\n\n" | ||
1152 | " perf buildid-cache -vu vmlinux\n\n" | ||
1153 | "or:\n\n" | ||
1154 | " --vmlinux vmlinux\n", build_id_msg ?: ""); | ||
1155 | } | ||
1156 | break; | ||
1157 | default: | ||
1158 | scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1126 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) | 1165 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) |
1127 | { | 1166 | { |
1128 | struct dso *dso = map->dso; | 1167 | struct dso *dso = map->dso; |
@@ -1143,11 +1182,8 @@ int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) | |||
1143 | symbol__join_symfs(symfs_filename, filename); | 1182 | symbol__join_symfs(symfs_filename, filename); |
1144 | 1183 | ||
1145 | if (filename == NULL) { | 1184 | if (filename == NULL) { |
1146 | if (dso->has_build_id) { | 1185 | if (dso->has_build_id) |
1147 | pr_err("Can't annotate %s: not enough memory\n", | 1186 | return ENOMEM; |
1148 | sym->name); | ||
1149 | return -ENOMEM; | ||
1150 | } | ||
1151 | goto fallback; | 1187 | goto fallback; |
1152 | } else if (dso__is_kcore(dso)) { | 1188 | } else if (dso__is_kcore(dso)) { |
1153 | goto fallback; | 1189 | goto fallback; |
@@ -1168,27 +1204,7 @@ fallback: | |||
1168 | 1204 | ||
1169 | if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && | 1205 | if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && |
1170 | !dso__is_kcore(dso)) { | 1206 | !dso__is_kcore(dso)) { |
1171 | char bf[SBUILD_ID_SIZE + 15] = " with build id "; | 1207 | err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; |
1172 | char *build_id_msg = NULL; | ||
1173 | |||
1174 | if (dso->annotate_warned) | ||
1175 | goto out_free_filename; | ||
1176 | |||
1177 | if (dso->has_build_id) { | ||
1178 | build_id__sprintf(dso->build_id, | ||
1179 | sizeof(dso->build_id), bf + 15); | ||
1180 | build_id_msg = bf; | ||
1181 | } | ||
1182 | err = -ENOENT; | ||
1183 | dso->annotate_warned = 1; | ||
1184 | pr_err("Can't annotate %s:\n\n" | ||
1185 | "No vmlinux file%s\nwas found in the path.\n\n" | ||
1186 | "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" | ||
1187 | "Please use:\n\n" | ||
1188 | " perf buildid-cache -vu vmlinux\n\n" | ||
1189 | "or:\n\n" | ||
1190 | " --vmlinux vmlinux\n", | ||
1191 | sym->name, build_id_msg ?: ""); | ||
1192 | goto out_free_filename; | 1208 | goto out_free_filename; |
1193 | } | 1209 | } |
1194 | 1210 | ||
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); | |||
157 | 157 | ||
158 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize); | 158 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize); |
159 | 159 | ||
160 | enum symbol_disassemble_errno { | ||
161 | SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, | ||
162 | |||
163 | /* | ||
164 | * Choose an arbitrary negative big number not to clash with standard | ||
165 | * errno since SUS requires the errno has distinct positive values. | ||
166 | * See 'Issue 6' in the link below. | ||
167 | * | ||
168 | * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html | ||
169 | */ | ||
170 | __SYMBOL_ANNOTATE_ERRNO__START = -10000, | ||
171 | |||
172 | SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, | ||
173 | |||
174 | __SYMBOL_ANNOTATE_ERRNO__END, | ||
175 | }; | ||
176 | |||
177 | int symbol__strerror_disassemble(struct symbol *sym, struct map *map, | ||
178 | int errnum, char *buf, size_t buflen); | ||
179 | |||
160 | int symbol__annotate_init(struct map *map, struct symbol *sym); | 180 | int symbol__annotate_init(struct map *map, struct symbol *sym); |
161 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 181 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
162 | struct perf_evsel *evsel, bool full_paths, | 182 | struct perf_evsel *evsel, bool full_paths, |