Commit 463910a5 authored by Daniel Borkmann's avatar Daniel Borkmann

Merge branch 'bpf-bpftool-dbg-output'

Quentin Monnet says:

====================
This series adds an option to bpftool to make it print additional
information via libbpf and the kernel verifier when attempting to load
programs.

A new API function is added to libbpf in order to pass the log_level
from bpftool with the bpf_object__* part of the API.

Options for a finer control over the log levels to use for libbpf and
the verifier could be added in the future, if desired.

v3:
- Fix and clarify commit logs.

v2:
- Do not add distinct options for libbpf and verifier logs, just keep the
  one that sets all log levels to their maximum. Rename the option.
- Do not offer a way to pick desired log levels. The choice is "use the
  option to print all logs" or "stick with the defaults".
- Do not export BPF_LOG_* flags to user header.
- Update all man pages (most bpftool operations use libbpf and may print
  libbpf logs). Verifier logs are only used when attempting to load
  programs for now, so bpftool-prog.rst and bpftool.rst remain the only
  pages updated in that regard.

Previous discussion available at:

https://lore.kernel.org/bpf/20190523105426.3938-1-quentin.monnet@netronome.com/
https://lore.kernel.org/bpf/20190429095227.9745-1-quentin.monnet@netronome.com/
====================
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents d98363b5 55d77807
...@@ -72,6 +72,10 @@ OPTIONS ...@@ -72,6 +72,10 @@ OPTIONS
-p, --pretty -p, --pretty
Generate human-readable JSON output. Implies **-j**. Generate human-readable JSON output. Implies **-j**.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
EXAMPLES EXAMPLES
======== ========
**# bpftool btf dump id 1226** **# bpftool btf dump id 1226**
......
...@@ -113,6 +113,10 @@ OPTIONS ...@@ -113,6 +113,10 @@ OPTIONS
-f, --bpffs -f, --bpffs
Show file names of pinned programs. Show file names of pinned programs.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
EXAMPLES EXAMPLES
======== ========
| |
......
...@@ -73,6 +73,10 @@ OPTIONS ...@@ -73,6 +73,10 @@ OPTIONS
-p, --pretty -p, --pretty
Generate human-readable JSON output. Implies **-j**. Generate human-readable JSON output. Implies **-j**.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
SEE ALSO SEE ALSO
======== ========
**bpf**\ (2), **bpf**\ (2),
......
...@@ -152,6 +152,10 @@ OPTIONS ...@@ -152,6 +152,10 @@ OPTIONS
Do not automatically attempt to mount any virtual file system Do not automatically attempt to mount any virtual file system
(such as tracefs or BPF virtual file system) when necessary. (such as tracefs or BPF virtual file system) when necessary.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
EXAMPLES EXAMPLES
======== ========
**# bpftool map show** **# bpftool map show**
......
...@@ -65,6 +65,10 @@ OPTIONS ...@@ -65,6 +65,10 @@ OPTIONS
-p, --pretty -p, --pretty
Generate human-readable JSON output. Implies **-j**. Generate human-readable JSON output. Implies **-j**.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
EXAMPLES EXAMPLES
======== ========
......
...@@ -53,6 +53,10 @@ OPTIONS ...@@ -53,6 +53,10 @@ OPTIONS
-p, --pretty -p, --pretty
Generate human-readable JSON output. Implies **-j**. Generate human-readable JSON output. Implies **-j**.
-d, --debug
Print all logs available from libbpf, including debug-level
information.
EXAMPLES EXAMPLES
======== ========
......
...@@ -174,6 +174,11 @@ OPTIONS ...@@ -174,6 +174,11 @@ OPTIONS
Do not automatically attempt to mount any virtual file system Do not automatically attempt to mount any virtual file system
(such as tracefs or BPF virtual file system) when necessary. (such as tracefs or BPF virtual file system) when necessary.
-d, --debug
Print all logs available, even debug-level information. This
includes logs from libbpf as well as from the verifier, when
attempting to load programs.
EXAMPLES EXAMPLES
======== ========
**# bpftool prog show** **# bpftool prog show**
......
...@@ -66,6 +66,10 @@ OPTIONS ...@@ -66,6 +66,10 @@ OPTIONS
Do not automatically attempt to mount any virtual file system Do not automatically attempt to mount any virtual file system
(such as tracefs or BPF virtual file system) when necessary. (such as tracefs or BPF virtual file system) when necessary.
-d, --debug
Print all logs available, even debug-level information. This
includes logs from libbpf as well as from the verifier, when
attempting to load programs.
SEE ALSO SEE ALSO
======== ========
......
...@@ -187,7 +187,7 @@ _bpftool() ...@@ -187,7 +187,7 @@ _bpftool()
# Deal with options # Deal with options
if [[ ${words[cword]} == -* ]]; then if [[ ${words[cword]} == -* ]]; then
local c='--version --json --pretty --bpffs --mapcompat' local c='--version --json --pretty --bpffs --mapcompat --debug'
COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
return 0 return 0
fi fi
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include <bpf.h> #include <bpf.h>
#include <libbpf.h>
#include "main.h" #include "main.h"
...@@ -25,6 +26,7 @@ bool pretty_output; ...@@ -25,6 +26,7 @@ bool pretty_output;
bool json_output; bool json_output;
bool show_pinned; bool show_pinned;
bool block_mount; bool block_mount;
bool verifier_logs;
int bpf_flags; int bpf_flags;
struct pinned_obj_table prog_table; struct pinned_obj_table prog_table;
struct pinned_obj_table map_table; struct pinned_obj_table map_table;
...@@ -77,6 +79,13 @@ static int do_version(int argc, char **argv) ...@@ -77,6 +79,13 @@ static int do_version(int argc, char **argv)
return 0; return 0;
} }
static int __printf(2, 0)
print_all_levels(__maybe_unused enum libbpf_print_level level,
const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
int cmd_select(const struct cmd *cmds, int argc, char **argv, int cmd_select(const struct cmd *cmds, int argc, char **argv,
int (*help)(int argc, char **argv)) int (*help)(int argc, char **argv))
{ {
...@@ -317,6 +326,7 @@ int main(int argc, char **argv) ...@@ -317,6 +326,7 @@ int main(int argc, char **argv)
{ "bpffs", no_argument, NULL, 'f' }, { "bpffs", no_argument, NULL, 'f' },
{ "mapcompat", no_argument, NULL, 'm' }, { "mapcompat", no_argument, NULL, 'm' },
{ "nomount", no_argument, NULL, 'n' }, { "nomount", no_argument, NULL, 'n' },
{ "debug", no_argument, NULL, 'd' },
{ 0 } { 0 }
}; };
int opt, ret; int opt, ret;
...@@ -332,7 +342,7 @@ int main(int argc, char **argv) ...@@ -332,7 +342,7 @@ int main(int argc, char **argv)
hash_init(map_table.table); hash_init(map_table.table);
opterr = 0; opterr = 0;
while ((opt = getopt_long(argc, argv, "Vhpjfmn", while ((opt = getopt_long(argc, argv, "Vhpjfmnd",
options, NULL)) >= 0) { options, NULL)) >= 0) {
switch (opt) { switch (opt) {
case 'V': case 'V':
...@@ -362,6 +372,10 @@ int main(int argc, char **argv) ...@@ -362,6 +372,10 @@ int main(int argc, char **argv)
case 'n': case 'n':
block_mount = true; block_mount = true;
break; break;
case 'd':
libbpf_set_print(print_all_levels);
verifier_logs = true;
break;
default: default:
p_err("unrecognized option '%s'", argv[optind - 1]); p_err("unrecognized option '%s'", argv[optind - 1]);
if (json_output) if (json_output)
......
...@@ -91,6 +91,7 @@ extern json_writer_t *json_wtr; ...@@ -91,6 +91,7 @@ extern json_writer_t *json_wtr;
extern bool json_output; extern bool json_output;
extern bool show_pinned; extern bool show_pinned;
extern bool block_mount; extern bool block_mount;
extern bool verifier_logs;
extern int bpf_flags; extern int bpf_flags;
extern struct pinned_obj_table prog_table; extern struct pinned_obj_table prog_table;
extern struct pinned_obj_table map_table; extern struct pinned_obj_table map_table;
......
...@@ -750,10 +750,11 @@ static int do_detach(int argc, char **argv) ...@@ -750,10 +750,11 @@ static int do_detach(int argc, char **argv)
static int load_with_options(int argc, char **argv, bool first_prog_only) static int load_with_options(int argc, char **argv, bool first_prog_only)
{ {
enum bpf_attach_type expected_attach_type; struct bpf_object_load_attr load_attr = { 0 };
struct bpf_object_open_attr attr = { struct bpf_object_open_attr open_attr = {
.prog_type = BPF_PROG_TYPE_UNSPEC, .prog_type = BPF_PROG_TYPE_UNSPEC,
}; };
enum bpf_attach_type expected_attach_type;
struct map_replace *map_replace = NULL; struct map_replace *map_replace = NULL;
struct bpf_program *prog = NULL, *pos; struct bpf_program *prog = NULL, *pos;
unsigned int old_map_fds = 0; unsigned int old_map_fds = 0;
...@@ -767,7 +768,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) ...@@ -767,7 +768,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
if (!REQ_ARGS(2)) if (!REQ_ARGS(2))
return -1; return -1;
attr.file = GET_ARG(); open_attr.file = GET_ARG();
pinfile = GET_ARG(); pinfile = GET_ARG();
while (argc) { while (argc) {
...@@ -776,7 +777,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) ...@@ -776,7 +777,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
NEXT_ARG(); NEXT_ARG();
if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) { if (open_attr.prog_type != BPF_PROG_TYPE_UNSPEC) {
p_err("program type already specified"); p_err("program type already specified");
goto err_free_reuse_maps; goto err_free_reuse_maps;
} }
...@@ -793,7 +794,8 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) ...@@ -793,7 +794,8 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
strcat(type, *argv); strcat(type, *argv);
strcat(type, "/"); strcat(type, "/");
err = libbpf_prog_type_by_name(type, &attr.prog_type, err = libbpf_prog_type_by_name(type,
&open_attr.prog_type,
&expected_attach_type); &expected_attach_type);
free(type); free(type);
if (err < 0) if (err < 0)
...@@ -881,16 +883,16 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) ...@@ -881,16 +883,16 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
set_max_rlimit(); set_max_rlimit();
obj = __bpf_object__open_xattr(&attr, bpf_flags); obj = __bpf_object__open_xattr(&open_attr, bpf_flags);
if (IS_ERR_OR_NULL(obj)) { if (IS_ERR_OR_NULL(obj)) {
p_err("failed to open object file"); p_err("failed to open object file");
goto err_free_reuse_maps; goto err_free_reuse_maps;
} }
bpf_object__for_each_program(pos, obj) { bpf_object__for_each_program(pos, obj) {
enum bpf_prog_type prog_type = attr.prog_type; enum bpf_prog_type prog_type = open_attr.prog_type;
if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { if (open_attr.prog_type == BPF_PROG_TYPE_UNSPEC) {
const char *sec_name = bpf_program__title(pos, false); const char *sec_name = bpf_program__title(pos, false);
err = libbpf_prog_type_by_name(sec_name, &prog_type, err = libbpf_prog_type_by_name(sec_name, &prog_type,
...@@ -960,7 +962,12 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) ...@@ -960,7 +962,12 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
goto err_close_obj; goto err_close_obj;
} }
err = bpf_object__load(obj); load_attr.obj = obj;
if (verifier_logs)
/* log_level1 + log_level2 + stats, but not stable UAPI */
load_attr.log_level = 1 + 2 + 4;
err = bpf_object__load_xattr(&load_attr);
if (err) { if (err) {
p_err("failed to load object file"); p_err("failed to load object file");
goto err_close_obj; goto err_close_obj;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
BPF_VERSION = 0 BPF_VERSION = 0
BPF_PATCHLEVEL = 0 BPF_PATCHLEVEL = 0
BPF_EXTRAVERSION = 3 BPF_EXTRAVERSION = 4
MAKEFLAGS += --no-print-directory MAKEFLAGS += --no-print-directory
......
...@@ -2224,7 +2224,7 @@ static bool bpf_program__is_function_storage(struct bpf_program *prog, ...@@ -2224,7 +2224,7 @@ static bool bpf_program__is_function_storage(struct bpf_program *prog,
} }
static int static int
bpf_object__load_progs(struct bpf_object *obj) bpf_object__load_progs(struct bpf_object *obj, int log_level)
{ {
size_t i; size_t i;
int err; int err;
...@@ -2232,6 +2232,7 @@ bpf_object__load_progs(struct bpf_object *obj) ...@@ -2232,6 +2232,7 @@ bpf_object__load_progs(struct bpf_object *obj)
for (i = 0; i < obj->nr_programs; i++) { for (i = 0; i < obj->nr_programs; i++) {
if (bpf_program__is_function_storage(&obj->programs[i], obj)) if (bpf_program__is_function_storage(&obj->programs[i], obj))
continue; continue;
obj->programs[i].log_level = log_level;
err = bpf_program__load(&obj->programs[i], err = bpf_program__load(&obj->programs[i],
obj->license, obj->license,
obj->kern_version); obj->kern_version);
...@@ -2383,10 +2384,14 @@ int bpf_object__unload(struct bpf_object *obj) ...@@ -2383,10 +2384,14 @@ int bpf_object__unload(struct bpf_object *obj)
return 0; return 0;
} }
int bpf_object__load(struct bpf_object *obj) int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
{ {
struct bpf_object *obj;
int err; int err;
if (!attr)
return -EINVAL;
obj = attr->obj;
if (!obj) if (!obj)
return -EINVAL; return -EINVAL;
...@@ -2399,7 +2404,7 @@ int bpf_object__load(struct bpf_object *obj) ...@@ -2399,7 +2404,7 @@ int bpf_object__load(struct bpf_object *obj)
CHECK_ERR(bpf_object__create_maps(obj), err, out); CHECK_ERR(bpf_object__create_maps(obj), err, out);
CHECK_ERR(bpf_object__relocate(obj), err, out); CHECK_ERR(bpf_object__relocate(obj), err, out);
CHECK_ERR(bpf_object__load_progs(obj), err, out); CHECK_ERR(bpf_object__load_progs(obj, attr->log_level), err, out);
return 0; return 0;
out: out:
...@@ -2408,6 +2413,15 @@ int bpf_object__load(struct bpf_object *obj) ...@@ -2408,6 +2413,15 @@ int bpf_object__load(struct bpf_object *obj)
return err; return err;
} }
int bpf_object__load(struct bpf_object *obj)
{
struct bpf_object_load_attr attr = {
.obj = obj,
};
return bpf_object__load_xattr(&attr);
}
static int check_path(const char *path) static int check_path(const char *path)
{ {
char *cp, errmsg[STRERR_BUFSIZE]; char *cp, errmsg[STRERR_BUFSIZE];
......
...@@ -89,8 +89,14 @@ LIBBPF_API int bpf_object__unpin_programs(struct bpf_object *obj, ...@@ -89,8 +89,14 @@ LIBBPF_API int bpf_object__unpin_programs(struct bpf_object *obj,
LIBBPF_API int bpf_object__pin(struct bpf_object *object, const char *path); LIBBPF_API int bpf_object__pin(struct bpf_object *object, const char *path);
LIBBPF_API void bpf_object__close(struct bpf_object *object); LIBBPF_API void bpf_object__close(struct bpf_object *object);
struct bpf_object_load_attr {
struct bpf_object *obj;
int log_level;
};
/* Load/unload object into/from kernel */ /* Load/unload object into/from kernel */
LIBBPF_API int bpf_object__load(struct bpf_object *obj); LIBBPF_API int bpf_object__load(struct bpf_object *obj);
LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr);
LIBBPF_API int bpf_object__unload(struct bpf_object *obj); LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
LIBBPF_API const char *bpf_object__name(struct bpf_object *obj); LIBBPF_API const char *bpf_object__name(struct bpf_object *obj);
LIBBPF_API unsigned int bpf_object__kversion(struct bpf_object *obj); LIBBPF_API unsigned int bpf_object__kversion(struct bpf_object *obj);
......
...@@ -171,4 +171,5 @@ LIBBPF_0.0.4 { ...@@ -171,4 +171,5 @@ LIBBPF_0.0.4 {
btf_dump__free; btf_dump__free;
btf_dump__new; btf_dump__new;
btf__parse_elf; btf__parse_elf;
bpf_object__load_xattr;
} LIBBPF_0.0.3; } LIBBPF_0.0.3;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment