Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee51d851 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 5cb725a9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
+6 −3
Original line number Diff line number Diff line
@@ -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;
	}

+6 −2
Original line number Diff line number Diff line
@@ -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;
	}

+42 −26
Original line number Diff line number Diff line
@@ -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;
	}

+20 −0
Original line number Diff line number Diff line
@@ -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,