mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc
@ 2026-09-28 23:14 Vineet Gupta
  2026-09-29  0:01 ` Ihor Solodrai
  2026-09-29  0:30 ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 4+ messages in thread
From: Vineet Gupta @ 2026-09-28 23:14 UTC (permalink / raw)
  To: bpf, andrii, ast, daniel
  Cc: eddyz87, memxor, martin.lau, song, yonghong.song, jolsa, emil,
	ihor.solodrai, linux-kernel, Vineet Gupta

test_progs-bpf_gcc fails to build:

  prog_tests/linked_externs.c:17:23: error: 'struct linked_arena' has no
      member named 'arena'

Several problems, all from bpf-gcc not supporting address_space(1).

First, the arena variables are declared with __arena, but that macro is
for pointers -- it marks the pointee address space. The one that carries
placement is __arena_global:

  #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) && !defined(BPF_ARENA_FORCE_ASM)
  #define __arena        __attribute__((address_space(1))) __attribute__((btf_type_tag("arena")))
  #define __arena_global __attribute__((address_space(1)))
  #else
  #define __arena        __attribute__((btf_type_tag("arena")))
  #define __arena_global SEC(".addr_space.1")
  #endif

__BPF_FEATURE_ADDR_SPACE_CAST is a clang predefine. Under clang the two
are interchangeable here, since address_space(1) both places the
variable and is what btf_type_tag would have described. Under bpf-gcc
__arena is only a BTF type tag, so the definitions land in .data, the
arena map gets no initial value, and is_skel_data() in bpftool does not
emit the typed arena member -- hence the build error. Note this is
distinct from skel->maps.arena, which comes from SEC(".maps") and is
always present.

The extern declarations need __arena_global too. Without a section, gcc
does not place an extern in any DATASEC, so it stays a free-floating
extern VAR rather than an entry of .addr_space.1. test_relink() only
walks that DATASEC:

    id = btf__find_by_name_kind(btf, sec_name, BTF_KIND_DATASEC);
    ...
        ASSERT_NEQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_EXTERN, "var_resolved");

so relink_arena would report OK under bpf-gcc whether or not the linker
resolved anything -- it would not be testing the allocated-section path
this test exists for.

Second, placement alone is not enough to run the test. Dereferencing an
arena global needs an addr_space_cast, which only clang emits:

  clang:                                  bpf-gcc:
    r1 = 0x0 ll                             r1 = 0x0 ll
    r1 = addr_space_cast(r1, 0x0, 0x1)      r2 = *(u64 *)(r1 + 0x0)
    r1 = *(u64 *)(r1 + 0x0)

so the verifier sees a scalar and rejects the program:

  4: (79) r2 = *(u64 *)(r1 +0)
  R1 invalid mem access 'scalar'

Guard the program bodies and skip the skeleton subtest, as
arena_atomics.c already does. The variables stay unconditional so the
arena is still populated and the skeleton still has its member. The
fallback bodies reference the externs without dereferencing them:
'used' is ignored on an extern, so an unreferenced one is dropped and
.addr_space.1 loses it again.

With this, bpf-gcc reports:

  #217/1   linked_externs/skel_arena:SKIP
  #217/2   linked_externs/relink_arena:OK
  #217/3   linked_externs/relink_maps:OK

with b_val present in .addr_space.1 as linkage=extern, same as clang, so
relink_arena covers the same path in both. clang still passes all three.

Fixes: 34354db1b148 ("selftests/bpf: Add linked_externs test for externs in allocated sections")
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---

v2:
- Declare the externs with __arena_global too. Without a section gcc
  keeps them out of the .addr_space.1 DATASEC, which is the only thing
  test_relink() inspects, so relink_arena could not fail under bpf-gcc
  regardless of the linker (bpf-ci).
- Link to v1: https://lore.kernel.org/bpf/20260928215110.3966357-1-vineet.gupta@linux.dev/
 .../selftests/bpf/prog_tests/linked_externs.c | 15 ++++++++++--
 .../selftests/bpf/progs/linked_arena1.c       | 24 +++++++++++++++++--
 .../selftests/bpf/progs/linked_arena2.c       |  8 +++++--
 3 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/linked_externs.c b/tools/testing/selftests/bpf/prog_tests/linked_externs.c
index 29358c82dc35..ff568f5cfc42 100644
--- a/tools/testing/selftests/bpf/prog_tests/linked_externs.c
+++ b/tools/testing/selftests/bpf/prog_tests/linked_externs.c
@@ -10,10 +10,20 @@ static void test_skel(void)
 	struct linked_arena *skel;
 	int err;
 
-	skel = linked_arena__open_and_load();
-	if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+	skel = linked_arena__open();
+	if (!ASSERT_OK_PTR(skel, "skel_open"))
 		return;
 
+	if (skel->data->skip_tests) {
+		printf("%s:SKIP: no addr_space_cast support in the BPF compiler\n", __func__);
+		test__skip();
+		goto cleanup;
+	}
+
+	err = linked_arena__load(skel);
+	if (!ASSERT_OK(err, "skel_load"))
+		goto cleanup;
+
 	ASSERT_EQ(skel->arena->a_val, 1, "a_val_init");
 	ASSERT_EQ(skel->arena->b_val, 2, "b_val_init");
 
@@ -28,6 +38,7 @@ static void test_skel(void)
 	ASSERT_EQ(skel->arena->a_val, 11, "a_val");
 	ASSERT_EQ(skel->arena->b_val, 22, "b_val");
 
+cleanup:
 	linked_arena__destroy(skel);
 }
 
diff --git a/tools/testing/selftests/bpf/progs/linked_arena1.c b/tools/testing/selftests/bpf/progs/linked_arena1.c
index 3e8788dec1d9..5027b4ac2887 100644
--- a/tools/testing/selftests/bpf/progs/linked_arena1.c
+++ b/tools/testing/selftests/bpf/progs/linked_arena1.c
@@ -10,13 +10,33 @@ struct {
 	__uint(max_entries, 1); /* number of pages */
 } arena SEC(".maps");
 
-long __arena a_val = 1;
-extern long __arena b_val; /* defined in linked_arena2.c */
+/*
+ * Dereferencing an arena global needs the compiler to emit an
+ * addr_space_cast, which only clang does. Keep the variables so the arena
+ * is still populated and the skeleton still has its arena member, but skip
+ * the test elsewhere.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+bool skip_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_tests = true;
+#endif
+
+long __arena_global a_val = 1;
+extern long __arena_global b_val; /* defined in linked_arena2.c */
 
 SEC("syscall")
 int sum1(void *ctx)
 {
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
 	return a_val + b_val;
+#else
+	/*
+	 * Reference the extern without dereferencing it, so that the relink
+	 * test still has an extern to resolve.
+	 */
+	return (long)&b_val;
+#endif
 }
 
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/linked_arena2.c b/tools/testing/selftests/bpf/progs/linked_arena2.c
index d0bcdf18a4b6..db37198854a3 100644
--- a/tools/testing/selftests/bpf/progs/linked_arena2.c
+++ b/tools/testing/selftests/bpf/progs/linked_arena2.c
@@ -4,15 +4,19 @@
 #include <bpf/bpf_helpers.h>
 #include "bpf_arena_common.h"
 
-long __arena b_val = 2;
-extern long __arena a_val; /* defined in linked_arena1.c */
+long __arena_global b_val = 2;
+extern long __arena_global a_val; /* defined in linked_arena1.c */
 
 SEC("syscall")
 int bump2(void *ctx)
 {
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
 	a_val += 10;
 	b_val += 20;
 	return a_val + b_val;
+#else /* see linked_arena1.c */
+	return (long)&a_val;
+#endif
 }
 
 char _license[] SEC("license") = "GPL";
-- 
2.53.0-Meta


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

* Re: [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc
  2026-09-28 23:14 [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc Vineet Gupta
@ 2026-09-29  0:01 ` Ihor Solodrai
  2026-09-29  0:26   ` Andrii Nakryiko
  2026-09-29  0:30 ` patchwork-bot+netdevbpf
  1 sibling, 1 reply; 4+ messages in thread
From: Ihor Solodrai @ 2026-09-29  0:01 UTC (permalink / raw)
  To: Vineet Gupta, bpf, andrii, ast, daniel
  Cc: eddyz87, memxor, martin.lau, song, yonghong.song, jolsa, emil,
	linux-kernel

On 2026-09-28 4:14 p.m., Vineet Gupta wrote:
> test_progs-bpf_gcc fails to build:
> 
>    prog_tests/linked_externs.c:17:23: error: 'struct linked_arena' has no
>        member named 'arena'
> 
> Several problems, all from bpf-gcc not supporting address_space(1).
> 
> First, the arena variables are declared with __arena, but that macro is
> for pointers -- it marks the pointee address space. The one that carries
> placement is __arena_global:
> 
>    #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) && !defined(BPF_ARENA_FORCE_ASM)
>    #define __arena        __attribute__((address_space(1))) __attribute__((btf_type_tag("arena")))
>    #define __arena_global __attribute__((address_space(1)))
>    #else
>    #define __arena        __attribute__((btf_type_tag("arena")))
>    #define __arena_global SEC(".addr_space.1")
>    #endif
> 
> __BPF_FEATURE_ADDR_SPACE_CAST is a clang predefine. Under clang the two
> are interchangeable here, since address_space(1) both places the
> variable and is what btf_type_tag would have described. Under bpf-gcc
> __arena is only a BTF type tag, so the definitions land in .data, the
> arena map gets no initial value, and is_skel_data() in bpftool does not
> emit the typed arena member -- hence the build error. Note this is
> distinct from skel->maps.arena, which comes from SEC(".maps") and is
> always present.
> 
> The extern declarations need __arena_global too. Without a section, gcc
> does not place an extern in any DATASEC, so it stays a free-floating
> extern VAR rather than an entry of .addr_space.1. test_relink() only
> walks that DATASEC:
> 
>      id = btf__find_by_name_kind(btf, sec_name, BTF_KIND_DATASEC);
>      ...
>          ASSERT_NEQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_EXTERN, "var_resolved");
> 
> so relink_arena would report OK under bpf-gcc whether or not the linker
> resolved anything -- it would not be testing the allocated-section path
> this test exists for.
> 
> Second, placement alone is not enough to run the test. Dereferencing an
> arena global needs an addr_space_cast, which only clang emits:
> 
>    clang:                                  bpf-gcc:
>      r1 = 0x0 ll                             r1 = 0x0 ll
>      r1 = addr_space_cast(r1, 0x0, 0x1)      r2 = *(u64 *)(r1 + 0x0)
>      r1 = *(u64 *)(r1 + 0x0)
> 
> so the verifier sees a scalar and rejects the program:
> 
>    4: (79) r2 = *(u64 *)(r1 +0)
>    R1 invalid mem access 'scalar'
> 
> Guard the program bodies and skip the skeleton subtest, as
> arena_atomics.c already does. The variables stay unconditional so the
> arena is still populated and the skeleton still has its member. The
> fallback bodies reference the externs without dereferencing them:
> 'used' is ignored on an extern, so an unreferenced one is dropped and
> .addr_space.1 loses it again.
> 
> With this, bpf-gcc reports:
> 
>    #217/1   linked_externs/skel_arena:SKIP
>    #217/2   linked_externs/relink_arena:OK
>    #217/3   linked_externs/relink_maps:OK
> 
> with b_val present in .addr_space.1 as linkage=extern, same as clang, so
> relink_arena covers the same path in both. clang still passes all three.
> 
> Fixes: 34354db1b148 ("selftests/bpf: Add linked_externs test for externs in allocated sections")
> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>

Tested-by: Ihor Solodrai <ihor.solodrai@linux.dev>

This fixes the current GCC BPF selftests build failure on CI:
https://github.com/kernel-patches/vmtest/actions/runs/36498905340/job/109187331070

nit: The commit message is kinda too long. If you'd like it to be read
by a human, try making it shorter :)

Thanks!

> [...]

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

* Re: [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc
  2026-09-29  0:01 ` Ihor Solodrai
@ 2026-09-29  0:26   ` Andrii Nakryiko
  0 siblings, 0 replies; 4+ messages in thread
From: Andrii Nakryiko @ 2026-09-29  0:26 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Vineet Gupta, bpf, andrii, ast, daniel, eddyz87, memxor,
	martin.lau, song, yonghong.song, jolsa, emil, linux-kernel

On Mon, Sep 28, 2026 at 5:01 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> On 2026-09-28 4:14 p.m., Vineet Gupta wrote:
> > test_progs-bpf_gcc fails to build:
> >
> >    prog_tests/linked_externs.c:17:23: error: 'struct linked_arena' has no
> >        member named 'arena'
> >
> > Several problems, all from bpf-gcc not supporting address_space(1).
> >
> > First, the arena variables are declared with __arena, but that macro is
> > for pointers -- it marks the pointee address space. The one that carries
> > placement is __arena_global:
> >
> >    #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) && !defined(BPF_ARENA_FORCE_ASM)
> >    #define __arena        __attribute__((address_space(1))) __attribute__((btf_type_tag("arena")))
> >    #define __arena_global __attribute__((address_space(1)))
> >    #else
> >    #define __arena        __attribute__((btf_type_tag("arena")))
> >    #define __arena_global SEC(".addr_space.1")
> >    #endif
> >
> > __BPF_FEATURE_ADDR_SPACE_CAST is a clang predefine. Under clang the two
> > are interchangeable here, since address_space(1) both places the
> > variable and is what btf_type_tag would have described. Under bpf-gcc
> > __arena is only a BTF type tag, so the definitions land in .data, the
> > arena map gets no initial value, and is_skel_data() in bpftool does not
> > emit the typed arena member -- hence the build error. Note this is
> > distinct from skel->maps.arena, which comes from SEC(".maps") and is
> > always present.
> >
> > The extern declarations need __arena_global too. Without a section, gcc
> > does not place an extern in any DATASEC, so it stays a free-floating
> > extern VAR rather than an entry of .addr_space.1. test_relink() only
> > walks that DATASEC:
> >
> >      id = btf__find_by_name_kind(btf, sec_name, BTF_KIND_DATASEC);
> >      ...
> >          ASSERT_NEQ(btf_var(t)->linkage, BTF_VAR_GLOBAL_EXTERN, "var_resolved");
> >
> > so relink_arena would report OK under bpf-gcc whether or not the linker
> > resolved anything -- it would not be testing the allocated-section path
> > this test exists for.
> >
> > Second, placement alone is not enough to run the test. Dereferencing an
> > arena global needs an addr_space_cast, which only clang emits:
> >
> >    clang:                                  bpf-gcc:
> >      r1 = 0x0 ll                             r1 = 0x0 ll
> >      r1 = addr_space_cast(r1, 0x0, 0x1)      r2 = *(u64 *)(r1 + 0x0)
> >      r1 = *(u64 *)(r1 + 0x0)
> >
> > so the verifier sees a scalar and rejects the program:
> >
> >    4: (79) r2 = *(u64 *)(r1 +0)
> >    R1 invalid mem access 'scalar'
> >
> > Guard the program bodies and skip the skeleton subtest, as
> > arena_atomics.c already does. The variables stay unconditional so the
> > arena is still populated and the skeleton still has its member. The
> > fallback bodies reference the externs without dereferencing them:
> > 'used' is ignored on an extern, so an unreferenced one is dropped and
> > .addr_space.1 loses it again.
> >
> > With this, bpf-gcc reports:
> >
> >    #217/1   linked_externs/skel_arena:SKIP
> >    #217/2   linked_externs/relink_arena:OK
> >    #217/3   linked_externs/relink_maps:OK
> >
> > with b_val present in .addr_space.1 as linkage=extern, same as clang, so
> > relink_arena covers the same path in both. clang still passes all three.
> >
> > Fixes: 34354db1b148 ("selftests/bpf: Add linked_externs test for externs in allocated sections")
> > Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
>
> Tested-by: Ihor Solodrai <ihor.solodrai@linux.dev>
>

thanks for the fix and testing, my bad with __arena_global and GCC-BPF
build failure. applied to bpf-next, one step closer to green CI!

> This fixes the current GCC BPF selftests build failure on CI:
> https://github.com/kernel-patches/vmtest/actions/runs/36498905340/job/109187331070
>
> nit: The commit message is kinda too long. If you'd like it to be read
> by a human, try making it shorter :)
>
> Thanks!
>
> > [...]

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

* Re: [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc
  2026-09-28 23:14 [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc Vineet Gupta
  2026-09-29  0:01 ` Ihor Solodrai
@ 2026-09-29  0:30 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-29  0:30 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: bpf, andrii, ast, daniel, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, linux-kernel

Hello:

This patch was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:

On Mon, 28 Sep 2026 16:14:41 -0700 you wrote:
> test_progs-bpf_gcc fails to build:
> 
>   prog_tests/linked_externs.c:17:23: error: 'struct linked_arena' has no
>       member named 'arena'
> 
> Several problems, all from bpf-gcc not supporting address_space(1).
> 
> [...]

Here is the summary with links:
  - [bpf-next,v2] selftests/bpf: Fix linked_externs with bpf-gcc
    https://git.kernel.org/bpf/bpf-next/c/61c1e63c9b65

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-09-29  0:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-28 23:14 [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc Vineet Gupta
2026-09-29  0:01 ` Ihor Solodrai
2026-09-29  0:26   ` Andrii Nakryiko
2026-09-29  0:30 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®