Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+78 -31
+4
tools/perf/builtin-top.c
··· 132 132 if (err == 0) { 133 133 out_assign: 134 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 141 pthread_mutex_unlock(&notes->lock);
+6 -3
tools/perf/ui/browsers/annotate.c
··· 1026 1026 .use_navkeypressed = true, 1027 1027 }, 1028 1028 }; 1029 - int ret = -1; 1029 + int ret = -1, err; 1030 1030 int nr_pcnt = 1; 1031 1031 size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1032 1032 ··· 1050 1050 (nr_pcnt - 1); 1051 1051 } 1052 1052 1053 - if (symbol__disassemble(sym, map, sizeof_bdl) < 0) { 1054 - ui__error("%s", ui_helpline__last_msg); 1053 + err = symbol__disassemble(sym, map, sizeof_bdl); 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 1058 goto out_free_offsets; 1056 1059 } 1057 1060
+6 -2
tools/perf/ui/gtk/annotate.c
··· 162 162 GtkWidget *notebook; 163 163 GtkWidget *scrolled_window; 164 164 GtkWidget *tab_label; 165 + int err; 165 166 166 167 if (map->dso->annotate_warned) 167 168 return -1; 168 169 169 - if (symbol__disassemble(sym, map, 0) < 0) { 170 - ui__error("%s", ui_helpline__current); 170 + err = symbol__disassemble(sym, map, 0); 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 175 return -1; 172 176 } 173 177
+42 -26
tools/perf/util/annotate.c
··· 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 1165 int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) 1127 1166 { 1128 1167 struct dso *dso = map->dso; ··· 1182 1143 symbol__join_symfs(symfs_filename, filename); 1183 1144 1184 1145 if (filename == NULL) { 1185 - if (dso->has_build_id) { 1186 - pr_err("Can't annotate %s: not enough memory\n", 1187 - sym->name); 1188 - return -ENOMEM; 1189 - } 1146 + if (dso->has_build_id) 1147 + return ENOMEM; 1190 1148 goto fallback; 1191 1149 } else if (dso__is_kcore(dso)) { 1192 1150 goto fallback; ··· 1204 1168 1205 1169 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1206 1170 !dso__is_kcore(dso)) { 1207 - char bf[SBUILD_ID_SIZE + 15] = " with build id "; 1208 - char *build_id_msg = NULL; 1209 - 1210 - if (dso->annotate_warned) 1211 - goto out_free_filename; 1212 - 1213 - if (dso->has_build_id) { 1214 - build_id__sprintf(dso->build_id, 1215 - sizeof(dso->build_id), bf + 15); 1216 - build_id_msg = bf; 1217 - } 1218 - err = -ENOENT; 1219 - dso->annotate_warned = 1; 1220 - pr_err("Can't annotate %s:\n\n" 1221 - "No vmlinux file%s\nwas found in the path.\n\n" 1222 - "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" 1223 - "Please use:\n\n" 1224 - " perf buildid-cache -vu vmlinux\n\n" 1225 - "or:\n\n" 1226 - " --vmlinux vmlinux\n", 1227 - sym->name, build_id_msg ?: ""); 1171 + err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1228 1172 goto out_free_filename; 1229 1173 } 1230 1174
+20
tools/perf/util/annotate.h
··· 157 157 158 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 180 int symbol__annotate_init(struct map *map, struct symbol *sym); 161 181 int symbol__annotate_printf(struct symbol *sym, struct map *map, 162 182 struct perf_evsel *evsel, bool full_paths,