Skip to content

Commit

Permalink
elf_reader: permit multiple .data* sections
Browse files Browse the repository at this point in the history
Mirror libbpf behavior. Quoting the respective commit message[1]:

> Having the ability to use multiple .data sections and putting
> dedicated global variables into separate .data.custom section also
> opens up some new and interesting possibilities (like dynamically
> sizing global arrays, without using BPF_MAP_TYPE_ARRAY map).

[1] libbpf/libbpf#274

Another motivation for dedicated data sections is a more granular access
control, such as making a subset of variables BPF_F_RDONLY_PROG
(userspace can alter but BPF can't). Also note that verifier doesn't
prevent overflowing .data buffers into adjacent variables as long as the
write is within the backing array map bounds.

Signed-off-by: Nick Zavaritsky <mejedi@gmail.com>
  • Loading branch information
mejedi authored and ti-mo committed Aug 21, 2024
1 parent a31a756 commit 2435814
Show file tree
Hide file tree
Showing 10 changed files with 13 additions and 3 deletions.
2 changes: 1 addition & 1 deletion elf_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
sections[idx] = newElfSection(sec, mapSection)
case sec.Name == ".maps":
sections[idx] = newElfSection(sec, btfMapSection)
case sec.Name == ".bss" || sec.Name == ".data" || strings.HasPrefix(sec.Name, ".rodata"):
case sec.Name == ".bss" || strings.HasPrefix(sec.Name, ".data") || strings.HasPrefix(sec.Name, ".rodata"):
sections[idx] = newElfSection(sec, dataSection)
case sec.Type == elf.SHT_REL:
// Store relocations under the section index of the target
Expand Down
8 changes: 8 additions & 0 deletions elf_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ func TestLoadCollectionSpec(t *testing.T) {
ValueSize: 8,
MaxEntries: 1,
},
".data.custom": {
Name: SanitizeName(".data.custom", -1),
Type: Array,
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
Contents: []MapKV{{Key: uint32(0), Value: make([]uint8, 4)}},
},
},
Programs: map[string]*ProgramSpec{
"xdp_prog": {
Expand Down
2 changes: 1 addition & 1 deletion info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ func TestProgInfoExtBTF(t *testing.T) {
t.Fatal(err)
}

expectedLineInfoCount := 26
expectedLineInfoCount := 28
expectedFuncInfo := map[string]bool{
"xdp_prog": false,
"static_fn": false,
Expand Down
Binary file modified testdata/loader-clang-11-eb.elf
Binary file not shown.
Binary file modified testdata/loader-clang-11-el.elf
Binary file not shown.
Binary file modified testdata/loader-clang-14-eb.elf
Binary file not shown.
Binary file modified testdata/loader-clang-14-el.elf
Binary file not shown.
Binary file modified testdata/loader-clang-17-eb.elf
Binary file not shown.
Binary file modified testdata/loader-clang-17-el.elf
Binary file not shown.
4 changes: 3 additions & 1 deletion testdata/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,14 @@ volatile const unsigned int key3 = 2; // .rodata
static volatile const uint32_t arg; // .rodata, populated by loader
// custom .rodata section, populated by loader
static volatile const uint32_t arg2 __section(".rodata.test");
// custom .data section
static volatile uint32_t arg3 __section(".data.custom");

__section("xdp") int xdp_prog() {
map_lookup_elem(&hash_map, (void *)&key1);
map_lookup_elem(&hash_map2, (void *)&key2);
map_lookup_elem(&hash_map2, (void *)&key3);
return static_fn(arg) + global_fn(arg) + arg2;
return static_fn(arg) + global_fn(arg) + arg2 + arg3;
}

// This function has no relocations, and is thus parsed differently.
Expand Down

0 comments on commit 2435814

Please sign in to comment.