mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Borislav Petkov <bp@suse.de>, David Ahern <dsahern@gmail.com>,
	Don Zickus <dzickus@redhat.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Namhyung Kim <namhyung@kernel.org>,
	Stephane Eranian <eranian@google.com>
Subject: [PATCH 14/25] perf symbols: Save DSO loading errno to better report errors
Date: Tue, 24 Mar 2015 13:19:29 -0300	[thread overview]
Message-ID: <1427213980-9015-15-git-send-email-acme@kernel.org> (raw)
In-Reply-To: <1427213980-9015-1-git-send-email-acme@kernel.org>

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Before, when some problem happened while trying to load the kernel
symtab, 'perf top' would show:

      ┌─Warning:───────────────────────────┐
      │The vmlinux file can't be used.     │
      │Kernel samples will not be resolved.│
      │                                    │
      │                                    │
      │Press any key...                    │
      └────────────────────────────────────┘

Now, it reports:

  # perf top --vmlinux /dev/null

      ┌─Warning:───────────────────────────────────────────┐
      │The /tmp/passwd file can't be used: Invalid ELF file│
      │Kernel samples will not be resolved.                │
      │                                                    │
      │                                                    │
      │Press any key...                                    │
      └────────────────────────────────────────────────────┘

This is possible because we now register the reason for not being able
to load the symtab in the dso->load_errno member, and provide a
dso__strerror_load() routine to format this error into a strerror like
string with a short reason for the error while loading.

That can be just forwarding the dso__strerror_load() call to
strerror_r(), or, for a separate errno range providing a custom message.

Reported-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-u5rb5uq63xqhkfb8uv2lxd5u@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-top.c         |  6 ++++--
 tools/perf/util/dso.c            | 33 +++++++++++++++++++++++++++++++++
 tools/perf/util/dso.h            | 28 ++++++++++++++++++++++++++++
 tools/perf/util/symbol-elf.c     | 37 +++++++++++++++++++++++++++----------
 tools/perf/util/symbol-minimal.c |  7 ++++---
 5 files changed, 96 insertions(+), 15 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5fb8723c7128..1cb3436276d1 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -757,8 +757,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
 		    al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
 		    RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
 			if (symbol_conf.vmlinux_name) {
-				ui__warning("The %s file can't be used.\n%s",
-					    symbol_conf.vmlinux_name, msg);
+				char serr[256];
+				dso__strerror_load(al.map->dso, serr, sizeof(serr));
+				ui__warning("The %s file can't be used: %s\n%s",
+					    symbol_conf.vmlinux_name, serr, msg);
 			} else {
 				ui__warning("A vmlinux file was not found.\n%s",
 					    msg);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0d3667f92023..fc0ddd5792a9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1137,3 +1137,36 @@ enum dso_type dso__type(struct dso *dso, struct machine *machine)
 
 	return dso__type_fd(fd);
 }
+
+int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
+{
+	int idx, errnum = dso->load_errno;
+	/*
+	 * This must have a same ordering as the enum dso_load_errno.
+	 */
+	static const char *dso_load__error_str[] = {
+	"Internal tools/perf/ library error",
+	"Invalid ELF file",
+	"Can not read build id",
+	"Mismatching build id",
+	"Decompression failure",
+	};
+
+	BUG_ON(buflen == 0);
+
+	if (errnum >= 0) {
+		const char *err = strerror_r(errnum, buf, buflen);
+
+		if (err != buf)
+			scnprintf(buf, buflen, "%s", err);
+
+		return 0;
+	}
+
+	if (errnum <  __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END)
+		return -1;
+
+	idx = errnum - __DSO_LOAD_ERRNO__START;
+	scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
+	return 0;
+}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 88f345cc5be2..e0901b4ed8de 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -60,6 +60,31 @@ enum dso_type {
 	DSO__TYPE_X32BIT,
 };
 
+enum dso_load_errno {
+	DSO_LOAD_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
+	 */
+	__DSO_LOAD_ERRNO__START		= -10000,
+
+	DSO_LOAD_ERRNO__INTERNAL_ERROR	= __DSO_LOAD_ERRNO__START,
+
+	/* for symsrc__init() */
+	DSO_LOAD_ERRNO__INVALID_ELF,
+	DSO_LOAD_ERRNO__CANNOT_READ_BUILDID,
+	DSO_LOAD_ERRNO__MISMATCHING_BUILDID,
+
+	/* for decompress_kmodule */
+	DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE,
+
+	__DSO_LOAD_ERRNO__END,
+};
+
 #define DSO__SWAP(dso, type, val)			\
 ({							\
 	type ____r = val;				\
@@ -113,6 +138,7 @@ struct dso {
 	enum dso_swap_type	needs_swap;
 	enum dso_binary_type	symtab_type;
 	enum dso_binary_type	binary_type;
+	enum dso_load_errno	load_errno;
 	u8		 adjust_symbols:1;
 	u8		 has_build_id:1;
 	u8		 has_srcline:1;
@@ -294,4 +320,6 @@ void dso__free_a2l(struct dso *dso);
 
 enum dso_type dso__type(struct dso *dso, struct machine *machine);
 
+int dso__strerror_load(struct dso *dso, char *buf, size_t buflen);
+
 #endif /* __PERF_DSO */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 78ffde9df9bf..476268c99431 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -595,10 +595,13 @@ static int decompress_kmodule(struct dso *dso, const char *name,
 		return -1;
 
 	fd = mkstemp(tmpbuf);
-	if (fd < 0)
+	if (fd < 0) {
+		dso->load_errno = errno;
 		goto out;
+	}
 
 	if (!decompress_to_file(m.ext, name, fd)) {
+		dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
 		close(fd);
 		fd = -1;
 	}
@@ -635,37 +638,49 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 	Elf *elf;
 	int fd;
 
-	if (dso__needs_decompress(dso))
+	if (dso__needs_decompress(dso)) {
 		fd = decompress_kmodule(dso, name, type);
-	else
+		if (fd < 0)
+			return -1;
+	} else {
 		fd = open(name, O_RDONLY);
-
-	if (fd < 0)
-		return -1;
+		if (fd < 0) {
+			dso->load_errno = errno;
+			return -1;
+		}
+	}
 
 	elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
 	if (elf == NULL) {
 		pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
+		dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
 		goto out_close;
 	}
 
 	if (gelf_getehdr(elf, &ehdr) == NULL) {
+		dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
 		pr_debug("%s: cannot get elf header.\n", __func__);
 		goto out_elf_end;
 	}
 
-	if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
+	if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) {
+		dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR;
 		goto out_elf_end;
+	}
 
 	/* Always reject images with a mismatched build-id: */
 	if (dso->has_build_id) {
 		u8 build_id[BUILD_ID_SIZE];
 
-		if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
+		if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
+			dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
 			goto out_elf_end;
+		}
 
-		if (!dso__build_id_equal(dso, build_id))
+		if (!dso__build_id_equal(dso, build_id)) {
+			dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
 			goto out_elf_end;
+		}
 	}
 
 	ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
@@ -701,8 +716,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 	}
 
 	ss->name   = strdup(name);
-	if (!ss->name)
+	if (!ss->name) {
+		dso->load_errno = errno;
 		goto out_elf_end;
+	}
 
 	ss->elf    = elf;
 	ss->fd     = fd;
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index d7efb03b3f9a..fd8477cacf88 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -246,13 +246,12 @@ out:
 	return ret;
 }
 
-int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
-		 const char *name,
+int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 	         enum dso_binary_type type)
 {
 	int fd = open(name, O_RDONLY);
 	if (fd < 0)
-		return -1;
+		goto out_errno;
 
 	ss->name = strdup(name);
 	if (!ss->name)
@@ -264,6 +263,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
 	return 0;
 out_close:
 	close(fd);
+out_errno:
+	dso->load_errno = errno;
 	return -1;
 }
 
-- 
1.9.3


  parent reply	other threads:[~2015-03-24 16:20 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-24 16:19 [GIT PULL 00/25] perf/core improvements and fixes Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 01/25] perf tools: Use kmod_path__parse in map_groups__set_modules_path_dir Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 02/25] perf tools: Use kmod_path__parse in decompress_kmodule Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 03/25] perf tools: Use kmod_path__parse in is_kernel_module Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 04/25] perf tools: Remove compressed argument from is_kernel_module Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 05/25] perf tools: Remove is_kmodule_extension function Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 06/25] perf tools: Try to lookup kernel module map before creating one Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 07/25] perf annotate: Allow annotation for decompressed kernel modules Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 08/25] perf tools: Remove (null) value of "Sort order" for perf mem report Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 09/25] perf probe: Fix to get ummapped symbol address on kernel Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 10/25] tools lib traceevent: Factor out allocating and processing args Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 11/25] perf kmem: Print big numbers using thousands' group Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 13/25] perf target: Simplify handling of strerror_r return Arnaldo Carvalho de Melo
2015-03-24 16:19 ` Arnaldo Carvalho de Melo [this message]
2015-03-27 10:32   ` [PATCH 14/25] perf symbols: Save DSO loading errno to better report errors Borislav Petkov
2015-03-27 14:37     ` Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 15/25] tools lib traceevent: Handle NULL comm name Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 16/25] tools lib traceevent: Copy trace_clock and free it Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 17/25] tools lib traceevent: Handle %z in bprint format Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 18/25] tools lib traceevent: Add pevent_data_pid_from_comm() Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 19/25] tools lib traceevent: Make plugin options either string or boolean Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 21/25] tools lib traceevent: Add way to find sub buffer boundary Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 22/25] tools lib traceevent: Free filter tokens in process_filter() Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 23/25] tools lib traceevent: Add support for __print_array() Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 24/25] perf diff: Add kallsyms option Arnaldo Carvalho de Melo
2015-03-24 16:19 ` [PATCH 25/25] perf tools: Add pid/tid filtering to report and script commands Arnaldo Carvalho de Melo
2015-03-24 16:26 ` [GIT PULL 00/25] perf/core improvements and fixes Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1427213980-9015-15-git-send-email-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=adrian.hunter@intel.com \
    --cc=bp@suse.de \
    --cc=dsahern@gmail.com \
    --cc=dzickus@redhat.com \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome