diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 149 |
1 files changed, 96 insertions, 53 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 7e543c3102d4..32e6b6bc6f7d 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -4,6 +4,19 @@ * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> * Copyright (C) 2015 Huawei Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses> */ #include <stdlib.h> @@ -71,12 +84,13 @@ static const char *libbpf_strerror_table[NR_ERRNO] = { [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", - [ERRCODE_OFFSET(ENDIAN)] = "Endian missmatch", + [ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch", [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", [ERRCODE_OFFSET(RELOC)] = "Relocation failed", [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", + [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", }; int libbpf_strerror(int err, char *buf, size_t size) @@ -145,6 +159,7 @@ struct bpf_program { char *section_name; struct bpf_insn *insns; size_t insns_cnt; + enum bpf_prog_type type; struct { int insn_idx; @@ -286,6 +301,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx, prog->idx = idx; prog->instances.fds = NULL; prog->instances.nr = -1; + prog->type = BPF_PROG_TYPE_KPROBE; return 0; errout: @@ -881,8 +897,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) } static int -load_program(struct bpf_insn *insns, int insns_cnt, - char *license, u32 kern_version, int *pfd) +load_program(enum bpf_prog_type type, struct bpf_insn *insns, + int insns_cnt, char *license, u32 kern_version, int *pfd) { int ret; char *log_buf; @@ -894,9 +910,8 @@ load_program(struct bpf_insn *insns, int insns_cnt, if (!log_buf) pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); - ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, - insns_cnt, license, kern_version, - log_buf, BPF_LOG_BUF_SIZE); + ret = bpf_load_program(type, insns, insns_cnt, license, + kern_version, log_buf, BPF_LOG_BUF_SIZE); if (ret >= 0) { *pfd = ret; @@ -912,15 +927,27 @@ load_program(struct bpf_insn *insns, int insns_cnt, pr_warning("-- BEGIN DUMP LOG ---\n"); pr_warning("\n%s\n", log_buf); pr_warning("-- END LOG --\n"); + } else if (insns_cnt >= BPF_MAXINSNS) { + pr_warning("Program too large (%d insns), at most %d insns\n", + insns_cnt, BPF_MAXINSNS); + ret = -LIBBPF_ERRNO__PROG2BIG; } else { - if (insns_cnt >= BPF_MAXINSNS) { - pr_warning("Program too large (%d insns), at most %d insns\n", - insns_cnt, BPF_MAXINSNS); - ret = -LIBBPF_ERRNO__PROG2BIG; - } else if (log_buf) { - pr_warning("log buffer is empty\n"); - ret = -LIBBPF_ERRNO__KVER; + /* Wrong program type? */ + if (type != BPF_PROG_TYPE_KPROBE) { + int fd; + + fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, + insns_cnt, license, kern_version, + NULL, 0); + if (fd >= 0) { + close(fd); + ret = -LIBBPF_ERRNO__PROGTYPE; + goto out; + } } + + if (log_buf) + ret = -LIBBPF_ERRNO__KVER; } out: @@ -955,7 +982,7 @@ bpf_program__load(struct bpf_program *prog, pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", prog->section_name, prog->instances.nr); } - err = load_program(prog->insns, prog->insns_cnt, + err = load_program(prog->type, prog->insns, prog->insns_cnt, license, kern_version, &fd); if (!err) prog->instances.fds[0] = fd; @@ -984,7 +1011,7 @@ bpf_program__load(struct bpf_program *prog, continue; } - err = load_program(result.new_insn_ptr, + err = load_program(prog->type, result.new_insn_ptr, result.new_insn_cnt, license, kern_version, &fd); @@ -1186,20 +1213,14 @@ bpf_object__next(struct bpf_object *prev) return next; } -const char * -bpf_object__get_name(struct bpf_object *obj) +const char *bpf_object__name(struct bpf_object *obj) { - if (!obj) - return ERR_PTR(-EINVAL); - return obj->path; + return obj ? obj->path : ERR_PTR(-EINVAL); } -unsigned int -bpf_object__get_kversion(struct bpf_object *obj) +unsigned int bpf_object__kversion(struct bpf_object *obj) { - if (!obj) - return 0; - return obj->kern_version; + return obj ? obj->kern_version : 0; } struct bpf_program * @@ -1224,9 +1245,8 @@ bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) return &obj->programs[idx]; } -int bpf_program__set_private(struct bpf_program *prog, - void *priv, - bpf_program_clear_priv_t clear_priv) +int bpf_program__set_priv(struct bpf_program *prog, void *priv, + bpf_program_clear_priv_t clear_priv) { if (prog->priv && prog->clear_priv) prog->clear_priv(prog, prog->priv); @@ -1236,10 +1256,9 @@ int bpf_program__set_private(struct bpf_program *prog, return 0; } -int bpf_program__get_private(struct bpf_program *prog, void **ppriv) +void *bpf_program__priv(struct bpf_program *prog) { - *ppriv = prog->priv; - return 0; + return prog ? prog->priv : ERR_PTR(-EINVAL); } const char *bpf_program__title(struct bpf_program *prog, bool needs_copy) @@ -1311,32 +1330,61 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n) return fd; } -int bpf_map__get_fd(struct bpf_map *map) +static void bpf_program__set_type(struct bpf_program *prog, + enum bpf_prog_type type) { - if (!map) - return -EINVAL; - - return map->fd; + prog->type = type; } -int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef) +int bpf_program__set_tracepoint(struct bpf_program *prog) { - if (!map || !pdef) + if (!prog) return -EINVAL; + bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT); + return 0; +} - *pdef = map->def; +int bpf_program__set_kprobe(struct bpf_program *prog) +{ + if (!prog) + return -EINVAL; + bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE); return 0; } -const char *bpf_map__get_name(struct bpf_map *map) +static bool bpf_program__is_type(struct bpf_program *prog, + enum bpf_prog_type type) { - if (!map) - return NULL; - return map->name; + return prog ? (prog->type == type) : false; +} + +bool bpf_program__is_tracepoint(struct bpf_program *prog) +{ + return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT); +} + +bool bpf_program__is_kprobe(struct bpf_program *prog) +{ + return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE); +} + +int bpf_map__fd(struct bpf_map *map) +{ + return map ? map->fd : -EINVAL; } -int bpf_map__set_private(struct bpf_map *map, void *priv, - bpf_map_clear_priv_t clear_priv) +const struct bpf_map_def *bpf_map__def(struct bpf_map *map) +{ + return map ? &map->def : ERR_PTR(-EINVAL); +} + +const char *bpf_map__name(struct bpf_map *map) +{ + return map ? map->name : NULL; +} + +int bpf_map__set_priv(struct bpf_map *map, void *priv, + bpf_map_clear_priv_t clear_priv) { if (!map) return -EINVAL; @@ -1351,14 +1399,9 @@ int bpf_map__set_private(struct bpf_map *map, void *priv, return 0; } -int bpf_map__get_private(struct bpf_map *map, void **ppriv) +void *bpf_map__priv(struct bpf_map *map) { - if (!map) - return -EINVAL; - - if (ppriv) - *ppriv = map->priv; - return 0; + return map ? map->priv : ERR_PTR(-EINVAL); } struct bpf_map * @@ -1389,7 +1432,7 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) } struct bpf_map * -bpf_object__get_map_by_name(struct bpf_object *obj, const char *name) +bpf_object__find_map_by_name(struct bpf_object *obj, const char *name) { struct bpf_map *pos; |