github.com/cilium/ebpf@v0.16.0/cmd/bpf2go/gen/target.go (about) 1 package gen 2 3 import ( 4 "errors" 5 "fmt" 6 "go/build/constraint" 7 "maps" 8 "runtime" 9 "slices" 10 ) 11 12 var ErrInvalidTarget = errors.New("unsupported target") 13 14 var targetsByGoArch = map[GoArch]Target{ 15 "386": {"bpfel", "x86"}, 16 "amd64": {"bpfel", "x86"}, 17 "arm": {"bpfel", "arm"}, 18 "arm64": {"bpfel", "arm64"}, 19 "loong64": {"bpfel", "loongarch"}, 20 "mips": {"bpfeb", "mips"}, 21 "mipsle": {"bpfel", ""}, 22 "mips64": {"bpfeb", ""}, 23 "mips64le": {"bpfel", ""}, 24 "ppc64": {"bpfeb", "powerpc"}, 25 "ppc64le": {"bpfel", "powerpc"}, 26 "riscv64": {"bpfel", "riscv"}, 27 "s390x": {"bpfeb", "s390"}, 28 } 29 30 type Target struct { 31 // Clang arch string, used to define the clang -target flag, as per 32 // "clang -print-targets". 33 clang string 34 // Linux arch string, used to define __TARGET_ARCH_xzy macros used by 35 // https://github.com/libbpf/libbpf/blob/master/src/bpf_tracing.h 36 linux string 37 } 38 39 // TargetsByGoArch returns all supported targets. 40 func TargetsByGoArch() map[GoArch]Target { 41 return maps.Clone(targetsByGoArch) 42 } 43 44 // IsGeneric returns true if the target will compile to generic BPF. 45 func (tgt *Target) IsGeneric() bool { 46 return tgt.linux == "" 47 } 48 49 // Suffix returns a a string suitable for appending to a file name to 50 // identify the target. 51 func (tgt *Target) Suffix() string { 52 // The output filename must not match any of the following patterns: 53 // 54 // *_GOOS 55 // *_GOARCH 56 // *_GOOS_GOARCH 57 // 58 // Otherwise it is interpreted as a build constraint by the Go toolchain. 59 stem := tgt.clang 60 if tgt.linux != "" { 61 stem = fmt.Sprintf("%s_%s", tgt.linux, tgt.clang) 62 } 63 return stem 64 } 65 66 // ObsoleteSuffix returns an obsolete suffix for a subset of targets. 67 // 68 // It's used to work around an old bug and should not be used in new code. 69 func (tgt *Target) ObsoleteSuffix() string { 70 if tgt.linux == "" { 71 return "" 72 } 73 74 return fmt.Sprintf("%s_%s", tgt.clang, tgt.linux) 75 } 76 77 // GoArch is a Go arch string. 78 // 79 // See https://go.dev/doc/install/source#environment for valid GOARCHes when 80 // GOOS=linux. 81 type GoArch string 82 83 type GoArches []GoArch 84 85 // Constraints is satisfied when GOARCH is any of the arches. 86 func (arches GoArches) Constraint() constraint.Expr { 87 var archConstraint constraint.Expr 88 for _, goarch := range arches { 89 tag := &constraint.TagExpr{Tag: string(goarch)} 90 archConstraint = orConstraints(archConstraint, tag) 91 } 92 return archConstraint 93 } 94 95 // FindTarget turns a list of identifiers into targets and their respective 96 // GoArches. 97 // 98 // The following are valid identifiers: 99 // 100 // - bpf: compile generic BPF for host endianness 101 // - bpfel: compile generic BPF for little endian 102 // - bpfeb: compile generic BPF for big endian 103 // - native: compile BPF for host target 104 // - $GOARCH: compile BPF for $GOARCH target 105 // 106 // Generic BPF can run on any target goarch with the correct endianness, 107 // but doesn't have access to some arch specific tracing functionality. 108 func FindTarget(id string) (Target, GoArches, error) { 109 switch id { 110 case "bpf", "bpfel", "bpfeb": 111 var goarches []GoArch 112 for arch, archTarget := range targetsByGoArch { 113 if archTarget.clang == id { 114 // Include tags for all goarches that have the same endianness. 115 goarches = append(goarches, arch) 116 } 117 } 118 slices.Sort(goarches) 119 return Target{id, ""}, goarches, nil 120 121 case "native": 122 id = runtime.GOARCH 123 fallthrough 124 125 default: 126 archTarget, ok := targetsByGoArch[GoArch(id)] 127 if !ok || archTarget.linux == "" { 128 return Target{}, nil, fmt.Errorf("%q: %w", id, ErrInvalidTarget) 129 } 130 131 var goarches []GoArch 132 for goarch, lt := range targetsByGoArch { 133 if lt == archTarget { 134 // Include tags for all goarches that have the same 135 // target. 136 goarches = append(goarches, goarch) 137 } 138 } 139 140 slices.Sort(goarches) 141 return archTarget, goarches, nil 142 } 143 } 144 145 func orConstraints(x, y constraint.Expr) constraint.Expr { 146 if x == nil { 147 return y 148 } 149 150 if y == nil { 151 return x 152 } 153 154 return &constraint.OrExpr{X: x, Y: y} 155 }