@@ -1614,7 +1614,8 @@ struct bpf_prog {
call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
call_get_func_ip:1, /* Do we call get_func_ip() */
tstamp_type_access:1, /* Accessed __sk_buff->tstamp_type */
- sleepable:1; /* BPF program is sleepable */
+ sleepable:1, /* BPF program is sleepable */
+ debug_mode:1;
enum bpf_prog_type type; /* Type of BPF program */
enum bpf_attach_type expected_attach_type; /* For some prog types */
u32 len; /* Number of filter blocks */
@@ -1272,6 +1272,7 @@ enum bpf_perf_event_type {
/* The verifier internal test flag. Behavior is undefined */
#define BPF_F_TEST_REG_INVARIANTS (1U << 7)
+#define BPF_F_DEBUG_MODE (1U << 8)
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
*/
@@ -2757,7 +2757,8 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
BPF_F_XDP_HAS_FRAGS |
BPF_F_XDP_DEV_BOUND_ONLY |
BPF_F_TEST_REG_INVARIANTS |
- BPF_F_TOKEN_FD))
+ BPF_F_TOKEN_FD |
+ BPF_F_DEBUG_MODE))
return -EINVAL;
bpf_prog_load_fixup_attach_type(attr);
@@ -2870,6 +2871,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
prog->expected_attach_type = attr->expected_attach_type;
prog->sleepable = !!(attr->prog_flags & BPF_F_SLEEPABLE);
+ prog->debug_mode = !!(attr->prog_flags & BPF_F_DEBUG_MODE);
prog->aux->attach_btf = attach_btf;
prog->aux->attach_btf_id = attr->attach_btf_id;
prog->aux->dst_prog = dst_prog;
@@ -1272,6 +1272,8 @@ enum bpf_perf_event_type {
/* The verifier internal test flag. Behavior is undefined */
#define BPF_F_TEST_REG_INVARIANTS (1U << 7)
+#define BPF_F_DEBUG_MODE (1U << 8)
+
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
*/
@@ -689,6 +689,7 @@ struct bpf_object {
bool loaded;
bool has_subcalls;
bool has_rodata;
+ bool debug_mode;
struct bpf_gen *gen_loader;
@@ -7520,6 +7521,8 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
load_attr.log_level = log_level;
load_attr.prog_flags = prog->prog_flags;
load_attr.fd_array = obj->fd_array;
+ if (obj->debug_mode)
+ load_attr.prog_flags |= BPF_F_DEBUG_MODE;
load_attr.token_fd = obj->token_fd;
if (obj->token_fd)
@@ -7972,6 +7975,7 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
char *log_buf;
size_t log_size;
__u32 log_level;
+ bool debug_mode;
if (obj_buf && !obj_name)
return ERR_PTR(-EINVAL);
@@ -7996,6 +8000,7 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
log_buf = OPTS_GET(opts, kernel_log_buf, NULL);
log_size = OPTS_GET(opts, kernel_log_size, 0);
log_level = OPTS_GET(opts, kernel_log_level, 0);
+ debug_mode = OPTS_GET(opts, debug_mode, false);
if (log_size > UINT_MAX)
return ERR_PTR(-EINVAL);
if (log_size && !log_buf)
@@ -8018,6 +8023,7 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
obj->log_buf = log_buf;
obj->log_size = log_size;
obj->log_level = log_level;
+ obj->debug_mode = debug_mode;
if (token_path) {
obj->token_path = strdup(token_path);
@@ -123,6 +123,8 @@ struct bpf_object_open_opts {
*/
const char *object_name;
/* parse map definitions non-strictly, allowing extra attributes/data */
+ bool debug_mode;
+ /* open debug mode */
bool relaxed_maps;
/* maps that set the 'pinning' attribute in their definition will have
* their pin_path attribute set to a file in this directory, and be
This patch adds BPF debug mode. When a bpf program is in debug mode, all calls to kfuncs and helpers are traced and output to the trace ring buffer, including arguments and return values, in a strace-like format. Signed-off-by: Juntong Deng <juntong.deng@outlook.com> --- include/linux/bpf.h | 3 ++- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 4 +++- tools/include/uapi/linux/bpf.h | 2 ++ tools/lib/bpf/libbpf.c | 6 ++++++ tools/lib/bpf/libbpf.h | 2 ++ 6 files changed, 16 insertions(+), 2 deletions(-)