All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
@ 2024-04-26  9:22 Jose E. Marchesi
  2024-04-26 16:15 ` Andrii Nakryiko
  2024-04-26 16:21 ` Alexei Starovoitov
  0 siblings, 2 replies; 7+ messages in thread
From: Jose E. Marchesi @ 2024-04-26  9:22 UTC (permalink / raw
  To: bpf; +Cc: Jose E . Marchesi, Andrii Nakryiko, david.faust,
	cupertino.miranda

The BPF_PROG, BPF_KPROBE and BPF_KSYSCALL macros defined in
tools/lib/bpf/bpf_tracing.h use a clever hack in order to provide a
convenient way to define entry points for BPF programs as if they were
normal C functions that get typed actual arguments, instead of as
elements in a single "context" array argument.

For example, PPF_PROGS allows writing:

  SEC("struct_ops/cwnd_event")
  void BPF_PROG(cwnd_event, struct sock *sk, enum tcp_ca_event event)
  {
        bbr_cwnd_event(sk, event);
        dctcp_cwnd_event(sk, event);
        cubictcp_cwnd_event(sk, event);
  }

That expands into a pair of functions:

  void ____cwnd_event (unsigned long long *ctx, struct sock *sk, enum tcp_ca_event event)
  {
        bbr_cwnd_event(sk, event);
        dctcp_cwnd_event(sk, event);
        cubictcp_cwnd_event(sk, event);
  }

  void cwnd_event (unsigned long long *ctx)
  {
        _Pragma("GCC diagnostic push")
        _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")
        return ____cwnd_event(ctx, (void*)ctx[0], (void*)ctx[1]);
        _Pragma("GCC diagnostic pop")
  }

Note how the 64-bit unsigned integers in the incoming CTX get casted
to a void pointer, and then implicitly converted to whatever type of
the actual argument in the wrapped function.  In this case:

  Arg1: unsigned long long -> void * -> struct sock *
  Arg2: unsigned long long -> void * -> enum tcp_ca_event

The behavior of GCC and clang when facing such conversions differ:

  pointer -> pointer

    Allowed by the C standard.
    GCC: no warning nor error.
    clang: no warning nor error.

  pointer -> integer type

    [C standard says the result of this conversion is implementation
     defined, and it may lead to unaligned pointer etc.]

    GCC: error: integer from pointer without a cast [-Wint-conversion]
    clang: error: incompatible pointer to integer conversion [-Wint-conversion]

  pointer -> enumerated type

    GCC: error: incompatible types in assigment (*)
    clang: error: incompatible pointer to integer conversion [-Wint-conversion]

These macros work because converting pointers to pointers is allowed,
and converting pointers to integers also works provided a suitable
integer type even if it is implementation defined, much like casting a
pointer to uintptr_t is guaranteed to work by the C standard.  The
conversion errors emitted by both compilers by default are silenced by
the pragmas.

However, the GCC error marked with (*) above when assigning a pointer
to an enumerated value is not associated with the -Wint-conversion
warning, and it is not possible to turn it off.

This is preventing building the BPF kernel selftests with GCC.

This patch fixes this by avoiding intermediate casts to void*,
replaced with casts to `uintptr', which is an integer type capable of
safely store a BPF pointer, much like the standard uintptr_t.

Tested in bpf-next master.
No regressions.

Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: david.faust@oracle.com
Cc: cupertino.miranda@oracle.com
---
 tools/lib/bpf/bpf_tracing.h | 80 ++++++++++++++++++++-----------------
 1 file changed, 43 insertions(+), 37 deletions(-)

diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
index 1c13f8e88833..1098505a89c7 100644
--- a/tools/lib/bpf/bpf_tracing.h
+++ b/tools/lib/bpf/bpf_tracing.h
@@ -4,6 +4,12 @@
 
 #include "bpf_helpers.h"
 
+/* The following integer unsigned type must be able to hold a pointer.
+   It is used in the macros below in order to avoid eventual casts
+   from pointers to enum values, since these are rejected by GCC.  */
+
+typedef unsigned long long uintptr;
+
 /* Scan the ARCH passed in from ARCH env variable (see Makefile) */
 #if defined(__TARGET_ARCH_x86)
 	#define bpf_target_x86
@@ -523,9 +529,9 @@ struct pt_regs;
 #else
 
 #define BPF_KPROBE_READ_RET_IP(ip, ctx)					    \
-	({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
+	({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)PT_REGS_RET(ctx)); })
 #define BPF_KRETPROBE_READ_RET_IP(ip, ctx)				    \
-	({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
+	({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)(PT_REGS_FP(ctx) + sizeof(ip))); })
 
 #endif
 
@@ -633,18 +639,18 @@ struct pt_regs;
 #endif
 
 #define ___bpf_ctx_cast0()            ctx
-#define ___bpf_ctx_cast1(x)           ___bpf_ctx_cast0(), (void *)ctx[0]
-#define ___bpf_ctx_cast2(x, args...)  ___bpf_ctx_cast1(args), (void *)ctx[1]
-#define ___bpf_ctx_cast3(x, args...)  ___bpf_ctx_cast2(args), (void *)ctx[2]
-#define ___bpf_ctx_cast4(x, args...)  ___bpf_ctx_cast3(args), (void *)ctx[3]
-#define ___bpf_ctx_cast5(x, args...)  ___bpf_ctx_cast4(args), (void *)ctx[4]
-#define ___bpf_ctx_cast6(x, args...)  ___bpf_ctx_cast5(args), (void *)ctx[5]
-#define ___bpf_ctx_cast7(x, args...)  ___bpf_ctx_cast6(args), (void *)ctx[6]
-#define ___bpf_ctx_cast8(x, args...)  ___bpf_ctx_cast7(args), (void *)ctx[7]
-#define ___bpf_ctx_cast9(x, args...)  ___bpf_ctx_cast8(args), (void *)ctx[8]
-#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (void *)ctx[9]
-#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (void *)ctx[10]
-#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (void *)ctx[11]
+#define ___bpf_ctx_cast1(x)           ___bpf_ctx_cast0(), (uintptr) ctx[0]
+#define ___bpf_ctx_cast2(x, args...)  ___bpf_ctx_cast1(args), (uintptr) ctx[1]
+#define ___bpf_ctx_cast3(x, args...)  ___bpf_ctx_cast2(args), (uintptr) ctx[2]
+#define ___bpf_ctx_cast4(x, args...)  ___bpf_ctx_cast3(args), (uintptr) ctx[3]
+#define ___bpf_ctx_cast5(x, args...)  ___bpf_ctx_cast4(args), (uintptr) ctx[4]
+#define ___bpf_ctx_cast6(x, args...)  ___bpf_ctx_cast5(args), (uintptr) ctx[5]
+#define ___bpf_ctx_cast7(x, args...)  ___bpf_ctx_cast6(args), (uintptr) ctx[6]
+#define ___bpf_ctx_cast8(x, args...)  ___bpf_ctx_cast7(args), (uintptr) ctx[7]
+#define ___bpf_ctx_cast9(x, args...)  ___bpf_ctx_cast8(args), (uintptr) ctx[8]
+#define ___bpf_ctx_cast10(x, args...) ___bpf_ctx_cast9(args), (uintptr) ctx[9]
+#define ___bpf_ctx_cast11(x, args...) ___bpf_ctx_cast10(args), (uintptr) ctx[10]
+#define ___bpf_ctx_cast12(x, args...) ___bpf_ctx_cast11(args), (uintptr) ctx[11]
 #define ___bpf_ctx_cast(args...)      ___bpf_apply(___bpf_ctx_cast, ___bpf_narg(args))(args)
 
 /*
@@ -786,14 +792,14 @@ ____##name(unsigned long long *ctx ___bpf_ctx_decl(args))
 struct pt_regs;
 
 #define ___bpf_kprobe_args0()           ctx
-#define ___bpf_kprobe_args1(x)          ___bpf_kprobe_args0(), (void *)PT_REGS_PARM1(ctx)
-#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (void *)PT_REGS_PARM2(ctx)
-#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (void *)PT_REGS_PARM3(ctx)
-#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (void *)PT_REGS_PARM4(ctx)
-#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (void *)PT_REGS_PARM5(ctx)
-#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (void *)PT_REGS_PARM6(ctx)
-#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (void *)PT_REGS_PARM7(ctx)
-#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (void *)PT_REGS_PARM8(ctx)
+#define ___bpf_kprobe_args1(x)          ___bpf_kprobe_args0(), (uintptr)PT_REGS_PARM1(ctx)
+#define ___bpf_kprobe_args2(x, args...) ___bpf_kprobe_args1(args), (uintptr)PT_REGS_PARM2(ctx)
+#define ___bpf_kprobe_args3(x, args...) ___bpf_kprobe_args2(args), (uintptr)PT_REGS_PARM3(ctx)
+#define ___bpf_kprobe_args4(x, args...) ___bpf_kprobe_args3(args), (uintptr)PT_REGS_PARM4(ctx)
+#define ___bpf_kprobe_args5(x, args...) ___bpf_kprobe_args4(args), (uintptr)PT_REGS_PARM5(ctx)
+#define ___bpf_kprobe_args6(x, args...) ___bpf_kprobe_args5(args), (uintptr)PT_REGS_PARM6(ctx)
+#define ___bpf_kprobe_args7(x, args...) ___bpf_kprobe_args6(args), (uintptr)PT_REGS_PARM7(ctx)
+#define ___bpf_kprobe_args8(x, args...) ___bpf_kprobe_args7(args), (uintptr)PT_REGS_PARM8(ctx)
 #define ___bpf_kprobe_args(args...)     ___bpf_apply(___bpf_kprobe_args, ___bpf_narg(args))(args)
 
 /*
@@ -821,7 +827,7 @@ static __always_inline typeof(name(0))					    \
 ____##name(struct pt_regs *ctx, ##args)
 
 #define ___bpf_kretprobe_args0()       ctx
-#define ___bpf_kretprobe_args1(x)      ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
+#define ___bpf_kretprobe_args1(x)      ___bpf_kretprobe_args0(), (uintptr)PT_REGS_RC(ctx)
 #define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
 
 /*
@@ -845,24 +851,24 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
 
 /* If kernel has CONFIG_ARCH_HAS_SYSCALL_WRAPPER, read pt_regs directly */
 #define ___bpf_syscall_args0()           ctx
-#define ___bpf_syscall_args1(x)          ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_SYSCALL(regs)
-#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_SYSCALL(regs)
-#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_SYSCALL(regs)
-#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_SYSCALL(regs)
-#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_SYSCALL(regs)
-#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (void *)PT_REGS_PARM6_SYSCALL(regs)
-#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (void *)PT_REGS_PARM7_SYSCALL(regs)
+#define ___bpf_syscall_args1(x)          ___bpf_syscall_args0(), (uintptr)PT_REGS_PARM1_SYSCALL(regs)
+#define ___bpf_syscall_args2(x, args...) ___bpf_syscall_args1(args), (uintptr)PT_REGS_PARM2_SYSCALL(regs)
+#define ___bpf_syscall_args3(x, args...) ___bpf_syscall_args2(args), (uintptr)PT_REGS_PARM3_SYSCALL(regs)
+#define ___bpf_syscall_args4(x, args...) ___bpf_syscall_args3(args), (uintptr)PT_REGS_PARM4_SYSCALL(regs)
+#define ___bpf_syscall_args5(x, args...) ___bpf_syscall_args4(args), (uintptr)PT_REGS_PARM5_SYSCALL(regs)
+#define ___bpf_syscall_args6(x, args...) ___bpf_syscall_args5(args), (uintptr)PT_REGS_PARM6_SYSCALL(regs)
+#define ___bpf_syscall_args7(x, args...) ___bpf_syscall_args6(args), (uintptr)PT_REGS_PARM7_SYSCALL(regs)
 #define ___bpf_syscall_args(args...)     ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
 
 /* If kernel doesn't have CONFIG_ARCH_HAS_SYSCALL_WRAPPER, we have to BPF_CORE_READ from pt_regs */
 #define ___bpf_syswrap_args0()           ctx
-#define ___bpf_syswrap_args1(x)          ___bpf_syswrap_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (void *)PT_REGS_PARM6_CORE_SYSCALL(regs)
-#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (void *)PT_REGS_PARM7_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args1(x)          ___bpf_syswrap_args0(), (uintptr)PT_REGS_PARM1_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args2(x, args...) ___bpf_syswrap_args1(args), (uintptr)PT_REGS_PARM2_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args3(x, args...) ___bpf_syswrap_args2(args), (uintptr)PT_REGS_PARM3_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args4(x, args...) ___bpf_syswrap_args3(args), (uintptr)PT_REGS_PARM4_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args5(x, args...) ___bpf_syswrap_args4(args), (uintptr)PT_REGS_PARM5_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args6(x, args...) ___bpf_syswrap_args5(args), (uintptr)PT_REGS_PARM6_CORE_SYSCALL(regs)
+#define ___bpf_syswrap_args7(x, args...) ___bpf_syswrap_args6(args), (uintptr)PT_REGS_PARM7_CORE_SYSCALL(regs)
 #define ___bpf_syswrap_args(args...)     ___bpf_apply(___bpf_syswrap_args, ___bpf_narg(args))(args)
 
 /*
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-26  9:22 [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h Jose E. Marchesi
@ 2024-04-26 16:15 ` Andrii Nakryiko
  2024-04-26 18:02   ` Jose E. Marchesi
  2024-04-26 16:21 ` Alexei Starovoitov
  1 sibling, 1 reply; 7+ messages in thread
From: Andrii Nakryiko @ 2024-04-26 16:15 UTC (permalink / raw
  To: Jose E. Marchesi; +Cc: bpf, david.faust, cupertino.miranda

On Fri, Apr 26, 2024 at 2:22 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
> The BPF_PROG, BPF_KPROBE and BPF_KSYSCALL macros defined in
> tools/lib/bpf/bpf_tracing.h use a clever hack in order to provide a
> convenient way to define entry points for BPF programs as if they were
> normal C functions that get typed actual arguments, instead of as
> elements in a single "context" array argument.
>
> For example, PPF_PROGS allows writing:
>
>   SEC("struct_ops/cwnd_event")
>   void BPF_PROG(cwnd_event, struct sock *sk, enum tcp_ca_event event)
>   {
>         bbr_cwnd_event(sk, event);
>         dctcp_cwnd_event(sk, event);
>         cubictcp_cwnd_event(sk, event);
>   }
>
> That expands into a pair of functions:
>
>   void ____cwnd_event (unsigned long long *ctx, struct sock *sk, enum tcp_ca_event event)
>   {
>         bbr_cwnd_event(sk, event);
>         dctcp_cwnd_event(sk, event);
>         cubictcp_cwnd_event(sk, event);
>   }
>
>   void cwnd_event (unsigned long long *ctx)
>   {
>         _Pragma("GCC diagnostic push")
>         _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")
>         return ____cwnd_event(ctx, (void*)ctx[0], (void*)ctx[1]);
>         _Pragma("GCC diagnostic pop")
>   }
>
> Note how the 64-bit unsigned integers in the incoming CTX get casted
> to a void pointer, and then implicitly converted to whatever type of
> the actual argument in the wrapped function.  In this case:
>
>   Arg1: unsigned long long -> void * -> struct sock *
>   Arg2: unsigned long long -> void * -> enum tcp_ca_event
>
> The behavior of GCC and clang when facing such conversions differ:
>
>   pointer -> pointer
>
>     Allowed by the C standard.
>     GCC: no warning nor error.
>     clang: no warning nor error.
>
>   pointer -> integer type
>
>     [C standard says the result of this conversion is implementation
>      defined, and it may lead to unaligned pointer etc.]
>
>     GCC: error: integer from pointer without a cast [-Wint-conversion]
>     clang: error: incompatible pointer to integer conversion [-Wint-conversion]
>
>   pointer -> enumerated type
>
>     GCC: error: incompatible types in assigment (*)
>     clang: error: incompatible pointer to integer conversion [-Wint-conversion]
>
> These macros work because converting pointers to pointers is allowed,
> and converting pointers to integers also works provided a suitable
> integer type even if it is implementation defined, much like casting a
> pointer to uintptr_t is guaranteed to work by the C standard.  The
> conversion errors emitted by both compilers by default are silenced by
> the pragmas.
>
> However, the GCC error marked with (*) above when assigning a pointer
> to an enumerated value is not associated with the -Wint-conversion
> warning, and it is not possible to turn it off.
>
> This is preventing building the BPF kernel selftests with GCC.
>
> This patch fixes this by avoiding intermediate casts to void*,
> replaced with casts to `uintptr', which is an integer type capable of
> safely store a BPF pointer, much like the standard uintptr_t.
>
> Tested in bpf-next master.
> No regressions.
>
> Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
> Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
> Cc: david.faust@oracle.com
> Cc: cupertino.miranda@oracle.com
> ---
>  tools/lib/bpf/bpf_tracing.h | 80 ++++++++++++++++++++-----------------
>  1 file changed, 43 insertions(+), 37 deletions(-)
>
> diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
> index 1c13f8e88833..1098505a89c7 100644
> --- a/tools/lib/bpf/bpf_tracing.h
> +++ b/tools/lib/bpf/bpf_tracing.h
> @@ -4,6 +4,12 @@
>
>  #include "bpf_helpers.h"
>
> +/* The following integer unsigned type must be able to hold a pointer.
> +   It is used in the macros below in order to avoid eventual casts
> +   from pointers to enum values, since these are rejected by GCC.  */
> +
> +typedef unsigned long long uintptr;
> +

hold on, we didn't talk about adding new typedefs. This bpf_tracing.h
header is included into tons of user code, so we should avoid adding
extra global definitions and typedes. Please just use (unsigned long
long) explicitly everywhere.

Also please check CI failures ([0]).

  [0] https://github.com/kernel-patches/bpf/actions/runs/8846180836/job/24291582343

pw-bot: cr

>  /* Scan the ARCH passed in from ARCH env variable (see Makefile) */
>  #if defined(__TARGET_ARCH_x86)
>         #define bpf_target_x86
> @@ -523,9 +529,9 @@ struct pt_regs;
>  #else
>
>  #define BPF_KPROBE_READ_RET_IP(ip, ctx)                                            \
> -       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
> +       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)PT_REGS_RET(ctx)); })
>  #define BPF_KRETPROBE_READ_RET_IP(ip, ctx)                                 \
> -       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
> +       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)(PT_REGS_FP(ctx) + sizeof(ip))); })

these are passing pointers, please don't just do a blind find&replace

>
>  #endif
>

[...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-26  9:22 [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h Jose E. Marchesi
  2024-04-26 16:15 ` Andrii Nakryiko
@ 2024-04-26 16:21 ` Alexei Starovoitov
  1 sibling, 0 replies; 7+ messages in thread
From: Alexei Starovoitov @ 2024-04-26 16:21 UTC (permalink / raw
  To: Jose E. Marchesi; +Cc: bpf, Andrii Nakryiko, David Faust, Cupertino Miranda

On Fri, Apr 26, 2024 at 2:22 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
> Tested in bpf-next master.
> No regressions.

CI disagrees :)

The build is failing on all architectures:
https://patchwork.kernel.org/project/netdevbpf/patch/20240426092214.16426-1-jose.marchesi@oracle.com/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-26 16:15 ` Andrii Nakryiko
@ 2024-04-26 18:02   ` Jose E. Marchesi
  2024-04-28 19:03     ` Jose E. Marchesi
  0 siblings, 1 reply; 7+ messages in thread
From: Jose E. Marchesi @ 2024-04-26 18:02 UTC (permalink / raw
  To: Andrii Nakryiko; +Cc: bpf, david.faust, cupertino.miranda


> On Fri, Apr 26, 2024 at 2:22 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>> The BPF_PROG, BPF_KPROBE and BPF_KSYSCALL macros defined in
>> tools/lib/bpf/bpf_tracing.h use a clever hack in order to provide a
>> convenient way to define entry points for BPF programs as if they were
>> normal C functions that get typed actual arguments, instead of as
>> elements in a single "context" array argument.
>>
>> For example, PPF_PROGS allows writing:
>>
>>   SEC("struct_ops/cwnd_event")
>>   void BPF_PROG(cwnd_event, struct sock *sk, enum tcp_ca_event event)
>>   {
>>         bbr_cwnd_event(sk, event);
>>         dctcp_cwnd_event(sk, event);
>>         cubictcp_cwnd_event(sk, event);
>>   }
>>
>> That expands into a pair of functions:
>>
>>   void ____cwnd_event (unsigned long long *ctx, struct sock *sk, enum tcp_ca_event event)
>>   {
>>         bbr_cwnd_event(sk, event);
>>         dctcp_cwnd_event(sk, event);
>>         cubictcp_cwnd_event(sk, event);
>>   }
>>
>>   void cwnd_event (unsigned long long *ctx)
>>   {
>>         _Pragma("GCC diagnostic push")
>>         _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")
>>         return ____cwnd_event(ctx, (void*)ctx[0], (void*)ctx[1]);
>>         _Pragma("GCC diagnostic pop")
>>   }
>>
>> Note how the 64-bit unsigned integers in the incoming CTX get casted
>> to a void pointer, and then implicitly converted to whatever type of
>> the actual argument in the wrapped function.  In this case:
>>
>>   Arg1: unsigned long long -> void * -> struct sock *
>>   Arg2: unsigned long long -> void * -> enum tcp_ca_event
>>
>> The behavior of GCC and clang when facing such conversions differ:
>>
>>   pointer -> pointer
>>
>>     Allowed by the C standard.
>>     GCC: no warning nor error.
>>     clang: no warning nor error.
>>
>>   pointer -> integer type
>>
>>     [C standard says the result of this conversion is implementation
>>      defined, and it may lead to unaligned pointer etc.]
>>
>>     GCC: error: integer from pointer without a cast [-Wint-conversion]
>>     clang: error: incompatible pointer to integer conversion [-Wint-conversion]
>>
>>   pointer -> enumerated type
>>
>>     GCC: error: incompatible types in assigment (*)
>>     clang: error: incompatible pointer to integer conversion [-Wint-conversion]
>>
>> These macros work because converting pointers to pointers is allowed,
>> and converting pointers to integers also works provided a suitable
>> integer type even if it is implementation defined, much like casting a
>> pointer to uintptr_t is guaranteed to work by the C standard.  The
>> conversion errors emitted by both compilers by default are silenced by
>> the pragmas.
>>
>> However, the GCC error marked with (*) above when assigning a pointer
>> to an enumerated value is not associated with the -Wint-conversion
>> warning, and it is not possible to turn it off.
>>
>> This is preventing building the BPF kernel selftests with GCC.
>>
>> This patch fixes this by avoiding intermediate casts to void*,
>> replaced with casts to `uintptr', which is an integer type capable of
>> safely store a BPF pointer, much like the standard uintptr_t.
>>
>> Tested in bpf-next master.
>> No regressions.
>>
>> Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
>> Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
>> Cc: david.faust@oracle.com
>> Cc: cupertino.miranda@oracle.com
>> ---
>>  tools/lib/bpf/bpf_tracing.h | 80 ++++++++++++++++++++-----------------
>>  1 file changed, 43 insertions(+), 37 deletions(-)
>>
>> diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
>> index 1c13f8e88833..1098505a89c7 100644
>> --- a/tools/lib/bpf/bpf_tracing.h
>> +++ b/tools/lib/bpf/bpf_tracing.h
>> @@ -4,6 +4,12 @@
>>
>>  #include "bpf_helpers.h"
>>
>> +/* The following integer unsigned type must be able to hold a pointer.
>> +   It is used in the macros below in order to avoid eventual casts
>> +   from pointers to enum values, since these are rejected by GCC.  */
>> +
>> +typedef unsigned long long uintptr;
>> +
>
> hold on, we didn't talk about adding new typedefs. This bpf_tracing.h
> header is included into tons of user code, so we should avoid adding
> extra global definitions and typedes. Please just use (unsigned long
> long) explicitly everywhere.

Ok.

> Also please check CI failures ([0]).
>
>   [0] https://github.com/kernel-patches/bpf/actions/runs/8846180836/job/24291582343

How weird.  This means something is going on in my local testing
environment.

> pw-bot: cr
>
>>  /* Scan the ARCH passed in from ARCH env variable (see Makefile) */
>>  #if defined(__TARGET_ARCH_x86)
>>         #define bpf_target_x86
>> @@ -523,9 +529,9 @@ struct pt_regs;
>>  #else
>>
>>  #define BPF_KPROBE_READ_RET_IP(ip, ctx)                                            \
>> -       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
>> +       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)PT_REGS_RET(ctx)); })
>>  #define BPF_KRETPROBE_READ_RET_IP(ip, ctx)                                 \
>> -       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
>> +       ({ bpf_probe_read_kernel(&(ip), sizeof(ip), (uintptr)(PT_REGS_FP(ctx) + sizeof(ip))); })
>
> these are passing pointers, please don't just do a blind find&replace
>
>>
>>  #endif
>>
>
> [...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-26 18:02   ` Jose E. Marchesi
@ 2024-04-28 19:03     ` Jose E. Marchesi
  2024-04-29 16:12       ` Andrii Nakryiko
  0 siblings, 1 reply; 7+ messages in thread
From: Jose E. Marchesi @ 2024-04-28 19:03 UTC (permalink / raw
  To: Andrii Nakryiko; +Cc: bpf, david.faust, cupertino.miranda


>> Also please check CI failures ([0]).
>>
>>   [0] https://github.com/kernel-patches/bpf/actions/runs/8846180836/job/24291582343
>
> How weird.  This means something is going on in my local testing
> environment.

Ok, I think I know what is going on: the CI failures had nothing to do
with the patch changes per-se, but with the fact the patch changes
bpf_tracing.h and a little problem in the build system.

If I change tools/lib/bpf/bpf_tracing.h in bpf-next master, then
execute:

 $ cd bpf-next/
 $ git clean -xf
 $ cd tools/testing/selftests/bpf/
 $ ./vmtest.sh -- ./test_progs

in tools/testing/sefltests/bpf, I get this:

  make[2]: *** No rule to make target '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpflibbpfbpf_helper_defs.h', needed by '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpf/include/bpf/libbpfbpf_helper_defs.h'.  Stop.


Same thing happens if I have a built tree and I do `make' in
tools/testing/selftests/bpf.

In tools/lib/bpf/Makefile there is:

  BPF_HELPER_DEFS	:= $(OUTPUT)bpf_helper_defs.h

which assumes OUTPUT always has a trailing slash, which seems to be a
common expectation for OUTPUT among all the Makefiles.

In tools/bpf/runqslower/Makefile we find:

  BPFTOOL_OUTPUT := $(OUTPUT)bpftool/
  DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)bootstrap/bpftool
  [...]
  $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OUTPUT)
	$(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) OUTPUT=$(BPFOBJ_OUTPUT) \
		    DESTDIR=$(BPFOBJ_OUTPUT) prefix= $(abspath $@) install_headers

which is ok because BPFTOOL_OUTPUT is defined with a trailing slash.

However in tools/testing/selftests/bpf/Makefile an explicit value for
BPFTOOL_OUTPUT is specified, that lacks a trailing slash:

  $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
	$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower	       \
		    OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
		    BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/		       \
		    BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf			       \
		    BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)		       \
		    EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'	       \
		    EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&			       \
		    cp $(RUNQSLOWER_OUTPUT)runqslower $@

This results in a malformed

  BPF_HELPER_DEFS	:= $(OUTPUT)bpf_helper_defs.h

in tools/lib/bpf/Makefile.

The patch below fixes this, but there are other many possible fixes
(like changing tools/bpf/runqslower/Makefile in order to pass
OUTPUT=$(BPFOBJ_OUTPUT)/, or changing tools/lib/bpf/Makefile to use
$(OUTPUT)/bpf_helper_defs.h) and I don't know which one you would
prefer.

Also, since the involved rules have not been changed recently, I am
wondering why this is being noted only now.  Is people using another
set-up/workflow that somehow doesn't trigger this?

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index ca8b73f7c774..665a5c1e9b8e 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -274,7 +274,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
 	$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower	       \
 		    OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
 		    BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/		       \
-		    BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf			       \
+		    BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf/			       \
 		    BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)		       \
 		    EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'	       \
 		    EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&			       \

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-28 19:03     ` Jose E. Marchesi
@ 2024-04-29 16:12       ` Andrii Nakryiko
  2024-04-30  8:20         ` Jose E. Marchesi
  0 siblings, 1 reply; 7+ messages in thread
From: Andrii Nakryiko @ 2024-04-29 16:12 UTC (permalink / raw
  To: Jose E. Marchesi; +Cc: bpf, david.faust, cupertino.miranda

On Sun, Apr 28, 2024 at 12:03 PM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> >> Also please check CI failures ([0]).
> >>
> >>   [0] https://github.com/kernel-patches/bpf/actions/runs/8846180836/job/24291582343
> >
> > How weird.  This means something is going on in my local testing
> > environment.
>
> Ok, I think I know what is going on: the CI failures had nothing to do
> with the patch changes per-se, but with the fact the patch changes
> bpf_tracing.h and a little problem in the build system.
>
> If I change tools/lib/bpf/bpf_tracing.h in bpf-next master, then
> execute:
>
>  $ cd bpf-next/
>  $ git clean -xf
>  $ cd tools/testing/selftests/bpf/
>  $ ./vmtest.sh -- ./test_progs
>
> in tools/testing/sefltests/bpf, I get this:
>
>   make[2]: *** No rule to make target '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpflibbpfbpf_helper_defs.h', needed by '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpf/include/bpf/libbpfbpf_helper_defs.h'.  Stop.
>
>
> Same thing happens if I have a built tree and I do `make' in
> tools/testing/selftests/bpf.
>
> In tools/lib/bpf/Makefile there is:
>
>   BPF_HELPER_DEFS       := $(OUTPUT)bpf_helper_defs.h
>
> which assumes OUTPUT always has a trailing slash, which seems to be a
> common expectation for OUTPUT among all the Makefiles.
>
> In tools/bpf/runqslower/Makefile we find:
>
>   BPFTOOL_OUTPUT := $(OUTPUT)bpftool/
>   DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)bootstrap/bpftool
>   [...]
>   $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OUTPUT)
>         $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) OUTPUT=$(BPFOBJ_OUTPUT) \
>                     DESTDIR=$(BPFOBJ_OUTPUT) prefix= $(abspath $@) install_headers
>
> which is ok because BPFTOOL_OUTPUT is defined with a trailing slash.
>
> However in tools/testing/selftests/bpf/Makefile an explicit value for
> BPFTOOL_OUTPUT is specified, that lacks a trailing slash:
>
>   $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
>         $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower            \
>                     OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
>                     BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/                  \
>                     BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf                          \
>                     BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)                \
>                     EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'               \
>                     EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&                          \
>                     cp $(RUNQSLOWER_OUTPUT)runqslower $@
>
> This results in a malformed
>
>   BPF_HELPER_DEFS       := $(OUTPUT)bpf_helper_defs.h
>
> in tools/lib/bpf/Makefile.
>
> The patch below fixes this, but there are other many possible fixes
> (like changing tools/bpf/runqslower/Makefile in order to pass
> OUTPUT=$(BPFOBJ_OUTPUT)/, or changing tools/lib/bpf/Makefile to use
> $(OUTPUT)/bpf_helper_defs.h) and I don't know which one you would
> prefer.
>
> Also, since the involved rules have not been changed recently, I am
> wondering why this is being noted only now.  Is people using another
> set-up/workflow that somehow doesn't trigger this?

Let's fix runqslower submake rule, yes, but I think it's irrelevant
here. Failures that CI caught were in samples/bpf
(samples/bpf/tracex2.bpf.c), while this is runqslower rule.

The reason you haven't caught it is because selftests/bpf/Makefile
doesn't build samples/bpf, but our BPF CI does have an extra step to
build samples/bpf.

>
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index ca8b73f7c774..665a5c1e9b8e 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -274,7 +274,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
>         $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower            \
>                     OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
>                     BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/                  \
> -                   BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf                          \
> +                   BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf/                         \
>                     BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)                \
>                     EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'               \
>                     EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&                          \

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h
  2024-04-29 16:12       ` Andrii Nakryiko
@ 2024-04-30  8:20         ` Jose E. Marchesi
  0 siblings, 0 replies; 7+ messages in thread
From: Jose E. Marchesi @ 2024-04-30  8:20 UTC (permalink / raw
  To: Andrii Nakryiko; +Cc: bpf, david.faust, cupertino.miranda


> On Sun, Apr 28, 2024 at 12:03 PM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> >> Also please check CI failures ([0]).
>> >>
>> >>   [0] https://github.com/kernel-patches/bpf/actions/runs/8846180836/job/24291582343
>> >
>> > How weird.  This means something is going on in my local testing
>> > environment.
>>
>> Ok, I think I know what is going on: the CI failures had nothing to do
>> with the patch changes per-se, but with the fact the patch changes
>> bpf_tracing.h and a little problem in the build system.
>>
>> If I change tools/lib/bpf/bpf_tracing.h in bpf-next master, then
>> execute:
>>
>>  $ cd bpf-next/
>>  $ git clean -xf
>>  $ cd tools/testing/selftests/bpf/
>>  $ ./vmtest.sh -- ./test_progs
>>
>> in tools/testing/sefltests/bpf, I get this:
>>
>>   make[2]: *** No rule to make target '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpflibbpfbpf_helper_defs.h', needed by '/home/jemarch/gnu/src/bpf-next/tools/testing/selftests/bpf/tools/build/libbpf/include/bpf/libbpfbpf_helper_defs.h'.  Stop.
>>
>>
>> Same thing happens if I have a built tree and I do `make' in
>> tools/testing/selftests/bpf.
>>
>> In tools/lib/bpf/Makefile there is:
>>
>>   BPF_HELPER_DEFS       := $(OUTPUT)bpf_helper_defs.h
>>
>> which assumes OUTPUT always has a trailing slash, which seems to be a
>> common expectation for OUTPUT among all the Makefiles.
>>
>> In tools/bpf/runqslower/Makefile we find:
>>
>>   BPFTOOL_OUTPUT := $(OUTPUT)bpftool/
>>   DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)bootstrap/bpftool
>>   [...]
>>   $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OUTPUT)
>>         $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) OUTPUT=$(BPFOBJ_OUTPUT) \
>>                     DESTDIR=$(BPFOBJ_OUTPUT) prefix= $(abspath $@) install_headers
>>
>> which is ok because BPFTOOL_OUTPUT is defined with a trailing slash.
>>
>> However in tools/testing/selftests/bpf/Makefile an explicit value for
>> BPFTOOL_OUTPUT is specified, that lacks a trailing slash:
>>
>>   $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
>>         $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower            \
>>                     OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
>>                     BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/                  \
>>                     BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf                          \
>>                     BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)                \
>>                     EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'               \
>>                     EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&                          \
>>                     cp $(RUNQSLOWER_OUTPUT)runqslower $@
>>
>> This results in a malformed
>>
>>   BPF_HELPER_DEFS       := $(OUTPUT)bpf_helper_defs.h
>>
>> in tools/lib/bpf/Makefile.
>>
>> The patch below fixes this, but there are other many possible fixes
>> (like changing tools/bpf/runqslower/Makefile in order to pass
>> OUTPUT=$(BPFOBJ_OUTPUT)/, or changing tools/lib/bpf/Makefile to use
>> $(OUTPUT)/bpf_helper_defs.h) and I don't know which one you would
>> prefer.
>>
>> Also, since the involved rules have not been changed recently, I am
>> wondering why this is being noted only now.  Is people using another
>> set-up/workflow that somehow doesn't trigger this?
>
> Let's fix runqslower submake rule, yes, but I think it's irrelevant
> here. Failures that CI caught were in samples/bpf
> (samples/bpf/tracex2.bpf.c), while this is runqslower rule.
>
> The reason you haven't caught it is because selftests/bpf/Makefile
> doesn't build samples/bpf, but our BPF CI does have an extra step to
> build samples/bpf.

Ok good to know.  Then we better start building it too as part of our
local testing.

Will look at what is going on there with this fix, and will also send a
separated patch for the Makefile.

Thanks.

>
>>
>> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
>> index ca8b73f7c774..665a5c1e9b8e 100644
>> --- a/tools/testing/selftests/bpf/Makefile
>> +++ b/tools/testing/selftests/bpf/Makefile
>> @@ -274,7 +274,7 @@ $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
>>         $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower            \
>>                     OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
>>                     BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/                  \
>> -                   BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf                          \
>> +                   BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf/                         \
>>                     BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR)                \
>>                     EXTRA_CFLAGS='-g $(OPT_FLAGS) $(SAN_CFLAGS)'               \
>>                     EXTRA_LDFLAGS='$(SAN_LDFLAGS)' &&                          \

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-04-30  8:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-26  9:22 [PATCH bpf-next] bpf: avoid casts from pointers to enums in bpf_tracing.h Jose E. Marchesi
2024-04-26 16:15 ` Andrii Nakryiko
2024-04-26 18:02   ` Jose E. Marchesi
2024-04-28 19:03     ` Jose E. Marchesi
2024-04-29 16:12       ` Andrii Nakryiko
2024-04-30  8:20         ` Jose E. Marchesi
2024-04-26 16:21 ` Alexei Starovoitov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.