Skip to content

Commit

Permalink
elf_reader: Allow strings read-only global data sections
Browse files Browse the repository at this point in the history
In the past we had the limitation that string sections like
`.rodata.str1.1` could not not be loaded since clang/LLVM doesn't
provide BTF information for such sections. In cilium#675 we lifted the
requirement to have BTF information for global data sections. This means
that we can now also allow string sections to be loaded as global data.

All facilities to do so are already in place, this commit just removes
the check for references to sections with the `SHF_STRINGS` flag set.

Fixes: cilium#741
Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
  • Loading branch information
dylandreimerink committed Jul 21, 2022
1 parent 7b6e73d commit 8cb233e
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 16 deletions.
4 changes: 0 additions & 4 deletions elf_reader.go
Expand Up @@ -261,10 +261,6 @@ func (ec *elfCode) loadRelocations(relSections map[elf.SectionIndex]*elf.Section
return fmt.Errorf("section %q: reference to %q in section %s: %w", section.Name, rel.Name, rel.Section, ErrNotSupported)
}

if target.Flags&elf.SHF_STRINGS > 0 {
return fmt.Errorf("section %q: string is not stack allocated: %w", section.Name, ErrNotSupported)
}

target.references++
}

Expand Down
63 changes: 57 additions & 6 deletions elf_reader_test.go
Expand Up @@ -422,13 +422,64 @@ func TestLoadInvalidInitializedBTFMap(t *testing.T) {
}

func TestStringSection(t *testing.T) {
testutils.Files(t, testutils.Glob(t, "testdata/strings-*.elf"), func(t *testing.T, file string) {
_, err := LoadCollectionSpec(file)
t.Log(err)
if !errors.Is(err, ErrNotSupported) {
t.Error("References to a string section should be unsupported")
}
file := fmt.Sprintf("testdata/strings-%s.elf", internal.ClangEndian)
spec, err := LoadCollectionSpec(file)
if err != nil {
t.Fatalf("load collection spec: %s", err)
}

for name := range spec.Maps {
t.Log(name)
}

strMap := spec.Maps[".rodata.str1.1"]
if strMap == nil {
t.Fatal("Unable to find map '.rodata.str1.1' in loaded collection")
}

if !strMap.Freeze {
t.Fatal("Read only data maps should be frozen")
}

if strMap.Flags != unix.BPF_F_RDONLY_PROG {
t.Fatal("Read only data maps should have the prog-read-only flag set")
}

coll, err := NewCollection(spec)
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatalf("new collection: %s", err)
}

prog := coll.Programs["filter"]
if prog == nil {
t.Fatal("program not found")
}

testMap := coll.Maps["my_map"]
if testMap == nil {
t.Fatal("test map not found")
}

const runCount = 3

_, err = prog.Run(&RunOptions{
Data: make([]byte, 14), // Min size for XDP programs
Repeat: runCount,
})
if err != nil {
t.Fatalf("prog run: %s", err)
}

key := []byte("This string is allocated in the string section\n\x00")
var value uint32
if err = testMap.Lookup(&key, &value); err != nil {
t.Fatalf("test map lookup: %s", err)
}

if value != runCount {
t.Fatal("Test map value not equal to run count!")
}
}

func TestLoadRawTracepoint(t *testing.T) {
Expand Down
Binary file modified testdata/strings-eb.elf
Binary file not shown.
Binary file modified testdata/strings-el.elf
Binary file not shown.
29 changes: 23 additions & 6 deletions testdata/strings.c
Expand Up @@ -2,11 +2,28 @@

char __license[] __section("license") = "MIT";

#define STR1 "This string is allocated in the string section\n"
#define STR2 "This one too\n"
typedef char custkey[48];

__section("socket") int filter() {
trace_printk(STR1, sizeof(STR1));
trace_printk(STR2, sizeof(STR2));
return 0;
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 2);
__type(key, custkey);
__type(value, uint32_t);
} my_map __section(".maps");

static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *)1;
static long (*bpf_map_update_elem)(void *map, const void *key, const void *value, uint64_t flags) = (void *)2;

#define KEY "This string is allocated in the string section\n"

__section("xdp") int filter() {
uint32_t *value = bpf_map_lookup_elem(&my_map, KEY);
if (value)
(*value)++;
else {
uint32_t newValue = 1;
bpf_map_update_elem(&my_map, KEY, &newValue, 0);
}

return 2;
}

0 comments on commit 8cb233e

Please sign in to comment.