* [PATCH bpf-next v4 0/3] Normalize enum values in libbpf and bpftool
@ 2026-11-07 2:07 Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 1/3] libbpf: Normalize enum values according to signedness Hungyu Lin
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-07 2:07 UTC (permalink / raw)
To: ast, bpf
Cc: andrii, qmo, daniel, yonghong.song, eddyz87, ihor.solodrai,
shuah, linux-kselftest, linux-kernel, Hungyu Lin
This series fixes enum signedness in libbpf and bpftool data dumps
using the shared btf_enum_value() helper suggested by Alexei. It also
uses the helper for enum-backed map fields, where sign extension can
change the requested map_extra value.
Ordinary enums are interpreted according to kflag. When kflag is
clear, values are treated as unsigned, including BTF from producers
that did not record signedness.
The helper returns __u64, consistent with btf_enum64_value(). bpftool
casts to __s64 at signed numeric output. CO-RE relocation handling is
left for a separate change.
Changes in v4:
- Return __u64 from btf_enum_value(), as requested by Andrii.
- Rely on kflag for name matching; remove legacy comparisons and
bpftool's cached match and priority logic, as requested by Andrii.
- Remove the legacy and ambiguous narrow-alias test cases. Keep signed
controls, unsigned names, numeric output and width-boundary coverage.
- Add an open-only skeleton test for the map_extra parser.
- Drop four libbpf numeric-fallback cases that do not exercise this change.
- Rebase onto bpf-next commit 3e1821848412.
Tested on arm64 (Linux 6.12.68, GCC 13.3, Clang 18.1). libbpf and
bpftool build with -Werror. Without patches 1 and 2, 9 of the 18 new
subtests in btf_dump, bpftool_map_dump and map_extra fail. With the
series, all 18 pass; the 23 existing subtests pass in both cases.
v3: https://lore.kernel.org/bpf/20261101103221.51534-1-dennylin0707@gmail.com/
Thanks,
Hungyu
Hungyu Lin (3):
libbpf: Normalize enum values according to signedness
bpftool: Preserve unsigned enum values in data dumps
selftests/bpf: Cover enum signedness in data dumps and map fields
tools/bpf/bpftool/btf_dumper.c | 23 ++-
tools/lib/bpf/btf.h | 6 +
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 2 +-
.../bpf/prog_tests/bpftool_map_dump.c | 162 ++++++++++++++++++
.../selftests/bpf/prog_tests/btf_dump.c | 77 +++++++++
.../selftests/bpf/prog_tests/map_extra.c | 19 ++
.../selftests/bpf/progs/test_map_extra.c | 12 ++
8 files changed, 293 insertions(+), 10 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/map_extra.c
create mode 100644 tools/testing/selftests/bpf/progs/test_map_extra.c
base-commit: 3e18218484126afb9da722080659c038cb2256ab
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v4 1/3] libbpf: Normalize enum values according to signedness
2026-11-07 2:07 [PATCH bpf-next v4 0/3] Normalize enum values in libbpf and bpftool Hungyu Lin
@ 2026-11-07 2:07 ` Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 2/3] bpftool: Preserve unsigned enum values in data dumps Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 3/3] selftests/bpf: Cover enum signedness in data dumps and map fields Hungyu Lin
2 siblings, 0 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-07 2:07 UTC (permalink / raw)
To: ast, bpf
Cc: andrii, qmo, daniel, yonghong.song, eddyz87, ihor.solodrai,
shuah, linux-kselftest, linux-kernel, Hungyu Lin
BTF_KIND_ENUM stores enumerators in a signed 32-bit field even for
unsigned enums. btf_dump_enum_data() compares unsigned data against that
signed field, so values with bit 31 set fail to match their names.
get_map_field_long() also sign-extends the field: for example,
__ulong(map_extra, 0x80000000) becomes 0xffffffff80000000 instead of the
requested arena mapping address.
Add btf_enum_value() to extend an enumerator according to kflag and use
it for data-name matching and enum-backed map fields. Return __u64,
consistent with btf_enum64_value(), while sign-extending signed values.
Fixes: d90ec262b35b ("libbpf: Add enum64 support for btf_dump")
Fixes: d147357e2e59 ("libbpf: Allow specifying 64-bit integers in map BTF.")
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/DMJG1R2YIJRK.16CZLV9S5U7Z7@gmail.com/
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
---
Changes in v4:
- Return __u64 from the shared helper and compare normalized values.
- Drop the legacy comparison and rely on kflag, as requested by Andrii.
tools/lib/bpf/btf.h | 6 ++++++
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 57f12630c5d1..d74c92056f0f 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -636,6 +636,12 @@ static inline struct btf_enum *btf_enum(const struct btf_type *t)
return (struct btf_enum *)(t + 1);
}
+/* btf_enum->val is signed even for unsigned enums; kflag records the sign. */
+static inline __u64 btf_enum_value(const struct btf_type *t, const struct btf_enum *e)
+{
+ return btf_kflag(t) ? (__s64)e->val : (__u32)e->val;
+}
+
struct btf_enum64;
static inline struct btf_enum64 *btf_enum64(const struct btf_type *t)
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index fcd97aa90589..602664a6adef 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -2378,7 +2378,7 @@ static int btf_dump_enum_data(struct btf_dump *d,
const struct btf_enum *e;
for (i = 0, e = btf_enum(t); i < btf_vlen(t); i++, e++) {
- if (value != e->val)
+ if ((__u64)value != btf_enum_value(t, e))
continue;
btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off));
return 0;
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0e2a93a42908..44134421bd7d 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2650,7 +2650,7 @@ static bool get_map_field_long(const char *map_name, const struct btf *btf,
if (btf_is_enum(t)) {
const struct btf_enum *e = btf_enum(t);
- *res = e->val;
+ *res = btf_enum_value(t, e);
} else {
const struct btf_enum64 *e = btf_enum64(t);
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v4 2/3] bpftool: Preserve unsigned enum values in data dumps
2026-11-07 2:07 [PATCH bpf-next v4 0/3] Normalize enum values in libbpf and bpftool Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 1/3] libbpf: Normalize enum values according to signedness Hungyu Lin
@ 2026-11-07 2:07 ` Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 3/3] selftests/bpf: Cover enum signedness in data dumps and map fields Hungyu Lin
2 siblings, 0 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-07 2:07 UTC (permalink / raw)
To: ast, bpf
Cc: andrii, qmo, daniel, yonghong.song, eddyz87, ihor.solodrai,
shuah, linux-kselftest, linux-kernel, Hungyu Lin
btf_dumper_enum() loads ordinary enum data as signed and uses signed
numeric output. Unsigned values with the high bit set can therefore be
printed as negative numbers. Narrow unsigned values also fail to match
their enumerators: an eight-bit 0xff is loaded as -1, while its named
value is stored as 255.
btf_dumper_enum64() likewise uses signed numeric output for unmatched
values. For example, 0x8000000000000001 is printed as
-9223372036854775807 instead of 9223372036854775809.
Load ordinary enum data according to kflag and use btf_enum_value() for
name matching. Select the numeric writer according to kflag for both
enum kinds, casting the value to __s64 for signed output.
Fixes: ca7e6e45d108 ("bpftool: Print the enum's name instead of value")
Fixes: 58a53978fdf6 ("bpftool: Add btf enum64 support")
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Quentin Monnet <qmo@kernel.org>
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
---
Changes in v4:
- Keep the normalized value unsigned; cast explicitly for signed output.
- Remove the signed-width compatibility comparison and match-priority
logic, as requested by Andrii.
tools/bpf/bpftool/btf_dumper.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index 3267163119dc..a7171622ce57 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -149,28 +149,29 @@ static int btf_dumper_enum(const struct btf_dumper *d,
const void *data)
{
const struct btf_enum *enums = btf_enum(t);
- __s64 value;
+ bool is_signed = btf_kflag(t);
+ __u64 value;
__u32 i;
switch (t->size) {
case 8:
- value = *(__s64 *)data;
+ value = *(__u64 *)data;
break;
case 4:
- value = *(__s32 *)data;
+ value = is_signed ? (__s64)*(__s32 *)data : *(__u32 *)data;
break;
case 2:
- value = *(__s16 *)data;
+ value = is_signed ? *(__s16 *)data : *(__u16 *)data;
break;
case 1:
- value = *(__s8 *)data;
+ value = is_signed ? *(__s8 *)data : *(__u8 *)data;
break;
default:
return -EINVAL;
}
for (i = 0; i < btf_vlen(t); i++) {
- if (value == enums[i].val) {
+ if (value == btf_enum_value(t, &enums[i])) {
jsonw_string(d->jw,
btf__name_by_offset(d->btf,
enums[i].name_off));
@@ -178,7 +179,10 @@ static int btf_dumper_enum(const struct btf_dumper *d,
}
}
- jsonw_int(d->jw, value);
+ if (is_signed)
+ jsonw_int(d->jw, (__s64)value);
+ else
+ jsonw_uint(d->jw, value);
return 0;
}
@@ -204,7 +208,10 @@ static int btf_dumper_enum64(const struct btf_dumper *d,
}
}
- jsonw_int(d->jw, value);
+ if (btf_kflag(t))
+ jsonw_int(d->jw, (__s64)value);
+ else
+ jsonw_uint(d->jw, value);
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v4 3/3] selftests/bpf: Cover enum signedness in data dumps and map fields
2026-11-07 2:07 [PATCH bpf-next v4 0/3] Normalize enum values in libbpf and bpftool Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 1/3] libbpf: Normalize enum values according to signedness Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 2/3] bpftool: Preserve unsigned enum values in data dumps Hungyu Lin
@ 2026-11-07 2:07 ` Hungyu Lin
2 siblings, 0 replies; 4+ messages in thread
From: Hungyu Lin @ 2026-11-07 2:07 UTC (permalink / raw)
To: ast, bpf
Cc: andrii, qmo, daniel, yonghong.song, eddyz87, ihor.solodrai,
shuah, linux-kselftest, linux-kernel, Hungyu Lin
Exercise unsigned enum values with their high bit set and signed
controls through libbpf's data dumper. Include ordinary enums stored in
eight bytes and check that wider data cannot match an enumerator only
through its low 32 bits.
Extend bpftool_map_dump with BTF-backed array maps and check both JSON
and plain output. Cover narrow unsigned names, signed and unsigned
numeric output, wider ordinary enums and unmatched ENUM64 values.
Initialize map data at its actual width so the stored bytes match the
value width on big-endian hosts.
Also use an open-only arena skeleton to check an enum-backed map_extra
value with bit 31 set. The object is not loaded into the kernel, so the
test needs neither arena support nor mmap.
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Quentin Monnet <qmo@kernel.org>
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
---
Changes in v4:
- Remove legacy-name and ambiguous narrow-alias cases, following the
decision to rely on kflag.
- Add an open-only skeleton test for the map_extra parser.
- Remove four unrelated libbpf numeric-fallback cases.
.../bpf/prog_tests/bpftool_map_dump.c | 162 ++++++++++++++++++
.../selftests/bpf/prog_tests/btf_dump.c | 77 +++++++++
| 19 ++
| 12 ++
4 files changed, 270 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/map_extra.c
create mode 100644 tools/testing/selftests/bpf/progs/test_map_extra.c
diff --git a/tools/testing/selftests/bpf/prog_tests/bpftool_map_dump.c b/tools/testing/selftests/bpf/prog_tests/bpftool_map_dump.c
index 187b3f784307..8002c24d02de 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpftool_map_dump.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpftool_map_dump.c
@@ -7,6 +7,7 @@
#define PIN_PATH "/sys/fs/bpf/test_bpftool_map_dump_sk_storage"
#define QUEUE_PIN_PATH "/sys/fs/bpf/test_bpftool_map_dump_queue"
+#define ENUM_PIN_PATH "/sys/fs/bpf/test_bpftool_map_dump_enum"
#define JSON_ERROR "{\"error\":\"can't dump sk_storage map"
/* An empty socket storage map with an int value. */
@@ -124,10 +125,171 @@ static void test_queue(void)
close(map_fd);
}
+enum enum_dump_kind {
+ DUMP_ENUM_UNSIGNED,
+ DUMP_ENUM_SIGNED,
+ DUMP_ENUM64_UNSIGNED,
+ DUMP_ENUM64_SIGNED,
+};
+
+struct enum_dump_test {
+ const char *name;
+ enum enum_dump_kind kind;
+ __u32 size;
+ __u64 value;
+ const char *expected;
+};
+
+static const struct enum_dump_test enum_dump_tests[] = {
+ { "enum_u8_name", DUMP_ENUM_UNSIGNED, 1, 0xff, "\"MAX\"" },
+ { "enum_u8_unknown", DUMP_ENUM_UNSIGNED, 1, (__u64)-22, "234" },
+ { "enum_u16_name", DUMP_ENUM_UNSIGNED, 2, 0xffff, "\"MAX\"" },
+ { "enum_u16_unknown", DUMP_ENUM_UNSIGNED, 2, (__u64)-22, "65514" },
+ { "enum_u32_high", DUMP_ENUM_UNSIGNED, 4, 0x80000000, "\"HIGH\"" },
+ { "enum_u32_max", DUMP_ENUM_UNSIGNED, 4, 0xffffffff, "\"MAX\"" },
+ { "enum_u32_unknown", DUMP_ENUM_UNSIGNED, 4, (__u64)-22, "4294967274" },
+ { "enum_s8_name", DUMP_ENUM_SIGNED, 1, (__u64)-1, "\"NEG\"" },
+ { "enum_s8_unknown", DUMP_ENUM_SIGNED, 1, (__u64)-22, "-22" },
+ { "enum_s16_name", DUMP_ENUM_SIGNED, 2, (__u64)-1, "\"NEG\"" },
+ { "enum_s32_name", DUMP_ENUM_SIGNED, 4, (__u64)-1, "\"NEG\"" },
+ { "enum_s32_unknown", DUMP_ENUM_SIGNED, 4, (__u64)-22, "-22" },
+ { "enum_wide_name", DUMP_ENUM_UNSIGNED, 8, 0xffffffff, "\"MAX\"" },
+ { "enum_wide_unknown", DUMP_ENUM_UNSIGNED, 8, 0x1ffffffffULL, "8589934591" },
+ { "enum64_unsigned", DUMP_ENUM64_UNSIGNED, 8, (1ULL << 63) | 1,
+ "9223372036854775809" },
+ { "enum64_signed", DUMP_ENUM64_SIGNED, 8, (__u64)-22, "-22" },
+};
+
+static int add_enum_dump_values(struct btf *btf, const struct enum_dump_test *test)
+{
+ __u64 max = test->size == 1 ? 0xff : test->size == 2 ? 0xffff : 0xffffffff;
+ int err;
+
+ switch (test->kind) {
+ case DUMP_ENUM_UNSIGNED:
+ err = btf__add_enum_value(btf, "HIGH", (max >> 1) + 1);
+ return err ?: btf__add_enum_value(btf, "MAX", max);
+ case DUMP_ENUM_SIGNED:
+ return btf__add_enum_value(btf, "NEG", -1);
+ case DUMP_ENUM64_UNSIGNED:
+ err = btf__add_enum64_value(btf, "HIGH", 1ULL << 63);
+ return err ?: btf__add_enum64_value(btf, "LOW", 1);
+ case DUMP_ENUM64_SIGNED:
+ return btf__add_enum64_value(btf, "NEG", (__u64)-1);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int create_enum_dump_map(const struct enum_dump_test *test)
+{
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+ bool enum64 = test->kind == DUMP_ENUM64_UNSIGNED ||
+ test->kind == DUMP_ENUM64_SIGNED;
+ struct btf *btf;
+ int key_id, value_id, fd = -1;
+
+ btf = btf__new_empty();
+ if (!ASSERT_OK_PTR(btf, "btf__new_empty"))
+ return -1;
+
+ key_id = btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
+ if (!ASSERT_GT(key_id, 0, "btf__add_int"))
+ goto out;
+ if (enum64)
+ value_id = btf__add_enum64(btf, "enum_value", test->size,
+ test->kind == DUMP_ENUM64_SIGNED);
+ else
+ value_id = btf__add_enum(btf, "enum_value", test->size);
+ if (!ASSERT_GT(value_id, 0, "add enum"))
+ goto out;
+ if (!ASSERT_OK(add_enum_dump_values(btf, test), "add enum values"))
+ goto out;
+ if (!ASSERT_OK(btf__load_into_kernel(btf), "btf__load_into_kernel"))
+ goto out;
+
+ opts.btf_fd = btf__fd(btf);
+ opts.btf_key_type_id = key_id;
+ opts.btf_value_type_id = value_id;
+ fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "enum_dump", sizeof(__u32),
+ test->size, 1, &opts);
+ ASSERT_OK_FD(fd, "bpf_map_create");
+out:
+ btf__free(btf);
+ return fd;
+}
+
+static void test_enum_dump(const struct enum_dump_test *test)
+{
+ union {
+ __u8 val8;
+ __u16 val16;
+ __u32 val32;
+ __u64 val64;
+ } value;
+ char output[1024] = {}, expected[128];
+ __u32 key = 0;
+ int map_fd, ret;
+
+ /* Store the value at its native width, including on big-endian hosts. */
+ switch (test->size) {
+ case 1:
+ value.val8 = (__u8)test->value;
+ break;
+ case 2:
+ value.val16 = (__u16)test->value;
+ break;
+ case 4:
+ value.val32 = (__u32)test->value;
+ break;
+ case 8:
+ value.val64 = test->value;
+ break;
+ default:
+ PRINT_FAIL("unexpected enum size %u (expected 1, 2, 4 or 8)\n", test->size);
+ return;
+ }
+
+ map_fd = create_enum_dump_map(test);
+ if (map_fd < 0)
+ return;
+ if (!ASSERT_OK(bpf_map_update_elem(map_fd, &key, &value, BPF_ANY),
+ "update enum value"))
+ goto out;
+ if (!ASSERT_OK(bpf_obj_pin(map_fd, ENUM_PIN_PATH), "pin enum map"))
+ goto out;
+
+ ret = get_bpftool_command_output("-j map dump pinned " ENUM_PIN_PATH,
+ output, sizeof(output));
+ if (!ASSERT_OK(ret, "json enum dump"))
+ goto out;
+ snprintf(expected, sizeof(expected), "\"formatted\":{\"key\":0,\"value\":%s}",
+ test->expected);
+ ASSERT_HAS_SUBSTR(output, expected, "json enum value");
+
+ memset(output, 0, sizeof(output));
+ ret = get_bpftool_command_output("map dump pinned " ENUM_PIN_PATH,
+ output, sizeof(output));
+ if (!ASSERT_OK(ret, "plain enum dump"))
+ goto out;
+ snprintf(expected, sizeof(expected), "\"value\": %s\n", test->expected);
+ ASSERT_HAS_SUBSTR(output, expected, "plain enum value");
+out:
+ unlink(ENUM_PIN_PATH);
+ close(map_fd);
+}
+
void test_bpftool_map_dump(void)
{
+ size_t i;
+
if (test__start_subtest("sk_storage"))
test_sk_storage();
if (test__start_subtest("queue"))
test_queue();
+
+ for (i = 0; i < ARRAY_SIZE(enum_dump_tests); i++) {
+ if (test__start_subtest(enum_dump_tests[i].name))
+ test_enum_dump(&enum_dump_tests[i]);
+ }
}
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_dump.c b/tools/testing/selftests/bpf/prog_tests/btf_dump.c
index bfa74db17987..b2af060fe5b5 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_dump.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_dump.c
@@ -977,6 +977,80 @@ static void test_btf_dump_enum_data(struct btf *btf, struct btf_dump *d,
sizeof(enum bpf_cmd) - 1, "", BPF_MAP_CREATE);
}
+static void test_btf_dump_enum_values(void)
+{
+ LIBBPF_OPTS(btf_dump_type_data_opts, opts,
+ .compact = true,
+ .skip_names = true);
+ struct {
+ const char *name;
+ __u32 size;
+ __s64 enum_value;
+ union {
+ __u8 u8;
+ __u16 u16;
+ __u32 u32;
+ __u64 u64;
+ } data;
+ const char *expected;
+ } cases[] = {
+ { "unsigned_byte", 1, 0xff, { .u8 = 0xff }, "VALUE" },
+ { "unsigned_short", 2, 0xffff, { .u16 = 0xffff }, "VALUE" },
+ { "unsigned_high", 4, 0x80000000LL,
+ { .u32 = 0x80000000U }, "VALUE" },
+ { "unsigned_max", 4, 0xffffffffLL,
+ { .u32 = 0xffffffffU }, "VALUE" },
+ { "signed_value", 4, -1, { .u32 = (__u32)-1 }, "VALUE" },
+ { "unsigned_wide", 8, 0xffffffffLL,
+ { .u64 = 0xffffffffULL }, "VALUE" },
+ /*
+ * Wider data must not match an enumerator through its low 32 bits.
+ * Check numeric output without requiring an exact value.
+ */
+ { "wide_unknown", 8, 0xffffffffLL,
+ { .u64 = 0x1ffffffffULL }, NULL },
+ };
+ struct btf_dump *d;
+ struct btf *btf;
+ int ids[ARRAY_SIZE(cases)];
+ char str[STRSIZE];
+ int err, i;
+
+ btf = btf__new_empty();
+ if (!ASSERT_OK_PTR(btf, "new_empty"))
+ return;
+ for (i = 0; i < ARRAY_SIZE(cases); i++) {
+ ids[i] = btf__add_enum(btf, cases[i].name, cases[i].size);
+ if (!ASSERT_GT(ids[i], 0, "add_enum"))
+ goto free_btf;
+ err = btf__add_enum_value(btf, "VALUE", cases[i].enum_value);
+ if (!ASSERT_OK(err, "add_enum_value"))
+ goto free_btf;
+ }
+
+ d = btf_dump__new(btf, btf_dump_snprintf, str, NULL);
+ if (!ASSERT_OK_PTR(d, "btf_dump__new"))
+ goto free_btf;
+
+ for (i = 0; i < ARRAY_SIZE(cases); i++) {
+ str[0] = '\0';
+ err = btf_dump__dump_type_data(d, ids[i], &cases[i].data,
+ cases[i].size, &opts);
+ ASSERT_EQ(err, cases[i].size, cases[i].name);
+ if (cases[i].expected) {
+ ASSERT_STREQ(str, cases[i].expected, cases[i].name);
+ } else {
+ ASSERT_NEQ(str[0], '\0', cases[i].name);
+ ASSERT_EQ(strspn(str, "0123456789"), strlen(str),
+ cases[i].name);
+ }
+ }
+
+ btf_dump__free(d);
+free_btf:
+ btf__free(btf);
+}
+
static void test_btf_dump_struct_data(struct btf *btf, struct btf_dump *d,
char *str)
{
@@ -1421,6 +1495,9 @@ void test_btf_dump() {
if (test__start_subtest("btf_dump: type_tags"))
test_btf_dump_type_tags();
+ if (test__start_subtest("btf_dump: enum_values"))
+ test_btf_dump_enum_values();
+
btf = libbpf_find_kernel_btf();
if (!ASSERT_OK_PTR(btf, "no kernel BTF found"))
return;
--git a/tools/testing/selftests/bpf/prog_tests/map_extra.c b/tools/testing/selftests/bpf/prog_tests/map_extra.c
new file mode 100644
index 000000000000..cbb1881ba693
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/map_extra.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include "test_map_extra.skel.h"
+
+void test_map_extra(void)
+{
+ struct test_map_extra *skel;
+
+ if (!test__start_subtest("enum32_high"))
+ return;
+
+ skel = test_map_extra__open();
+ if (!ASSERT_OK_PTR(skel, "test_map_extra__open"))
+ return;
+
+ ASSERT_EQ(bpf_map__map_extra(skel->maps.arena), 0x80000000ULL,
+ "map_extra");
+ test_map_extra__destroy(skel);
+}
--git a/tools/testing/selftests/bpf/progs/test_map_extra.c b/tools/testing/selftests/bpf/progs/test_map_extra.c
new file mode 100644
index 000000000000..b6aa2341c115
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_map_extra.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARENA);
+ __uint(map_flags, BPF_F_MMAPABLE);
+ __uint(max_entries, 1);
+ __ulong(map_extra, 0x80000000U);
+} arena SEC(".maps");
+
+char LICENSE[] SEC("license") = "GPL";
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-07 2:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-07 2:07 [PATCH bpf-next v4 0/3] Normalize enum values in libbpf and bpftool Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 1/3] libbpf: Normalize enum values according to signedness Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 2/3] bpftool: Preserve unsigned enum values in data dumps Hungyu Lin
2026-11-07 2:07 ` [PATCH bpf-next v4 3/3] selftests/bpf: Cover enum signedness in data dumps and map fields Hungyu Lin
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®