@@ -192,4 +192,122 @@ struct pt_regs;
192192 (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
193193#endif
194194
195+ #define ___bpf_concat (a , b ) a ## b
196+ #define ___bpf_apply (fn , n ) ___bpf_concat(fn, n)
197+ #define ___bpf_nth (_ , _1 , _2 , _3 , _4 , _5 , _6 , _7 , _8 , _9 , _a , _b , _c , N , ...) N
198+ #define ___bpf_narg (...) \
199+ ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
200+ #define ___bpf_empty (...) \
201+ ___bpf_nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)
202+
203+ #define ___bpf_ctx_cast0 () ctx
204+ #define ___bpf_ctx_cast1 (x ) ___bpf_ctx_cast0(), (void *)ctx[0]
205+ #define ___bpf_ctx_cast2 (x , args ...) ___bpf_ctx_cast1(args), (void *)ctx[1]
206+ #define ___bpf_ctx_cast3 (x , args ...) ___bpf_ctx_cast2(args), (void *)ctx[2]
207+ #define ___bpf_ctx_cast4 (x , args ...) ___bpf_ctx_cast3(args), (void *)ctx[3]
208+ #define ___bpf_ctx_cast5 (x , args ...) ___bpf_ctx_cast4(args), (void *)ctx[4]
209+ #define ___bpf_ctx_cast6 (x , args ...) ___bpf_ctx_cast5(args), (void *)ctx[5]
210+ #define ___bpf_ctx_cast7 (x , args ...) ___bpf_ctx_cast6(args), (void *)ctx[6]
211+ #define ___bpf_ctx_cast8 (x , args ...) ___bpf_ctx_cast7(args), (void *)ctx[7]
212+ #define ___bpf_ctx_cast9 (x , args ...) ___bpf_ctx_cast8(args), (void *)ctx[8]
213+ #define ___bpf_ctx_cast10 (x , args ...) ___bpf_ctx_cast9(args), (void *)ctx[9]
214+ #define ___bpf_ctx_cast11 (x , args ...) ___bpf_ctx_cast10(args), (void *)ctx[10]
215+ #define ___bpf_ctx_cast12 (x , args ...) ___bpf_ctx_cast11(args), (void *)ctx[11]
216+ #define ___bpf_ctx_cast (args ...) \
217+ ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
218+
219+ /*
220+ * BPF_PROG is a convenience wrapper for generic tp_btf/fentry/fexit and
221+ * similar kinds of BPF programs, that accept input arguments as a single
222+ * pointer to untyped u64 array, where each u64 can actually be a typed
223+ * pointer or integer of different size. Instead of requring user to write
224+ * manual casts and work with array elements by index, BPF_PROG macro
225+ * allows user to declare a list of named and typed input arguments in the
226+ * same syntax as for normal C function. All the casting is hidden and
227+ * performed transparently, while user code can just assume working with
228+ * function arguments of specified type and name.
229+ *
230+ * Original raw context argument is preserved as well as 'ctx' argument.
231+ * This is useful when using BPF helpers that expect original context
232+ * as one of the parameters (e.g., for bpf_perf_event_output()).
233+ */
234+ #define BPF_PROG (name , args ...) \
235+ name(unsigned long long *ctx); \
236+ static __attribute__((always_inline)) typeof(name(0)) \
237+ ____##name(unsigned long long *ctx, ##args); \
238+ typeof(name(0)) name(unsigned long long *ctx) \
239+ { \
240+ _Pragma("GCC diagnostic push") \
241+ _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
242+ return ____##name(___bpf_ctx_cast(args)); \
243+ _Pragma("GCC diagnostic pop") \
244+ } \
245+ static __attribute__((always_inline)) typeof(name(0)) \
246+ ____##name(unsigned long long *ctx, ##args)
247+
248+ struct pt_regs ;
249+
250+ #define ___bpf_kprobe_args0 () ctx
251+ #define ___bpf_kprobe_args1 (x ) \
252+ ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
253+ #define ___bpf_kprobe_args2 (x , args ...) \
254+ ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
255+ #define ___bpf_kprobe_args3 (x , args ...) \
256+ ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
257+ #define ___bpf_kprobe_args4 (x , args ...) \
258+ ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
259+ #define ___bpf_kprobe_args5 (x , args ...) \
260+ ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
261+ #define ___bpf_kprobe_args (args ...) \
262+ ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
263+
264+ /*
265+ * BPF_KPROBE serves the same purpose for kprobes as BPF_PROG for
266+ * tp_btf/fentry/fexit BPF programs. It hides the underlying platform-specific
267+ * low-level way of getting kprobe input arguments from struct pt_regs, and
268+ * provides a familiar typed and named function arguments syntax and
269+ * semantics of accessing kprobe input paremeters.
270+ *
271+ * Original struct pt_regs* context is preserved as 'ctx' argument. This might
272+ * be necessary when using BPF helpers like bpf_perf_event_output().
273+ */
274+ #define BPF_KPROBE (name , args ...) \
275+ name(struct pt_regs *ctx); \
276+ static __attribute__((always_inline)) typeof(name(0)) \
277+ ____##name(struct pt_regs *ctx, ##args); \
278+ typeof(name(0)) name(struct pt_regs *ctx) \
279+ { \
280+ _Pragma("GCC diagnostic push") \
281+ _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
282+ return ____##name(___bpf_kprobe_args(args)); \
283+ _Pragma("GCC diagnostic pop") \
284+ } \
285+ static __attribute__((always_inline)) typeof(name(0)) \
286+ ____##name(struct pt_regs *ctx, ##args)
287+
288+ #define ___bpf_kretprobe_args0 () ctx
289+ #define ___bpf_kretprobe_args1 (x ) \
290+ ___bpf_kretprobe_args0(), (void *)PT_REGS_RET(ctx)
291+ #define ___bpf_kretprobe_args (args ...) \
292+ ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
293+
294+ /*
295+ * BPF_KRETPROBE is similar to BPF_KPROBE, except, it only provides optional
296+ * return value (in addition to `struct pt_regs *ctx`), but no input
297+ * arguments, because they will be clobbered by the time probed function
298+ * returns.
299+ */
300+ #define BPF_KRETPROBE (name , args ...) \
301+ name(struct pt_regs *ctx); \
302+ static __attribute__((always_inline)) typeof(name(0)) \
303+ ____##name(struct pt_regs *ctx, ##args); \
304+ typeof(name(0)) name(struct pt_regs *ctx) \
305+ { \
306+ _Pragma("GCC diagnostic push") \
307+ _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
308+ return ____##name(___bpf_kretprobe_args(args)); \
309+ _Pragma("GCC diagnostic pop") \
310+ } \
311+ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
312+
195313#endif
0 commit comments