github.com/kubeshark/ebpf@v0.9.2/linker_test.go (about) 1 package ebpf 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/kubeshark/ebpf/asm" 8 "github.com/kubeshark/ebpf/internal" 9 "github.com/kubeshark/ebpf/internal/testutils" 10 11 qt "github.com/frankban/quicktest" 12 ) 13 14 func TestFindReferences(t *testing.T) { 15 progs := map[string]*ProgramSpec{ 16 "entrypoint": { 17 Type: SocketFilter, 18 Instructions: asm.Instructions{ 19 // Make sure the call doesn't happen at instruction 0 20 // to exercise the relative offset calculation. 21 asm.Mov.Reg(asm.R0, asm.R1), 22 asm.Call.Label("my_func"), 23 asm.Return(), 24 }, 25 License: "MIT", 26 }, 27 "my_other_func": { 28 Instructions: asm.Instructions{ 29 asm.LoadImm(asm.R0, 1337, asm.DWord).WithSymbol("my_other_func"), 30 asm.Return(), 31 }, 32 }, 33 "my_func": { 34 Instructions: asm.Instructions{ 35 asm.Call.Label("my_other_func").WithSymbol("my_func"), 36 asm.Return(), 37 }, 38 }, 39 } 40 41 flattenPrograms(progs, []string{"entrypoint"}) 42 43 prog, err := NewProgram(progs["entrypoint"]) 44 testutils.SkipIfNotSupported(t, err) 45 if err != nil { 46 t.Fatal(err) 47 } 48 defer prog.Close() 49 50 ret, _, err := prog.Test(make([]byte, 14)) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 if ret != 1337 { 56 t.Errorf("Expected return code 1337, got %d", ret) 57 } 58 } 59 60 func TestForwardFunctionDeclaration(t *testing.T) { 61 testutils.Files(t, testutils.Glob(t, "testdata/fwd_decl-*.elf"), func(t *testing.T, file string) { 62 coll, err := LoadCollectionSpec(file) 63 if err != nil { 64 t.Fatal(err) 65 } 66 67 if coll.ByteOrder != internal.NativeEndian { 68 return 69 } 70 71 spec := coll.Programs["call_fwd"] 72 73 // This program calls an unimplemented forward function declaration. 74 _, err = NewProgram(spec) 75 if !errors.Is(err, asm.ErrUnsatisfiedProgramReference) { 76 t.Fatal("Expected an error wrapping ErrUnsatisfiedProgramReference, got:", err) 77 } 78 79 // Append the implementation of fwd(). 80 spec.Instructions = append(spec.Instructions, 81 asm.Mov.Imm32(asm.R0, 23).WithSymbol("fwd"), 82 asm.Return(), 83 ) 84 85 // The body of the subprog we appended does not come with BTF func_infos, 86 // so the verifier will reject it. Load without BTF. 87 spec.BTF = nil 88 89 prog, err := NewProgram(spec) 90 testutils.SkipIfNotSupported(t, err) 91 if err != nil { 92 t.Fatal(err) 93 } 94 defer prog.Close() 95 96 ret, _, err := prog.Test(make([]byte, 14)) 97 if err != nil { 98 t.Fatal("Running program:", err) 99 } 100 if ret != 23 { 101 t.Fatalf("Expected 23, got %d", ret) 102 } 103 }) 104 } 105 106 func TestSplitSymbols(t *testing.T) { 107 c := qt.New(t) 108 109 // Splitting an empty insns results in an error. 110 _, err := splitSymbols(asm.Instructions{}) 111 c.Assert(err, qt.IsNotNil, qt.Commentf("empty insns")) 112 113 // Splitting non-empty insns without a leading Symbol is an error. 114 _, err = splitSymbols(asm.Instructions{ 115 asm.Return(), 116 }) 117 c.Assert(err, qt.IsNotNil, qt.Commentf("insns without leading Symbol")) 118 119 // Non-empty insns with a single Instruction that is a Symbol. 120 insns := asm.Instructions{ 121 asm.Return().WithSymbol("sym"), 122 } 123 m, err := splitSymbols(insns) 124 c.Assert(err, qt.IsNil, qt.Commentf("insns with a single Symbol")) 125 126 c.Assert(len(m), qt.Equals, 1) 127 c.Assert(len(m["sym"]), qt.Equals, 1) 128 129 // Insns containing duplicate Symbols. 130 _, err = splitSymbols(asm.Instructions{ 131 asm.Return().WithSymbol("sym"), 132 asm.Return().WithSymbol("sym"), 133 }) 134 c.Assert(err, qt.IsNotNil, qt.Commentf("insns containing duplicate Symbols")) 135 136 // Insns with multiple Symbols and subprogs of various lengths. 137 m, err = splitSymbols(asm.Instructions{ 138 asm.Return().WithSymbol("sym1"), 139 140 asm.Mov.Imm(asm.R0, 0).WithSymbol("sym2"), 141 asm.Return(), 142 143 asm.Mov.Imm(asm.R0, 0).WithSymbol("sym3"), 144 asm.Mov.Imm(asm.R0, 1), 145 asm.Return(), 146 147 asm.Mov.Imm(asm.R0, 0).WithSymbol("sym4"), 148 asm.Mov.Imm(asm.R0, 1), 149 asm.Mov.Imm(asm.R0, 2), 150 asm.Return(), 151 }) 152 c.Assert(err, qt.IsNil, qt.Commentf("insns with multiple Symbols")) 153 154 c.Assert(len(m), qt.Equals, 4) 155 c.Assert(len(m["sym1"]), qt.Equals, 1) 156 c.Assert(len(m["sym2"]), qt.Equals, 2) 157 c.Assert(len(m["sym3"]), qt.Equals, 3) 158 c.Assert(len(m["sym4"]), qt.Equals, 4) 159 }