mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Wang Nan <wangnan0@huawei.com>
To: <acme@kernel.org>
Cc: <lizefan@huawei.com>, <pi3orama@163.com>,
	<linux-kernel@vger.kernel.org>, Wang Nan <wangnan0@huawei.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 5/5] perf tools: Improve BPF related error messages output
Date: Tue, 3 Nov 2015 10:44:46 +0000	[thread overview]
Message-ID: <1446547486-229499-6-git-send-email-wangnan0@huawei.com> (raw)
In-Reply-To: <1446547486-229499-1-git-send-email-wangnan0@huawei.com>

A series of bpf loader related error code is introduced to help error
delivering. Functions are improved to return those new error code.
Functions which return pointers are adjusted to encode error code into
return value using "ERR_PTR".

bpf_loader_strerror() are introduced to convert those error message to
string. It detected the value of error code and calls libbpf_strerror()
and strerror_r() accordingly, so caller don't need to consider checking
the range of error code. bpf__strerror_head() is updated so existing
strerror functions can support these error code automatically.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/bpf-loader.c   | 98 +++++++++++++++++++++++++++++++++++++-----
 tools/perf/util/bpf-loader.h   | 18 ++++++++
 tools/perf/util/parse-events.c |  7 +--
 3 files changed, 110 insertions(+), 13 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index dd6fa27..1e406f4 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,6 +14,10 @@
 #include "probe-finder.h" // for MAX_PROBES
 #include "llvm-utils.h"
 
+#if BPF_LOADER_ERRNO__END >= LIBBPF_ERRNO__START
+# error Too many BPF loader error code
+#endif
+
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...)	\
 {						\
@@ -53,7 +57,7 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 
 		err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
 		if (err)
-			return ERR_PTR(err);
+			return ERR_PTR(-BPF_LOADER_ERRNO__ECOMPILE);
 		obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 		free(obj_buf);
 	} else
@@ -113,14 +117,14 @@ config_bpf_program(struct bpf_program *prog)
 	if (err < 0) {
 		pr_debug("bpf: '%s' is not a valid config string\n",
 			 config_str);
-		err = -EINVAL;
+		err = -BPF_LOADER_ERRNO__ECONFIG;
 		goto errout;
 	}
 
 	if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
 		pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
 			 config_str, PERF_BPF_PROBE_GROUP);
-		err = -EINVAL;
+		err = -BPF_LOADER_ERRNO__EGROUP;
 		goto errout;
 	} else if (!pev->group)
 		pev->group = strdup(PERF_BPF_PROBE_GROUP);
@@ -132,9 +136,9 @@ config_bpf_program(struct bpf_program *prog)
 	}
 
 	if (!pev->event) {
-		pr_debug("bpf: '%s': event name is missing\n",
+		pr_debug("bpf: '%s': event name is missing. Section name should be 'key=value'\n",
 			 config_str);
-		err = -EINVAL;
+		err = -BPF_LOADER_ERRNO__EEVENTNAME;
 		goto errout;
 	}
 	pr_debug("bpf: config '%s' is ok\n", config_str);
@@ -285,7 +289,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
 				(void **)&priv);
 		if (err || !priv) {
 			pr_debug("bpf: failed to get private field\n");
-			return -EINVAL;
+			return -BPF_LOADER_ERRNO__EINTERNAL;
 		}
 
 		pev = &priv->pev;
@@ -308,13 +312,65 @@ int bpf__foreach_tev(struct bpf_object *obj,
 	return 0;
 }
 
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+struct {
+	int code;
+	const char *msg;
+} bpf_loader_strerror_table[] = {
+	{BPF_LOADER_ERRNO__ECONFIG, "Invalid config string"},
+	{BPF_LOADER_ERRNO__EGROUP, "Invalid group name"},
+	{BPF_LOADER_ERRNO__EEVENTNAME, "No event name found in config string"},
+	{BPF_LOADER_ERRNO__EINTERNAL, "BPF loader internal error"},
+	{BPF_LOADER_ERRNO__ECOMPILE, "Error when compiling BPF scriptlet"},
+};
+
+static int
+bpf_loader_strerror(int err, char *buf, size_t size)
+{
+	unsigned int i;
+
+	if (!buf || !size)
+		return -1;
+
+	err = err > 0 ? err : -err;
+
+	if (err > LIBBPF_ERRNO__START)
+		return libbpf_strerror(err, buf, size);
+
+	if (err < BPF_LOADER_ERRNO__START) {
+		char sbuf[STRERR_BUFSIZE], *msg;
+
+		msg = strerror_r(err, sbuf, sizeof(sbuf));
+		snprintf(buf, size, "%s", msg);
+		buf[size - 1] = '\0';
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bpf_loader_strerror_table); i++) {
+		if (bpf_loader_strerror_table[i].code == err) {
+			const char *msg;
+
+			msg = bpf_loader_strerror_table[i].msg;
+			snprintf(buf, size, "%s", msg);
+			buf[size - 1] = '\0';
+			return 0;
+		}
+	}
+
+	snprintf(buf, size, "Unknown bpf loader error %d", err);
+	buf[size - 1] = '\0';
+	return -1;
+}
+
 #define bpf__strerror_head(err, buf, size) \
 	char sbuf[STRERR_BUFSIZE], *emsg;\
 	if (!size)\
 		return 0;\
 	if (err < 0)\
 		err = -err;\
-	emsg = strerror_r(err, sbuf, sizeof(sbuf));\
+	bpf_loader_strerror(err, sbuf, sizeof(sbuf));\
+	emsg = sbuf;\
 	switch (err) {\
 	default:\
 		scnprintf(buf, size, "%s", emsg);\
@@ -330,13 +386,34 @@ int bpf__foreach_tev(struct bpf_object *obj,
 	}\
 	buf[size - 1] = '\0';
 
+int bpf__strerror_prepare_load(const char *filename, bool source,
+			       int err, char *buf, size_t size)
+{
+	size_t n;
+	int ret;
+
+	n = snprintf(buf, size, "Failed to load %s%s: ",
+			 filename, source ? " from source" : "");
+	if (n >= size) {
+		buf[size - 1] = '\0';
+		return 0;
+	}
+	buf += n;
+	size -= n;
+
+	ret = bpf_loader_strerror(err, buf, size);
+	buf[size - 1] = '\0';
+	return ret;
+}
+
 int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
 			int err, char *buf, size_t size)
 {
 	bpf__strerror_head(err, buf, size);
 	bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
-	bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n");
-	bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n");
+	bpf__strerror_entry(EACCES, "You need to be root");
+	bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
+	bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
 	bpf__strerror_end(buf, size);
 	return 0;
 }
@@ -345,7 +422,8 @@ int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
 		       int err, char *buf, size_t size)
 {
 	bpf__strerror_head(err, buf, size);
-	bpf__strerror_entry(EINVAL, "%s: Are you root and runing a CONFIG_BPF_SYSCALL kernel?",
+	bpf__strerror_entry(LIBBPF_ERRNO__ELOAD,
+			    "%s: Validate your program and check 'license'/'version' sections in your object",
 			    emsg)
 	bpf__strerror_end(buf, size);
 	return 0;
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index ccd8d7f..490c78c 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -11,6 +11,14 @@
 #include "probe-event.h"
 #include "debug.h"
 
+#define BPF_LOADER_ERRNO__START		3900
+#define BPF_LOADER_ERRNO__ECONFIG 	3900 /* Invalid config string */
+#define BPF_LOADER_ERRNO__EGROUP 	3901 /* Invalid group name */
+#define BPF_LOADER_ERRNO__EEVENTNAME	3902 /* Event name is missing */
+#define BPF_LOADER_ERRNO__EINTERNAL	3903 /* BPF loader internal error */
+#define BPF_LOADER_ERRNO__ECOMPILE	3904 /* Error when compiling BPF scriptlet */
+#define BPF_LOADER_ERRNO__END		3905
+
 struct bpf_object;
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
@@ -19,6 +27,8 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
 
 #ifdef HAVE_LIBBPF_SUPPORT
 struct bpf_object *bpf__prepare_load(const char *filename, bool source);
+int bpf__strerror_prepare_load(const char *filename, bool source,
+			       int err, char *buf, size_t size);
 
 void bpf__clear(void);
 
@@ -67,6 +77,14 @@ __bpf_strerror(char *buf, size_t size)
 	return 0;
 }
 
+int bpf__strerror_prepare_load(const char *filename __maybe_unused,
+			       bool source __maybe_unused,
+			       int err __maybe_unused,
+			       char *buf, size_t size)
+{
+	return __bpf_strerror(buf, size);
+}
+
 static inline int
 bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
 		    int err __maybe_unused,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bee6058..6b07027 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -642,9 +642,10 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
 			snprintf(errbuf, sizeof(errbuf),
 				 "BPF support is not compiled");
 		else
-			snprintf(errbuf, sizeof(errbuf),
-				 "BPF object file '%s' is invalid",
-				 bpf_file_name);
+			bpf__strerror_prepare_load(bpf_file_name,
+						   source,
+						   -err, errbuf,
+						   sizeof(errbuf));
 
 		data->error->help = strdup("(add -v to see detail)");
 		data->error->str = strdup(errbuf);
-- 
1.8.3.4


  parent reply	other threads:[~2015-11-03 11:01 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-03 10:44 [PATCH 0/5] perf bpf: Improve error code delivering and output Wang Nan
2015-11-03 10:44 ` [PATCH 1/5] perf test: Keep test result clean if '-v' not set Wang Nan
2015-11-03 11:19   ` Namhyung Kim
2015-11-08  7:27   ` [tip:perf/urgent] " tip-bot for Wang Nan
2015-11-03 10:44 ` [PATCH 2/5] perf tools: Mute libbpf when " Wang Nan
2015-11-03 10:49   ` Wangnan (F)
2015-11-08  7:27   ` [tip:perf/urgent] perf bpf: " tip-bot for Wang Nan
2015-11-03 10:44 ` [PATCH 3/5] perf tools: Parsing libbpf return value using err.h Wang Nan
2015-11-03 15:17   ` Arnaldo Carvalho de Melo
2015-11-03 15:20     ` Arnaldo Carvalho de Melo
2015-11-03 10:44 ` [PATCH 4/5] bpf tools: Improve libbpf error reporting Wang Nan
2015-11-03 10:44 ` Wang Nan [this message]
2015-11-03 15:43 ` [PATCH 0/5] perf bpf: Improve error code delivering and output Arnaldo Carvalho de Melo
2015-11-04  1:43   ` Wangnan (F)

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=1446547486-229499-6-git-send-email-wangnan0@huawei.com \
    --to=wangnan0@huawei.com \
    --cc=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=pi3orama@163.com \
    /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

all inboxes | Powered by JetHome®