From: Vineet Gupta <vineet.gupta@linux.dev>
To: bpf@vger.kernel.org, andrii@kernel.org, ast@kernel.org,
daniel@iogearbox.net
Cc: eddyz87@gmail.com, memxor@gmail.com, martin.lau@linux.dev,
song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org,
emil@etsalapatis.com, ihor.solodrai@linux.dev,
linux-kernel@vger.kernel.org,
Vineet Gupta <vineet.gupta@linux.dev>
Subject: [PATCH bpf-next v2] selftests/bpf: Fix linked_externs with bpf-gcc
Date: Mon, 28 Sep 2026 16:14:41 -0700 [thread overview]
Message-ID: <20260928231441.4037097-1-vineet.gupta@linux.dev> (raw)
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
next reply other threads:[~2026-09-28 23:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 23:14 Vineet Gupta [this message]
2026-09-29 0:01 ` Ihor Solodrai
2026-09-29 0:26 ` Andrii Nakryiko
2026-09-29 0:30 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928231441.4037097-1-vineet.gupta@linux.dev \
--to=vineet.gupta@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®