diff options
Diffstat (limited to 'tools/perf/util/bpf-loader.c')
-rw-r--r-- | tools/perf/util/bpf-loader.c | 88 |
1 files changed, 76 insertions, 12 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) err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); if (err) - return ERR_PTR(err); + return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); free(obj_buf); } else @@ -113,14 +113,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__CONFIG; 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__GROUP; goto errout; } else if (!pev->group) pev->group = strdup(PERF_BPF_PROBE_GROUP); @@ -132,9 +132,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__EVENTNAME; goto errout; } pr_debug("bpf: config '%s' is ok\n", config_str); @@ -285,7 +285,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__INTERNAL; } pev = &priv->pev; @@ -308,6 +308,18 @@ int bpf__foreach_tev(struct bpf_object *obj, return 0; } +#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) +#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c) +#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START) + +static const char *bpf_loader_strerror_table[NR_ERRNO] = { + [ERRCODE_OFFSET(CONFIG)] = "Invalid config string", + [ERRCODE_OFFSET(GROUP)] = "Invalid group name", + [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string", + [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error", + [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet", +}; + static int bpf_loader_strerror(int err, char *buf, size_t size) { @@ -322,10 +334,21 @@ bpf_loader_strerror(int err, char *buf, size_t size) if (err >= __LIBBPF_ERRNO__START) return libbpf_strerror(err, buf, size); - msg = strerror_r(err, sbuf, sizeof(sbuf)); - snprintf(buf, size, "%s", msg); + if (err >= __BPF_LOADER_ERRNO__START && err < __BPF_LOADER_ERRNO__END) { + msg = bpf_loader_strerror_table[ERRNO_OFFSET(err)]; + snprintf(buf, size, "%s", msg); + buf[size - 1] = '\0'; + return 0; + } + + if (err >= __BPF_LOADER_ERRNO__END) + snprintf(buf, size, "Unknown bpf loader error %d", err); + else + snprintf(buf, size, "%s", + strerror_r(err, sbuf, sizeof(sbuf))); + buf[size - 1] = '\0'; - return 0; + return -1; } #define bpf__strerror_head(err, buf, size) \ @@ -351,21 +374,62 @@ bpf_loader_strerror(int err, char *buf, size_t size) }\ 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; } -int bpf__strerror_load(struct bpf_object *obj __maybe_unused, +int bpf__strerror_load(struct bpf_object *obj, int err, char *buf, size_t size) { bpf__strerror_head(err, buf, size); + case LIBBPF_ERRNO__KVER: { + unsigned int obj_kver = bpf_object__get_kversion(obj); + unsigned int real_kver; + + if (fetch_kernel_version(&real_kver, NULL, 0)) { + scnprintf(buf, size, "Unable to fetch kernel version"); + break; + } + + if (obj_kver != real_kver) { + scnprintf(buf, size, + "'version' ("KVER_FMT") doesn't match running kernel ("KVER_FMT")", + KVER_PARAM(obj_kver), + KVER_PARAM(real_kver)); + break; + } + + scnprintf(buf, size, "Failed to load program for unknown reason"); + break; + } bpf__strerror_end(buf, size); return 0; } |