github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/core_reloc_test.go (about)

     1  package btf_test
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"os"
     7  	"slices"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/cilium/ebpf"
    12  	"github.com/cilium/ebpf/btf"
    13  	"github.com/cilium/ebpf/internal"
    14  	"github.com/cilium/ebpf/internal/testutils"
    15  
    16  	"github.com/go-quicktest/qt"
    17  )
    18  
    19  func TestCORERelocationLoad(t *testing.T) {
    20  	file := testutils.NativeFile(t, "testdata/relocs-%s.elf")
    21  	fh, err := os.Open(file)
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	defer fh.Close()
    26  
    27  	spec, err := ebpf.LoadCollectionSpecFromReader(fh)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	for _, progSpec := range spec.Programs {
    33  		t.Run(progSpec.Name, func(t *testing.T) {
    34  			if _, err := fh.Seek(0, io.SeekStart); err != nil {
    35  				t.Fatal(err)
    36  			}
    37  
    38  			prog, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{
    39  				KernelTypes: spec.Types,
    40  			})
    41  			testutils.SkipIfNotSupported(t, err)
    42  
    43  			if strings.HasPrefix(progSpec.Name, "err_") {
    44  				if err == nil {
    45  					prog.Close()
    46  					t.Fatal("Expected an error")
    47  				}
    48  				t.Log("Got expected error:", err)
    49  				return
    50  			}
    51  
    52  			if err != nil {
    53  				t.Fatal("Load program:", err)
    54  			}
    55  			defer prog.Close()
    56  
    57  			ret, _, err := prog.Test(internal.EmptyBPFContext)
    58  			testutils.SkipIfNotSupported(t, err)
    59  			if err != nil {
    60  				t.Fatal("Error when running:", err)
    61  			}
    62  
    63  			if ret != 0 {
    64  				t.Error("Assertion failed on line", ret)
    65  			}
    66  		})
    67  	}
    68  }
    69  
    70  func TestCORERelocationRead(t *testing.T) {
    71  	file := testutils.NativeFile(t, "testdata/relocs_read-%s.elf")
    72  	spec, err := ebpf.LoadCollectionSpec(file)
    73  	if err != nil {
    74  		t.Fatal(err)
    75  	}
    76  
    77  	targetFile := testutils.NativeFile(t, "testdata/relocs_read_tgt-%s.elf")
    78  	targetSpec, err := btf.LoadSpec(targetFile)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	for _, progSpec := range spec.Programs {
    84  		t.Run(progSpec.Name, func(t *testing.T) {
    85  			prog, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{
    86  				KernelTypes: targetSpec,
    87  			})
    88  			testutils.SkipIfNotSupported(t, err)
    89  			if err != nil {
    90  				t.Fatal("Load program:", err)
    91  			}
    92  			defer prog.Close()
    93  
    94  			ret, _, err := prog.Test(internal.EmptyBPFContext)
    95  			testutils.SkipIfNotSupported(t, err)
    96  			if err != nil {
    97  				t.Fatal("Error when running:", err)
    98  			}
    99  
   100  			if ret != 0 {
   101  				t.Error("Assertion failed on line", ret)
   102  			}
   103  		})
   104  	}
   105  }
   106  
   107  func TestLD64IMMReloc(t *testing.T) {
   108  	testutils.SkipOnOldKernel(t, "5.4", "vmlinux BTF in sysfs")
   109  
   110  	file := testutils.NativeFile(t, "testdata/relocs_enum-%s.elf")
   111  	fh, err := os.Open(file)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  	defer fh.Close()
   116  
   117  	spec, err := ebpf.LoadCollectionSpecFromReader(fh)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	coll, err := ebpf.NewCollection(spec)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	defer coll.Close()
   127  }
   128  
   129  func TestCOREPoisonLineInfo(t *testing.T) {
   130  	testutils.SkipOnOldKernel(t, "5.0", "program ext_infos")
   131  
   132  	spec, err := ebpf.LoadCollectionSpec(testutils.NativeFile(t, "../testdata/errors-%s.elf"))
   133  	qt.Assert(t, qt.IsNil(err))
   134  
   135  	var b btf.Builder
   136  	raw, err := b.Marshal(nil, nil)
   137  	qt.Assert(t, qt.IsNil(err))
   138  	empty, err := btf.LoadSpecFromReader(bytes.NewReader(raw))
   139  	qt.Assert(t, qt.IsNil(err))
   140  
   141  	for _, test := range []struct {
   142  		name string
   143  	}{
   144  		{"poisoned_single"},
   145  		{"poisoned_double"},
   146  	} {
   147  		progSpec := spec.Programs[test.name]
   148  		qt.Assert(t, qt.IsNotNil(progSpec))
   149  
   150  		t.Run(test.name, func(t *testing.T) {
   151  			t.Log(progSpec.Instructions)
   152  			_, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{
   153  				KernelTypes: empty,
   154  			})
   155  			testutils.SkipIfNotSupported(t, err)
   156  
   157  			var ve *ebpf.VerifierError
   158  			qt.Assert(t, qt.ErrorAs(err, &ve))
   159  			found := slices.ContainsFunc(ve.Log, func(line string) bool {
   160  				return strings.HasPrefix(line, "; instruction poisoned by CO-RE")
   161  			})
   162  			qt.Assert(t, qt.IsTrue(found))
   163  			t.Logf("%-5v", ve)
   164  		})
   165  	}
   166  }