libbpf: Add BPF_KPROBE_SYSCALL macro
authorHengqi Chen <hengqi.chen@gmail.com>
Mon, 7 Feb 2022 14:31:33 +0000 (22:31 +0800)
committerAndrii Nakryiko <andrii@kernel.org>
Wed, 9 Feb 2022 05:45:02 +0000 (21:45 -0800)
Add syscall-specific variant of BPF_KPROBE named BPF_KPROBE_SYSCALL ([0]).
The new macro hides the underlying way of getting syscall input arguments.
With the new macro, the following code:

    SEC("kprobe/__x64_sys_close")
    int BPF_KPROBE(do_sys_close, struct pt_regs *regs)
    {
        int fd;

        fd = PT_REGS_PARM1_CORE(regs);
        /* do something with fd */
    }

can be written as:

    SEC("kprobe/__x64_sys_close")
    int BPF_KPROBE_SYSCALL(do_sys_close, int fd)
    {
        /* do something with fd */
    }

  [0] Closes: https://github.com/libbpf/libbpf/issues/425

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220207143134.2977852-2-hengqi.chen@gmail.com
tools/lib/bpf/bpf_tracing.h

index eb6eb3b..e3a8c94 100644 (file)
@@ -470,4 +470,39 @@ typeof(name(0)) name(struct pt_regs *ctx)                              \
 }                                                                          \
 static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
 
+#define ___bpf_syscall_args0()           ctx
+#define ___bpf_syscall_args1(x)          ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args(args...)     ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
+
+/*
+ * BPF_KPROBE_SYSCALL is a variant of BPF_KPROBE, which is intended for
+ * tracing syscall functions, like __x64_sys_close. It hides the underlying
+ * platform-specific low-level way of getting syscall input arguments from
+ * struct pt_regs, and provides a familiar typed and named function arguments
+ * syntax and semantics of accessing syscall input parameters.
+ *
+ * Original struct pt_regs* context is preserved as 'ctx' argument. This might
+ * be necessary when using BPF helpers like bpf_perf_event_output().
+ *
+ * This macro relies on BPF CO-RE support.
+ */
+#define BPF_KPROBE_SYSCALL(name, args...)                                  \
+name(struct pt_regs *ctx);                                                 \
+static __attribute__((always_inline)) typeof(name(0))                      \
+____##name(struct pt_regs *ctx, ##args);                                   \
+typeof(name(0)) name(struct pt_regs *ctx)                                  \
+{                                                                          \
+       struct pt_regs *regs = PT_REGS_SYSCALL_REGS(ctx);                   \
+       _Pragma("GCC diagnostic push")                                      \
+       _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")              \
+       return ____##name(___bpf_syscall_args(args));                       \
+       _Pragma("GCC diagnostic pop")                                       \
+}                                                                          \
+static __attribute__((always_inline)) typeof(name(0))                      \
+____##name(struct pt_regs *ctx, ##args)
+
 #endif