1 package ebpf
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "errors"
7 "flag"
8 "fmt"
9 "os"
10 "path/filepath"
11 "strings"
12 "syscall"
13 "testing"
14
15 "github.com/cilium/ebpf/btf"
16 "github.com/cilium/ebpf/internal"
17 "github.com/cilium/ebpf/internal/testutils"
18 "github.com/cilium/ebpf/internal/unix"
19
20 "github.com/google/go-cmp/cmp"
21 "github.com/google/go-cmp/cmp/cmpopts"
22 )
23
24 func TestLoadCollectionSpec(t *testing.T) {
25 cpus, err := internal.PossibleCPUs()
26 if err != nil {
27 t.Fatal(err)
28 }
29
30 coll := &CollectionSpec{
31 Maps: map[string]*MapSpec{
32 "hash_map": {
33 Name: "hash_map",
34 Type: Hash,
35 KeySize: 4,
36 ValueSize: 8,
37 MaxEntries: 1,
38 Flags: unix.BPF_F_NO_PREALLOC,
39 },
40 "hash_map2": {
41 Name: "hash_map2",
42 Type: Hash,
43 KeySize: 4,
44 ValueSize: 8,
45 MaxEntries: 2,
46 },
47 "array_of_hash_map": {
48 Name: "array_of_hash_map",
49 Type: ArrayOfMaps,
50 KeySize: 4,
51 MaxEntries: 2,
52 },
53 "perf_event_array": {
54 Name: "perf_event_array",
55 Type: PerfEventArray,
56 MaxEntries: uint32(cpus),
57 },
58
59
60 "btf_pin": {
61 Name: "btf_pin",
62 Type: Hash,
63 KeySize: 4,
64 ValueSize: 8,
65 MaxEntries: 1,
66 Pinning: PinByName,
67 },
68 "btf_outer_map": {
69 Name: "btf_outer_map",
70 Type: ArrayOfMaps,
71 KeySize: 4,
72 ValueSize: 4,
73 MaxEntries: 1,
74 InnerMap: &MapSpec{
75 Name: "btf_outer_map_inner",
76 Type: Hash,
77 KeySize: 4,
78 ValueSize: 4,
79 MaxEntries: 1,
80 },
81 },
82 "btf_outer_map_anon": {
83 Name: "btf_outer_map_anon",
84 Type: ArrayOfMaps,
85 KeySize: 4,
86 ValueSize: 4,
87 MaxEntries: 1,
88 InnerMap: &MapSpec{
89 Name: "btf_outer_map_anon_inner",
90 Type: Hash,
91 KeySize: 4,
92 ValueSize: 4,
93 MaxEntries: 1,
94 },
95 },
96 },
97 Programs: map[string]*ProgramSpec{
98 "xdp_prog": {
99 Name: "xdp_prog",
100 Type: XDP,
101 SectionName: "xdp",
102 License: "MIT",
103 },
104 "no_relocation": {
105 Name: "no_relocation",
106 Type: SocketFilter,
107 SectionName: "socket",
108 License: "MIT",
109 },
110 "asm_relocation": {
111 Name: "asm_relocation",
112 Type: SocketFilter,
113 SectionName: "socket/2",
114 License: "MIT",
115 },
116 "data_sections": {
117 Name: "data_sections",
118 Type: SocketFilter,
119 SectionName: "socket/3",
120 License: "MIT",
121 },
122 "global_fn3": {
123 Name: "global_fn3",
124 Type: UnspecifiedProgram,
125 SectionName: "other",
126 License: "MIT",
127 },
128 "static_fn": {
129 Name: "static_fn",
130 Type: UnspecifiedProgram,
131 SectionName: "static",
132 License: "MIT",
133 },
134 "anon_const": {
135 Name: "anon_const",
136 Type: SocketFilter,
137 SectionName: "socket/4",
138 License: "MIT",
139 },
140 },
141 }
142
143 defaultOpts := cmp.Options{
144
145 cmp.Comparer(func(a, b bytes.Reader) bool {
146 if a.Len() == 0 && b.Len() == 0 {
147 return true
148 }
149 return false
150 }),
151 cmpopts.IgnoreTypes(new(btf.Spec)),
152 cmpopts.IgnoreFields(CollectionSpec{}, "ByteOrder", "Types"),
153 cmpopts.IgnoreFields(ProgramSpec{}, "Instructions", "ByteOrder"),
154 cmpopts.IgnoreFields(MapSpec{}, "Key", "Value"),
155 cmpopts.IgnoreUnexported(ProgramSpec{}),
156 cmpopts.IgnoreMapEntries(func(key string, _ *MapSpec) bool {
157 if key == ".bss" || key == ".data" || strings.HasPrefix(key, ".rodata") {
158 return true
159 }
160 return false
161 }),
162 }
163
164 ignoreBTFOpts := append(defaultOpts,
165 cmpopts.IgnoreMapEntries(func(key string, _ *MapSpec) bool {
166 return strings.HasPrefix(key, "btf_")
167 }),
168 )
169
170 testutils.Files(t, testutils.Glob(t, "testdata/loader-*.elf"), func(t *testing.T, file string) {
171 have, err := LoadCollectionSpec(file)
172 if err != nil {
173 t.Fatal("Can't parse ELF:", err)
174 }
175
176 opts := defaultOpts
177 if have.Types != nil {
178 err := have.RewriteConstants(map[string]interface{}{
179 "arg": uint32(1),
180 "arg2": uint32(2),
181 })
182 if err != nil {
183 t.Fatal("Can't rewrite constant:", err)
184 }
185
186 err = have.RewriteConstants(map[string]interface{}{
187 "totallyBogus": uint32(1),
188 })
189 if err == nil {
190 t.Error("Rewriting a bogus constant doesn't fail")
191 }
192 } else {
193 opts = ignoreBTFOpts
194 }
195
196 if diff := cmp.Diff(coll, have, opts...); diff != "" {
197 t.Errorf("MapSpec mismatch (-want +got):\n%s", diff)
198 }
199
200 if have.ByteOrder != internal.NativeEndian {
201 return
202 }
203
204 have.Maps["array_of_hash_map"].InnerMap = have.Maps["hash_map"]
205 coll, err := NewCollectionWithOptions(have, CollectionOptions{
206 Maps: MapOptions{
207 PinPath: testutils.TempBPFFS(t),
208 },
209 Programs: ProgramOptions{
210 LogLevel: 1,
211 },
212 })
213 testutils.SkipIfNotSupported(t, err)
214 if err != nil {
215 t.Fatal(err)
216 }
217 defer coll.Close()
218
219 ret, _, err := coll.Programs["xdp_prog"].Test(make([]byte, 14))
220 if err != nil {
221 t.Fatal("Can't run program:", err)
222 }
223
224 if ret != 7 {
225 t.Error("Expected return value to be 5, got", ret)
226 }
227 })
228 }
229
230 func BenchmarkELFLoader(b *testing.B) {
231 b.ReportAllocs()
232
233 for i := 0; i < b.N; i++ {
234 _, _ = LoadCollectionSpec("testdata/loader-el.elf")
235 }
236 }
237
238 func TestDataSections(t *testing.T) {
239 file := fmt.Sprintf("testdata/loader-%s.elf", internal.ClangEndian)
240 coll, err := LoadCollectionSpec(file)
241 if err != nil {
242 t.Fatal(err)
243 }
244
245 t.Log(coll.Programs["data_sections"].Instructions)
246
247 var obj struct {
248 Program *Program `ebpf:"data_sections"`
249 }
250
251 err = coll.LoadAndAssign(&obj, nil)
252 testutils.SkipIfNotSupported(t, err)
253 if err != nil {
254 t.Fatal(err)
255 }
256 defer obj.Program.Close()
257
258 ret, _, err := obj.Program.Test(make([]byte, 14))
259 if err != nil {
260 t.Fatal(err)
261 }
262
263 if ret != 0 {
264 t.Error("BPF assertion failed on line", ret)
265 }
266 }
267
268 func TestInlineASMConstant(t *testing.T) {
269 file := fmt.Sprintf("testdata/loader-%s.elf", internal.ClangEndian)
270 coll, err := LoadCollectionSpec(file)
271 if err != nil {
272 t.Fatal(err)
273 }
274
275 spec := coll.Programs["asm_relocation"]
276 if spec.Instructions[0].Reference() != "MY_CONST" {
277 t.Fatal("First instruction is not a reference to MY_CONST")
278 }
279
280
281 spec.Instructions[0].Constant = -1
282
283 t.Log(spec.Instructions)
284
285 var obj struct {
286 Program *Program `ebpf:"asm_relocation"`
287 }
288
289 err = coll.LoadAndAssign(&obj, nil)
290 testutils.SkipIfNotSupported(t, err)
291 if err != nil {
292 t.Fatal(err)
293 }
294 obj.Program.Close()
295 }
296
297 func TestCollectionSpecDetach(t *testing.T) {
298 coll := Collection{
299 Maps: map[string]*Map{
300 "foo": new(Map),
301 },
302 Programs: map[string]*Program{
303 "bar": new(Program),
304 },
305 }
306
307 foo := coll.DetachMap("foo")
308 if foo == nil {
309 t.Error("Program not returned from DetachMap")
310 }
311
312 if _, ok := coll.Programs["foo"]; ok {
313 t.Error("DetachMap doesn't remove map from Maps")
314 }
315
316 bar := coll.DetachProgram("bar")
317 if bar == nil {
318 t.Fatal("Program not returned from DetachProgram")
319 }
320
321 if _, ok := coll.Programs["bar"]; ok {
322 t.Error("DetachProgram doesn't remove program from Programs")
323 }
324 }
325
326 func TestLoadInvalidMap(t *testing.T) {
327 testutils.Files(t, testutils.Glob(t, "testdata/invalid_map-*.elf"), func(t *testing.T, file string) {
328 cs, err := LoadCollectionSpec(file)
329 if err != nil {
330 t.Fatal("Can't load CollectionSpec", err)
331 }
332
333 ms, ok := cs.Maps["invalid_map"]
334 if !ok {
335 t.Fatal("invalid_map not found in CollectionSpec")
336 }
337
338 m, err := NewMap(ms)
339 t.Log(err)
340 if err == nil {
341 m.Close()
342 t.Fatal("Creating a Map from a MapSpec with non-zero Extra is expected to fail.")
343 }
344 })
345 }
346
347 func TestLoadInvalidMapMissingSymbol(t *testing.T) {
348 testutils.Files(t, testutils.Glob(t, "testdata/invalid_map_static-el.elf"), func(t *testing.T, file string) {
349 _, err := LoadCollectionSpec(file)
350 t.Log(err)
351 if err == nil {
352 t.Fatal("Loading a map with static qualifier should fail")
353 }
354 })
355 }
356
357 func TestLoadInitializedBTFMap(t *testing.T) {
358 testutils.Files(t, testutils.Glob(t, "testdata/btf_map_init-*.elf"), func(t *testing.T, file string) {
359 coll, err := LoadCollectionSpec(file)
360 if err != nil {
361 t.Fatal(err)
362 }
363
364 t.Run("prog_array", func(t *testing.T) {
365 m, ok := coll.Maps["prog_array_init"]
366 if !ok {
367 t.Fatal("map prog_array_init not found in program")
368 }
369
370 if len(m.Contents) != 1 {
371 t.Error("expecting exactly 1 item in MapSpec contents")
372 }
373
374 p := m.Contents[0]
375 if cmp.Equal(p.Key, 1) {
376 t.Errorf("expecting MapSpec entry Key to equal 1, got %v", p.Key)
377 }
378
379 if _, ok := p.Value.(string); !ok {
380 t.Errorf("expecting MapSpec entry Value to be a string, got %T", p.Value)
381 }
382
383 if p.Value != "tail_1" {
384 t.Errorf("expected MapSpec entry Value 'tail_1', got: %s", p.Value)
385 }
386 })
387
388 t.Run("array_of_maps", func(t *testing.T) {
389 m, ok := coll.Maps["outer_map_init"]
390 if !ok {
391 t.Fatal("map outer_map_init not found in program")
392 }
393
394 if len(m.Contents) != 1 {
395 t.Error("expecting exactly 1 item in MapSpec contents")
396 }
397
398 p := m.Contents[0]
399 if cmp.Equal(p.Key, 1) {
400 t.Errorf("expecting MapSpec entry Key to equal 1, got %v", p.Key)
401 }
402
403 if _, ok := p.Value.(string); !ok {
404 t.Errorf("expecting MapSpec entry Value to be a string, got %T", p.Value)
405 }
406
407 if p.Value != "inner_map" {
408 t.Errorf("expected MapSpec entry Value 'inner_map', got: %s", p.Value)
409 }
410 })
411 })
412 }
413
414 func TestLoadInvalidInitializedBTFMap(t *testing.T) {
415 testutils.Files(t, testutils.Glob(t, "testdata/invalid_btf_map_init-*.elf"), func(t *testing.T, file string) {
416 _, err := LoadCollectionSpec(file)
417 t.Log(err)
418 if !errors.Is(err, internal.ErrNotSupported) {
419 t.Fatal("Loading an initialized BTF map should be unsupported")
420 }
421 })
422 }
423
424 func TestStringSection(t *testing.T) {
425 testutils.Files(t, testutils.Glob(t, "testdata/strings-*.elf"), func(t *testing.T, file string) {
426 _, err := LoadCollectionSpec(file)
427 t.Log(err)
428 if !errors.Is(err, ErrNotSupported) {
429 t.Error("References to a string section should be unsupported")
430 }
431 })
432 }
433
434 func TestLoadRawTracepoint(t *testing.T) {
435 testutils.SkipOnOldKernel(t, "4.17", "BPF_RAW_TRACEPOINT API")
436
437 testutils.Files(t, testutils.Glob(t, "testdata/raw_tracepoint-*.elf"), func(t *testing.T, file string) {
438 spec, err := LoadCollectionSpec(file)
439 if err != nil {
440 t.Fatal("Can't parse ELF:", err)
441 }
442
443 if spec.ByteOrder != internal.NativeEndian {
444 return
445 }
446
447 coll, err := NewCollectionWithOptions(spec, CollectionOptions{
448 Programs: ProgramOptions{
449 LogLevel: 1,
450 },
451 })
452 testutils.SkipIfNotSupported(t, err)
453 if err != nil {
454 t.Fatal("Can't create collection:", err)
455 }
456
457 coll.Close()
458 })
459 }
460
461 func TestTailCall(t *testing.T) {
462 testutils.Files(t, testutils.Glob(t, "testdata/btf_map_init-*.elf"), func(t *testing.T, file string) {
463 spec, err := LoadCollectionSpec(file)
464 if err != nil {
465 t.Fatal(err)
466 }
467
468 if spec.ByteOrder != internal.NativeEndian {
469 return
470 }
471
472 var obj struct {
473 TailMain *Program `ebpf:"tail_main"`
474 ProgArray *Map `ebpf:"prog_array_init"`
475 }
476
477 err = spec.LoadAndAssign(&obj, nil)
478 testutils.SkipIfNotSupported(t, err)
479 if err != nil {
480 t.Fatal(err)
481 }
482 defer obj.TailMain.Close()
483 defer obj.ProgArray.Close()
484
485 ret, _, err := obj.TailMain.Test(make([]byte, 14))
486 testutils.SkipIfNotSupported(t, err)
487 if err != nil {
488 t.Fatal(err)
489 }
490
491
492 if ret != 42 {
493 t.Fatalf("Expected tail call to return value 42, got %d", ret)
494 }
495 })
496 }
497
498 func TestSubprogRelocation(t *testing.T) {
499 testutils.SkipOnOldKernel(t, "5.13", "bpf_for_each_map_elem")
500
501 testutils.Files(t, testutils.Glob(t, "testdata/subprog_reloc-*.elf"), func(t *testing.T, file string) {
502 spec, err := LoadCollectionSpec(file)
503 if err != nil {
504 t.Fatal(err)
505 }
506
507 if spec.ByteOrder != internal.NativeEndian {
508 return
509 }
510
511 var obj struct {
512 Main *Program `ebpf:"fp_relocation"`
513 HashMap *Map `ebpf:"hash_map"`
514 }
515
516 err = spec.LoadAndAssign(&obj, nil)
517 testutils.SkipIfNotSupported(t, err)
518 if err != nil {
519 t.Fatal(err)
520 }
521 defer obj.Main.Close()
522 defer obj.HashMap.Close()
523
524 ret, _, err := obj.Main.Test(make([]byte, 14))
525 testutils.SkipIfNotSupported(t, err)
526 if err != nil {
527 t.Fatal(err)
528 }
529
530 if ret != 42 {
531 t.Fatalf("Expected subprog reloc to return value 42, got %d", ret)
532 }
533 })
534 }
535
536 func TestUnassignedProgArray(t *testing.T) {
537 testutils.Files(t, testutils.Glob(t, "testdata/btf_map_init-*.elf"), func(t *testing.T, file string) {
538 spec, err := LoadCollectionSpec(file)
539 if err != nil {
540 t.Fatal(err)
541 }
542
543 if spec.ByteOrder != internal.NativeEndian {
544 return
545 }
546
547
548
549
550
551 var obj struct {
552 TailMain *Program `ebpf:"tail_main"`
553
554 }
555
556 err = spec.LoadAndAssign(&obj, nil)
557 testutils.SkipIfNotSupported(t, err)
558 if err == nil {
559 obj.TailMain.Close()
560 t.Fatal("Expecting LoadAndAssign to return error")
561 }
562 })
563 }
564
565 func TestIPRoute2Compat(t *testing.T) {
566 testutils.Files(t, testutils.Glob(t, "testdata/iproute2_map_compat-*.elf"), func(t *testing.T, file string) {
567 spec, err := LoadCollectionSpec(file)
568 if err != nil {
569 t.Fatal("Can't parse ELF:", err)
570 }
571
572 if spec.ByteOrder != internal.NativeEndian {
573 return
574 }
575
576 ms, ok := spec.Maps["hash_map"]
577 if !ok {
578 t.Fatal("Map hash_map not found")
579 }
580
581 var id, pinning, innerID, innerIndex uint32
582
583 if ms.Extra == nil {
584 t.Fatal("missing extra bytes")
585 }
586
587 switch {
588 case binary.Read(ms.Extra, spec.ByteOrder, &id) != nil:
589 t.Fatal("missing id")
590 case binary.Read(ms.Extra, spec.ByteOrder, &pinning) != nil:
591 t.Fatal("missing pinning")
592 case binary.Read(ms.Extra, spec.ByteOrder, &innerID) != nil:
593 t.Fatal("missing inner_id")
594 case binary.Read(ms.Extra, spec.ByteOrder, &innerIndex) != nil:
595 t.Fatal("missing inner_idx")
596 }
597
598 if id != 0 || innerID != 0 || innerIndex != 0 {
599 t.Fatal("expecting id, inner_id and inner_idx to be zero")
600 }
601
602 if pinning != 2 {
603 t.Fatal("expecting pinning field to be 2 (PIN_GLOBAL_NS)")
604 }
605
606
607
608
609 ms.Pinning = PinByName
610
611 coll, err := NewCollectionWithOptions(spec, CollectionOptions{
612 Maps: MapOptions{
613 PinPath: testutils.TempBPFFS(t),
614 },
615 })
616 testutils.SkipIfNotSupported(t, err)
617 if err != nil {
618 t.Fatal("Can't create collection:", err)
619 }
620
621 coll.Close()
622 })
623 }
624
625 var (
626 elfPath = flag.String("elfs", os.Getenv("KERNEL_SELFTESTS"), "`Path` containing libbpf-compatible ELFs (defaults to $KERNEL_SELFTESTS)")
627 elfPattern = flag.String("elf-pattern", "*.o", "Glob `pattern` for object files that should be tested")
628 )
629
630 func TestLibBPFCompat(t *testing.T) {
631 if *elfPath == "" {
632
633
634
635 t.Skip("No path specified")
636 }
637
638 load := func(t *testing.T, spec *CollectionSpec, opts CollectionOptions, valid bool) {
639
640
641 opts.Programs.LogSize = -1
642
643 for name, p := range spec.Programs {
644 if p.Type != Extension {
645 continue
646 }
647
648 targetProg, targetColl := loadTargetProgram(t, name, opts)
649 defer targetColl.Close()
650 p.AttachTarget = targetProg
651 }
652
653 coll, err := NewCollectionWithOptions(spec, opts)
654 testutils.SkipIfNotSupported(t, err)
655 var errno syscall.Errno
656 if errors.As(err, &errno) {
657
658
659
660
661 t.Skip("Skipping since the kernel rejected the program:", errno)
662 }
663 if err == nil {
664 coll.Close()
665 }
666 if !valid {
667 if err == nil {
668 t.Fatal("Expected an error during load")
669 }
670 } else if err != nil {
671 t.Fatal("Error during loading:", err)
672 }
673 }
674
675 files := testutils.Glob(t, filepath.Join(*elfPath, *elfPattern),
676
677 "btf__core_reloc_*",
678 )
679
680 testutils.Files(t, files, func(t *testing.T, path string) {
681 file := filepath.Base(path)
682 switch file {
683 case "test_map_in_map.o", "test_map_in_map.linked3.o",
684 "test_select_reuseport_kern.o", "test_select_reuseport_kern.linked3.o":
685 t.Skip("Skipping due to missing InnerMap in map definition")
686 case "test_core_autosize.o":
687 t.Skip("Skipping since the test generates dynamic BTF")
688 case "test_static_linked.linked3.o":
689 t.Skip("Skipping since .text contains 'subprog' twice")
690 case "linked_maps.linked3.o", "linked_funcs.linked3.o":
691 t.Skip("Skipping since weak relocations are not supported")
692 }
693
694 t.Parallel()
695
696 spec, err := LoadCollectionSpec(path)
697 testutils.SkipIfNotSupported(t, err)
698 if err != nil {
699 t.Fatalf("Can't read %s: %s", file, err)
700 }
701
702 switch file {
703 case "test_sk_assign.o":
704
705 for _, m := range spec.Maps {
706 if m.Extra == nil || m.Extra.Len() == 0 {
707 t.Fatalf("Expected extra bytes in map %s", m.Name)
708 }
709 m.Extra = nil
710 }
711 }
712
713 var opts CollectionOptions
714 for _, mapSpec := range spec.Maps {
715 if mapSpec.Pinning != PinNone {
716 opts.Maps.PinPath = testutils.TempBPFFS(t)
717 break
718 }
719 }
720
721 coreFiles := sourceOfBTF(t, path)
722 if len(coreFiles) == 0 {
723
724
725 load(t, spec, opts, true)
726 return
727 }
728
729 for _, coreFile := range coreFiles {
730 name := filepath.Base(coreFile)
731 t.Run(name, func(t *testing.T) {
732
733
734
735 var valid bool
736 switch name {
737 case "btf__core_reloc_existence___err_wrong_arr_kind.o",
738 "btf__core_reloc_existence___err_wrong_arr_value_type.o",
739 "btf__core_reloc_existence___err_wrong_int_kind.o",
740 "btf__core_reloc_existence___err_wrong_int_sz.o",
741 "btf__core_reloc_existence___err_wrong_int_type.o",
742 "btf__core_reloc_existence___err_wrong_struct_type.o":
743
744 valid = true
745 case "btf__core_reloc_ints___err_wrong_sz_16.o",
746 "btf__core_reloc_ints___err_wrong_sz_32.o",
747 "btf__core_reloc_ints___err_wrong_sz_64.o",
748 "btf__core_reloc_ints___err_wrong_sz_8.o",
749 "btf__core_reloc_arrays___err_wrong_val_type1.o",
750 "btf__core_reloc_arrays___err_wrong_val_type2.o":
751
752
753 valid = true
754 case "btf__core_reloc_type_id___missing_targets.o",
755 "btf__core_reloc_flavors__err_wrong_name.o":
756 valid = false
757 case "btf__core_reloc_ints___err_bitfield.o":
758
759 valid = true
760 default:
761 valid = !strings.Contains(name, "___err_")
762 }
763
764 fh, err := os.Open(coreFile)
765 if err != nil {
766 t.Fatal(err)
767 }
768 defer fh.Close()
769
770 btfSpec, err := btf.LoadSpec(coreFile)
771 if err != nil {
772 t.Fatal(err)
773 }
774
775 opts := opts
776 opts.Programs.KernelTypes = btfSpec
777 load(t, spec, opts, valid)
778 })
779 }
780 })
781 }
782
783 func loadTargetProgram(tb testing.TB, name string, opts CollectionOptions) (*Program, *Collection) {
784 file := "test_pkt_access.o"
785 program := "test_pkt_access"
786 switch name {
787 case "new_connect_v4_prog":
788 file = "connect4_prog.o"
789 program = "connect_v4_prog"
790 case "new_do_bind":
791 file = "connect4_prog.o"
792 program = "connect_v4_prog"
793 case "freplace_cls_redirect_test":
794 file = "test_cls_redirect.o"
795 program = "cls_redirect"
796 case "new_handle_kprobe":
797 file = "test_attach_probe.o"
798 program = "handle_kprobe"
799 case "test_pkt_md_access_new":
800 file = "test_pkt_md_access.o"
801 program = "test_pkt_md_access"
802 default:
803 }
804
805 spec, err := LoadCollectionSpec(filepath.Join(*elfPath, file))
806 if err != nil {
807 tb.Fatalf("Can't read %s: %s", file, err)
808 }
809
810 coll, err := NewCollectionWithOptions(spec, opts)
811 if err != nil {
812 tb.Fatalf("Can't load target: %s", err)
813 }
814
815 return coll.Programs[program], coll
816 }
817
818 func sourceOfBTF(tb testing.TB, path string) []string {
819 const testPrefix = "test_core_reloc_"
820 const btfPrefix = "btf__core_reloc_"
821
822 dir, base := filepath.Split(path)
823 if !strings.HasPrefix(base, testPrefix) {
824 return nil
825 }
826
827 base = strings.TrimSuffix(base[len(testPrefix):], ".o")
828 switch base {
829 case "bitfields_direct", "bitfields_probed":
830 base = "bitfields"
831 }
832
833 return testutils.Glob(tb, filepath.Join(dir, btfPrefix+base+"*.o"))
834 }
835
836 func TestGetProgType(t *testing.T) {
837 type progTypeTestData struct {
838 Pt ProgramType
839 At AttachType
840 Fl uint32
841 To string
842 }
843
844 testcases := map[string]progTypeTestData{
845 "socket/garbage": {
846 Pt: SocketFilter,
847 At: AttachNone,
848 To: "",
849 },
850 "kprobe/func": {
851 Pt: Kprobe,
852 At: AttachNone,
853 To: "func",
854 },
855 "xdp/foo": {
856 Pt: XDP,
857 At: AttachNone,
858 To: "",
859 },
860 "xdp_devmap/foo": {
861 Pt: XDP,
862 At: AttachXDPDevMap,
863 To: "foo",
864 },
865 "cgroup_skb/ingress": {
866 Pt: CGroupSKB,
867 At: AttachCGroupInetIngress,
868 To: "",
869 },
870 "iter/bpf_map": {
871 Pt: Tracing,
872 At: AttachTraceIter,
873 To: "bpf_map",
874 },
875 "lsm.s/file_ioctl_sleepable": {
876 Pt: LSM,
877 At: AttachLSMMac,
878 To: "file_ioctl_sleepable",
879 Fl: unix.BPF_F_SLEEPABLE,
880 },
881 "lsm/file_ioctl": {
882 Pt: LSM,
883 At: AttachLSMMac,
884 To: "file_ioctl",
885 },
886 "sk_skb/stream_verdict/foo": {
887 Pt: SkSKB,
888 At: AttachSkSKBStreamVerdict,
889 To: "",
890 },
891 "sk_skb/bar": {
892 Pt: SkSKB,
893 At: AttachNone,
894 To: "",
895 },
896 }
897
898 for section, want := range testcases {
899 pt, at, fl, to := getProgType(section)
900
901 if diff := cmp.Diff(want, progTypeTestData{Pt: pt, At: at, Fl: fl, To: to}); diff != "" {
902 t.Errorf("getProgType mismatch (-want +got):\n%s", diff)
903 }
904 }
905 }
906
View as plain text