aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/bpf-loader.c88
-rw-r--r--tools/perf/util/bpf-loader.h23
-rw-r--r--tools/perf/util/parse-events.c7
-rw-r--r--tools/perf/util/util.h5
4 files changed, 108 insertions, 15 deletions
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index c46256b1f5fd..e3afa1b60bb5 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -53,7 +53,7 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
53 53
54 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 54 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
55 if (err) 55 if (err)
56 return ERR_PTR(err); 56 return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
57 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 57 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
58 free(obj_buf); 58 free(obj_buf);
59 } else 59 } else
@@ -113,14 +113,14 @@ config_bpf_program(struct bpf_program *prog)
113 if (err < 0) { 113 if (err < 0) {
114 pr_debug("bpf: '%s' is not a valid config string\n", 114 pr_debug("bpf: '%s' is not a valid config string\n",
115 config_str); 115 config_str);
116 err = -EINVAL; 116 err = -BPF_LOADER_ERRNO__CONFIG;
117 goto errout; 117 goto errout;
118 } 118 }
119 119
120 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { 120 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
121 pr_debug("bpf: '%s': group for event is set and not '%s'.\n", 121 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
122 config_str, PERF_BPF_PROBE_GROUP); 122 config_str, PERF_BPF_PROBE_GROUP);
123 err = -EINVAL; 123 err = -BPF_LOADER_ERRNO__GROUP;
124 goto errout; 124 goto errout;
125 } else if (!pev->group) 125 } else if (!pev->group)
126 pev->group = strdup(PERF_BPF_PROBE_GROUP); 126 pev->group = strdup(PERF_BPF_PROBE_GROUP);
@@ -132,9 +132,9 @@ config_bpf_program(struct bpf_program *prog)
132 } 132 }
133 133
134 if (!pev->event) { 134 if (!pev->event) {
135 pr_debug("bpf: '%s': event name is missing\n", 135 pr_debug("bpf: '%s': event name is missing. Section name should be 'key=value'\n",
136 config_str); 136 config_str);
137 err = -EINVAL; 137 err = -BPF_LOADER_ERRNO__EVENTNAME;
138 goto errout; 138 goto errout;
139 } 139 }
140 pr_debug("bpf: config '%s' is ok\n", config_str); 140 pr_debug("bpf: config '%s' is ok\n", config_str);
@@ -285,7 +285,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
285 (void **)&priv); 285 (void **)&priv);
286 if (err || !priv) { 286 if (err || !priv) {
287 pr_debug("bpf: failed to get private field\n"); 287 pr_debug("bpf: failed to get private field\n");
288 return -EINVAL; 288 return -BPF_LOADER_ERRNO__INTERNAL;
289 } 289 }
290 290
291 pev = &priv->pev; 291 pev = &priv->pev;
@@ -308,6 +308,18 @@ int bpf__foreach_tev(struct bpf_object *obj,
308 return 0; 308 return 0;
309} 309}
310 310
311#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
312#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
313#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
314
315static const char *bpf_loader_strerror_table[NR_ERRNO] = {
316 [ERRCODE_OFFSET(CONFIG)] = "Invalid config string",
317 [ERRCODE_OFFSET(GROUP)] = "Invalid group name",
318 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string",
319 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error",
320 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet",
321};
322
311static int 323static int
312bpf_loader_strerror(int err, char *buf, size_t size) 324bpf_loader_strerror(int err, char *buf, size_t size)
313{ 325{
@@ -322,10 +334,21 @@ bpf_loader_strerror(int err, char *buf, size_t size)
322 if (err >= __LIBBPF_ERRNO__START) 334 if (err >= __LIBBPF_ERRNO__START)
323 return libbpf_strerror(err, buf, size); 335 return libbpf_strerror(err, buf, size);
324 336
325 msg = strerror_r(err, sbuf, sizeof(sbuf)); 337 if (err >= __BPF_LOADER_ERRNO__START && err < __BPF_LOADER_ERRNO__END) {
326 snprintf(buf, size, "%s", msg); 338 msg = bpf_loader_strerror_table[ERRNO_OFFSET(err)];
339 snprintf(buf, size, "%s", msg);
340 buf[size - 1] = '\0';
341 return 0;
342 }
343
344 if (err >= __BPF_LOADER_ERRNO__END)
345 snprintf(buf, size, "Unknown bpf loader error %d", err);
346 else
347 snprintf(buf, size, "%s",
348 strerror_r(err, sbuf, sizeof(sbuf)));
349
327 buf[size - 1] = '\0'; 350 buf[size - 1] = '\0';
328 return 0; 351 return -1;
329} 352}
330 353
331#define bpf__strerror_head(err, buf, size) \ 354#define bpf__strerror_head(err, buf, size) \
@@ -351,21 +374,62 @@ bpf_loader_strerror(int err, char *buf, size_t size)
351 }\ 374 }\
352 buf[size - 1] = '\0'; 375 buf[size - 1] = '\0';
353 376
377int bpf__strerror_prepare_load(const char *filename, bool source,
378 int err, char *buf, size_t size)
379{
380 size_t n;
381 int ret;
382
383 n = snprintf(buf, size, "Failed to load %s%s: ",
384 filename, source ? " from source" : "");
385 if (n >= size) {
386 buf[size - 1] = '\0';
387 return 0;
388 }
389 buf += n;
390 size -= n;
391
392 ret = bpf_loader_strerror(err, buf, size);
393 buf[size - 1] = '\0';
394 return ret;
395}
396
354int bpf__strerror_probe(struct bpf_object *obj __maybe_unused, 397int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
355 int err, char *buf, size_t size) 398 int err, char *buf, size_t size)
356{ 399{
357 bpf__strerror_head(err, buf, size); 400 bpf__strerror_head(err, buf, size);
358 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'"); 401 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
359 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n"); 402 bpf__strerror_entry(EACCES, "You need to be root");
360 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n"); 403 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
404 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
361 bpf__strerror_end(buf, size); 405 bpf__strerror_end(buf, size);
362 return 0; 406 return 0;
363} 407}
364 408
365int bpf__strerror_load(struct bpf_object *obj __maybe_unused, 409int bpf__strerror_load(struct bpf_object *obj,
366 int err, char *buf, size_t size) 410 int err, char *buf, size_t size)
367{ 411{
368 bpf__strerror_head(err, buf, size); 412 bpf__strerror_head(err, buf, size);
413 case LIBBPF_ERRNO__KVER: {
414 unsigned int obj_kver = bpf_object__get_kversion(obj);
415 unsigned int real_kver;
416
417 if (fetch_kernel_version(&real_kver, NULL, 0)) {
418 scnprintf(buf, size, "Unable to fetch kernel version");
419 break;
420 }
421
422 if (obj_kver != real_kver) {
423 scnprintf(buf, size,
424 "'version' ("KVER_FMT") doesn't match running kernel ("KVER_FMT")",
425 KVER_PARAM(obj_kver),
426 KVER_PARAM(real_kver));
427 break;
428 }
429
430 scnprintf(buf, size, "Failed to load program for unknown reason");
431 break;
432 }
369 bpf__strerror_end(buf, size); 433 bpf__strerror_end(buf, size);
370 return 0; 434 return 0;
371} 435}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index ccd8d7fd79d3..5eb3629eed8b 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -8,9 +8,21 @@
8#include <linux/compiler.h> 8#include <linux/compiler.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <string.h> 10#include <string.h>
11#include <bpf/libbpf.h>
11#include "probe-event.h" 12#include "probe-event.h"
12#include "debug.h" 13#include "debug.h"
13 14
15enum bpf_loader_errno {
16 __BPF_LOADER_ERRNO__START = __LIBBPF_ERRNO__START - 100,
17 /* Invalid config string */
18 BPF_LOADER_ERRNO__CONFIG = __BPF_LOADER_ERRNO__START,
19 BPF_LOADER_ERRNO__GROUP, /* Invalid group name */
20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */
21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */
22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */
23 __BPF_LOADER_ERRNO__END,
24};
25
14struct bpf_object; 26struct bpf_object;
15#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" 27#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
16 28
@@ -19,6 +31,8 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
19 31
20#ifdef HAVE_LIBBPF_SUPPORT 32#ifdef HAVE_LIBBPF_SUPPORT
21struct bpf_object *bpf__prepare_load(const char *filename, bool source); 33struct bpf_object *bpf__prepare_load(const char *filename, bool source);
34int bpf__strerror_prepare_load(const char *filename, bool source,
35 int err, char *buf, size_t size);
22 36
23void bpf__clear(void); 37void bpf__clear(void);
24 38
@@ -67,6 +81,15 @@ __bpf_strerror(char *buf, size_t size)
67 return 0; 81 return 0;
68} 82}
69 83
84static inline
85int bpf__strerror_prepare_load(const char *filename __maybe_unused,
86 bool source __maybe_unused,
87 int err __maybe_unused,
88 char *buf, size_t size)
89{
90 return __bpf_strerror(buf, size);
91}
92
70static inline int 93static inline int
71bpf__strerror_probe(struct bpf_object *obj __maybe_unused, 94bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
72 int err __maybe_unused, 95 int err __maybe_unused,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c75b25d5e28c..e48d9da75707 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,
642 snprintf(errbuf, sizeof(errbuf), 642 snprintf(errbuf, sizeof(errbuf),
643 "BPF support is not compiled"); 643 "BPF support is not compiled");
644 else 644 else
645 snprintf(errbuf, sizeof(errbuf), 645 bpf__strerror_prepare_load(bpf_file_name,
646 "BPF object file '%s' is invalid", 646 source,
647 bpf_file_name); 647 -err, errbuf,
648 sizeof(errbuf));
648 649
649 data->error->help = strdup("(add -v to see detail)"); 650 data->error->help = strdup("(add -v to see detail)");
650 data->error->str = strdup(errbuf); 651 data->error->str = strdup(errbuf);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2665126267dc..dcc659017976 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -352,5 +352,10 @@ int get_stack_size(const char *str, unsigned long *_size);
352 352
353int fetch_kernel_version(unsigned int *puint, 353int fetch_kernel_version(unsigned int *puint,
354 char *str, size_t str_sz); 354 char *str, size_t str_sz);
355#define KVER_VERSION(x) (((x) >> 16) & 0xff)
356#define KVER_PATCHLEVEL(x) (((x) >> 8) & 0xff)
357#define KVER_SUBLEVEL(x) ((x) & 0xff)
358#define KVER_FMT "%d.%d.%d"
359#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
355 360
356#endif /* GIT_COMPAT_UTIL_H */ 361#endif /* GIT_COMPAT_UTIL_H */