Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elf_reader: Allow strings read-only global data sections #742

Merged
merged 1 commit into from Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
60 changes: 54 additions & 6 deletions elf_reader_test.go
Expand Up @@ -422,13 +422,61 @@ 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")
}

_, err = prog.Run(&RunOptions{
Data: make([]byte, 14), // Min size for XDP programs
})
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 != 1 {
t.Fatal("Test map value not 1!")
}
}

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;
}