Skip to content

Commit b41dc72

Browse files
committed
elf_reader: support value BTF on ringbuf and perf array maps
While reviewing cilium#1610, I noticed we were generating VariableSpecs for variables named 'unused' in our examples. There had to be a better way to get their BTF info into the ELF. I thoroughly checked all map types present in Linux 6.12 for any validation code on attr->value_size, and only RingBuf and Arena maps require value_size to be zero at all times. Special-case PerfEventArray so type annotations aren't limited to 4 bytes. Signed-off-by: Timo Beckers <[email protected]>
1 parent 0a77f25 commit b41dc72

10 files changed

+31
-0
lines changed

elf_reader.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,13 @@ func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *b
10131013
}
10141014
}
10151015

1016+
// Some maps don't support value sizes, but annotating their map definitions
1017+
// with __type macros can still be useful, especially to let bpf2go generate
1018+
// type definitions for them.
1019+
if value != nil && !mapType.canHaveValueSize() {
1020+
valueSize = 0
1021+
}
1022+
10161023
return &MapSpec{
10171024
Name: SanitizeName(name, -1),
10181025
Type: MapType(mapType),

elf_reader_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ func TestLoadCollectionSpec(t *testing.T) {
247247
}
248248
qt.Assert(t, qt.ContentEquals(mErr.Constants, []string{"totallyBogus", "totallyBogus2"}))
249249

250+
qt.Assert(t, qt.Equals(have.Maps["perf_event_array"].ValueSize, 0))
251+
qt.Assert(t, qt.IsNotNil(have.Maps["perf_event_array"].Value))
252+
250253
if diff := cmp.Diff(coll, have, cmpOpts...); diff != "" {
251254
t.Errorf("MapSpec mismatch (-want +got):\n%s", diff)
252255
}

testdata/loader-clang-11-eb.elf

88 Bytes
Binary file not shown.

testdata/loader-clang-11-el.elf

88 Bytes
Binary file not shown.

testdata/loader-clang-14-eb.elf

88 Bytes
Binary file not shown.

testdata/loader-clang-14-el.elf

88 Bytes
Binary file not shown.

testdata/loader-clang-17-eb.elf

88 Bytes
Binary file not shown.

testdata/loader-clang-17-el.elf

88 Bytes
Binary file not shown.

testdata/loader.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,15 @@ struct {
5858
});
5959
} btf_outer_map_anon __section(".maps");
6060

61+
struct perf_event {
62+
uint64_t foo;
63+
uint64_t bar;
64+
};
65+
6166
struct {
6267
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
6368
__uint(max_entries, 4096);
69+
__type(value, struct perf_event);
6470
} perf_event_array __section(".maps");
6571

6672
struct bpf_map_def array_of_hash_map __section("maps") = {

types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,21 @@ func (mt MapType) canStoreProgram() bool {
127127
return mt == ProgramArray
128128
}
129129

130+
// canHaveValueSize returns true if the map type supports setting a value size.
131+
func (mt MapType) canHaveValueSize() bool {
132+
switch mt {
133+
case RingBuf, Arena:
134+
return false
135+
136+
// Special-case perf events since they require a value size of either 0 or 4
137+
// for historical reasons. Let the library fix this up later.
138+
case PerfEventArray:
139+
return false
140+
}
141+
142+
return true
143+
}
144+
130145
// ProgramType of the eBPF program
131146
type ProgramType uint32
132147

0 commit comments

Comments
 (0)