github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/feature.go (about) 1 package btf 2 3 import ( 4 "errors" 5 "math" 6 7 "github.com/cilium/ebpf/internal" 8 "github.com/cilium/ebpf/internal/sys" 9 "github.com/cilium/ebpf/internal/unix" 10 ) 11 12 // haveBTF attempts to load a BTF blob containing an Int. It should pass on any 13 // kernel that supports BPF_BTF_LOAD. 14 var haveBTF = internal.NewFeatureTest("BTF", "4.18", func() error { 15 // 0-length anonymous integer 16 err := probeBTF(&Int{}) 17 if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) { 18 return internal.ErrNotSupported 19 } 20 return err 21 }) 22 23 // haveMapBTF attempts to load a minimal BTF blob containing a Var. It is 24 // used as a proxy for .bss, .data and .rodata map support, which generally 25 // come with a Var and Datasec. These were introduced in Linux 5.2. 26 var haveMapBTF = internal.NewFeatureTest("Map BTF (Var/Datasec)", "5.2", func() error { 27 if err := haveBTF(); err != nil { 28 return err 29 } 30 31 v := &Var{ 32 Name: "a", 33 Type: &Pointer{(*Void)(nil)}, 34 } 35 36 err := probeBTF(v) 37 if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) { 38 // Treat both EINVAL and EPERM as not supported: creating the map may still 39 // succeed without Btf* attrs. 40 return internal.ErrNotSupported 41 } 42 return err 43 }) 44 45 // haveProgBTF attempts to load a BTF blob containing a Func and FuncProto. It 46 // is used as a proxy for ext_info (func_info) support, which depends on 47 // Func(Proto) by definition. 48 var haveProgBTF = internal.NewFeatureTest("Program BTF (func/line_info)", "5.0", func() error { 49 if err := haveBTF(); err != nil { 50 return err 51 } 52 53 fn := &Func{ 54 Name: "a", 55 Type: &FuncProto{Return: (*Void)(nil)}, 56 } 57 58 err := probeBTF(fn) 59 if errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) { 60 return internal.ErrNotSupported 61 } 62 return err 63 }) 64 65 var haveFuncLinkage = internal.NewFeatureTest("BTF func linkage", "5.6", func() error { 66 if err := haveProgBTF(); err != nil { 67 return err 68 } 69 70 fn := &Func{ 71 Name: "a", 72 Type: &FuncProto{Return: (*Void)(nil)}, 73 Linkage: GlobalFunc, 74 } 75 76 err := probeBTF(fn) 77 if errors.Is(err, unix.EINVAL) { 78 return internal.ErrNotSupported 79 } 80 return err 81 }) 82 83 var haveEnum64 = internal.NewFeatureTest("ENUM64", "6.0", func() error { 84 if err := haveBTF(); err != nil { 85 return err 86 } 87 88 enum := &Enum{ 89 Size: 8, 90 Values: []EnumValue{ 91 {"TEST", math.MaxUint32 + 1}, 92 }, 93 } 94 95 err := probeBTF(enum) 96 if errors.Is(err, unix.EINVAL) { 97 return internal.ErrNotSupported 98 } 99 return err 100 }) 101 102 func probeBTF(typ Type) error { 103 b, err := NewBuilder([]Type{typ}) 104 if err != nil { 105 return err 106 } 107 108 buf, err := b.Marshal(nil, nil) 109 if err != nil { 110 return err 111 } 112 113 fd, err := sys.BtfLoad(&sys.BtfLoadAttr{ 114 Btf: sys.NewSlicePointer(buf), 115 BtfSize: uint32(len(buf)), 116 }) 117 118 if err == nil { 119 fd.Close() 120 } 121 122 return err 123 }