diff --git a/Makefile b/Makefile index 76a448caa..2384847a6 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,9 @@ TARGETS := \ testdata/map_spin_lock \ testdata/subprog_reloc \ testdata/fwd_decl \ - internal/btf/testdata/relocs + internal/btf/testdata/relocs \ + internal/btf/testdata/relocs_read \ + internal/btf/testdata/relocs_read_tgt .PHONY: all clean container-all container-shell generate diff --git a/internal/btf/core_reloc_test.go b/internal/btf/core_reloc_test.go index f4cf2bafe..4377b28b3 100644 --- a/internal/btf/core_reloc_test.go +++ b/internal/btf/core_reloc_test.go @@ -1,17 +1,19 @@ package btf_test import ( + "fmt" "io" "os" "strings" "testing" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/testutils" ) func TestCoreRelocationLoad(t *testing.T) { - testutils.Files(t, testutils.Glob(t, "testdata/*-el.elf"), func(t *testing.T, file string) { + testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) { fh, err := os.Open(file) if err != nil { t.Fatal(err) @@ -23,6 +25,10 @@ func TestCoreRelocationLoad(t *testing.T) { t.Fatal(err) } + if spec.ByteOrder != internal.NativeEndian { + return + } + for _, progSpec := range spec.Programs { t.Run(progSpec.Name, func(t *testing.T) { if _, err := fh.Seek(0, io.SeekStart); err != nil { @@ -60,3 +66,56 @@ func TestCoreRelocationLoad(t *testing.T) { } }) } + +func TestCoreRelocationRead(t *testing.T) { + testutils.Files(t, testutils.Glob(t, "testdata/relocs_read-*.elf"), func(t *testing.T, file string) { + fh, err := os.Open(file) + if err != nil { + t.Fatal(err) + } + defer fh.Close() + + spec, err := ebpf.LoadCollectionSpecFromReader(fh) + if err != nil { + t.Fatal(err) + } + + if spec.ByteOrder != internal.NativeEndian { + return + } + + tgt, err := os.Open(fmt.Sprintf("testdata/relocs_read_tgt-%s.elf", internal.ClangEndian)) + if err != nil { + t.Fatal(err) + } + defer tgt.Close() + + for _, progSpec := range spec.Programs { + t.Run(progSpec.Name, func(t *testing.T) { + if _, err := tgt.Seek(0, io.SeekStart); err != nil { + t.Fatal(err) + } + + testutils.SkipOnOldKernel(t, "4.16", "bpf2bpf calls") + + prog, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{ + TargetBTF: tgt, + }) + if err != nil { + t.Fatal("Load program:", err) + } + defer prog.Close() + + ret, _, err := prog.Test(make([]byte, 14)) + testutils.SkipIfNotSupported(t, err) + if err != nil { + t.Fatal("Error when running:", err) + } + + if ret != 0 { + t.Error("Assertion failed on line", ret) + } + }) + } + }) +} diff --git a/internal/btf/testdata/relocs_read-eb.elf b/internal/btf/testdata/relocs_read-eb.elf new file mode 100644 index 000000000..d5e6c328f Binary files /dev/null and b/internal/btf/testdata/relocs_read-eb.elf differ diff --git a/internal/btf/testdata/relocs_read-el.elf b/internal/btf/testdata/relocs_read-el.elf new file mode 100644 index 000000000..50b6c886a Binary files /dev/null and b/internal/btf/testdata/relocs_read-el.elf differ diff --git a/internal/btf/testdata/relocs_read.c b/internal/btf/testdata/relocs_read.c new file mode 100644 index 000000000..ccb4f499a --- /dev/null +++ b/internal/btf/testdata/relocs_read.c @@ -0,0 +1,37 @@ +#include "../../../testdata/common.h" + +#define core_access __builtin_preserve_access_index + +// Struct with the members declared in the wrong order. Accesses need +// a successful CO-RE relocation against the type in relocs_read_tgt.c +// for the test below to pass. +struct s { + char b; + char a; +}; + +// Perform a read from a subprog to ensure CO-RE relocations +// occurring there are tracked and executed in the final linked program. +__attribute__((noinline)) int read_subprog() { + struct s foo = { + .a = 0, + .b = 1, + }; + + if (core_access(foo.a) == 0) + return __LINE__; + + if (core_access(foo.b) == 1) + return __LINE__; + + return 0; +} + +__section("socket") int reads() { + int ret = read_subprog(); + if (ret) + return ret; + + return 0; +} + diff --git a/internal/btf/testdata/relocs_read_tgt-eb.elf b/internal/btf/testdata/relocs_read_tgt-eb.elf new file mode 100644 index 000000000..b0effd5f8 Binary files /dev/null and b/internal/btf/testdata/relocs_read_tgt-eb.elf differ diff --git a/internal/btf/testdata/relocs_read_tgt-el.elf b/internal/btf/testdata/relocs_read_tgt-el.elf new file mode 100644 index 000000000..34c056daa Binary files /dev/null and b/internal/btf/testdata/relocs_read_tgt-el.elf differ diff --git a/internal/btf/testdata/relocs_read_tgt.c b/internal/btf/testdata/relocs_read_tgt.c new file mode 100644 index 000000000..38bb4b156 --- /dev/null +++ b/internal/btf/testdata/relocs_read_tgt.c @@ -0,0 +1,16 @@ +/* + This file exists to emit ELFs with specific BTF types to use as target BTF + in tests. It can be made redundant when btf.Spec can be handcrafted and + passed as a CO-RE target in the future. +*/ + +#define core_access __builtin_preserve_access_index + +struct s { + char a; + char b; +}; + +int dummy() { + return core_access((struct s){}.a); +}