1 package ebpf
2
3 import (
4 "errors"
5 "testing"
6
7 "github.com/cilium/ebpf/asm"
8 "github.com/cilium/ebpf/internal"
9 "github.com/cilium/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
20
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
74 _, err = NewProgram(spec)
75 if !errors.Is(err, asm.ErrUnsatisfiedProgramReference) {
76 t.Fatal("Expected an error wrapping ErrUnsatisfiedProgramReference, got:", err)
77 }
78
79
80 spec.Instructions = append(spec.Instructions,
81 asm.Mov.Imm32(asm.R0, 23).WithSymbol("fwd"),
82 asm.Return(),
83 )
84
85
86
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
110 _, err := splitSymbols(asm.Instructions{})
111 c.Assert(err, qt.IsNotNil, qt.Commentf("empty insns"))
112
113
114 _, err = splitSymbols(asm.Instructions{
115 asm.Return(),
116 })
117 c.Assert(err, qt.IsNotNil, qt.Commentf("insns without leading Symbol"))
118
119
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
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
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 }
160
View as plain text