Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/bpf2go: clean up goarch / clang / linux target handling #1310

Merged
merged 2 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 38 additions & 35 deletions cmd/bpf2go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"sort"
"strings"

"golang.org/x/exp/slices"

"github.com/cilium/ebpf"
)

Expand Down Expand Up @@ -47,28 +49,23 @@ Options:
//
// Targets without a Linux string can't be used directly and are only included
// for the generic bpf, bpfel, bpfeb targets.
var targetByGoArch = map[string]target{
"386": {"bpfel", "x86"},
"amd64": {"bpfel", "x86"},
"amd64p32": {"bpfel", ""},
"arm": {"bpfel", "arm"},
"arm64": {"bpfel", "arm64"},
"loong64": {"bpfel", "loongarch"},
"mipsle": {"bpfel", ""},
"mips64le": {"bpfel", ""},
"mips64p32le": {"bpfel", ""},
"ppc64le": {"bpfel", "powerpc"},
"riscv64": {"bpfel", "riscv"},
"armbe": {"bpfeb", "arm"},
"arm64be": {"bpfeb", "arm64"},
"mips": {"bpfeb", ""},
"mips64": {"bpfeb", ""},
"mips64p32": {"bpfeb", ""},
"ppc64": {"bpfeb", "powerpc"},
"s390": {"bpfeb", "s390"},
"s390x": {"bpfeb", "s390"},
"sparc": {"bpfeb", "sparc"},
"sparc64": {"bpfeb", "sparc"},
//
// See https://go.dev/doc/install/source#environment for valid GOARCHes when
// GOOS=linux.
var targetByGoArch = map[goarch]target{
"386": {"bpfel", "x86"},
"amd64": {"bpfel", "x86"},
"arm": {"bpfel", "arm"},
"arm64": {"bpfel", "arm64"},
"loong64": {"bpfel", "loongarch"},
"mips": {"bpfeb", "mips"},
"mipsle": {"bpfel", ""},
"mips64": {"bpfeb", ""},
"mips64le": {"bpfel", ""},
"ppc64": {"bpfeb", "powerpc"},
"ppc64le": {"bpfel", "powerpc"},
"riscv64": {"bpfel", "riscv"},
"s390x": {"bpfeb", "s390"},
}

func run(stdout io.Writer, pkg, outputDir string, args []string) (err error) {
Expand Down Expand Up @@ -96,7 +93,7 @@ type bpf2go struct {
// Valid go identifier.
identStem string
// Targets to build for.
targetArches map[target][]string
targetArches map[target][]goarch
// C compiler.
cc string
// Command used to strip DWARF.
Expand Down Expand Up @@ -298,7 +295,7 @@ func (b2g *bpf2go) convertAll() (err error) {
return nil
}

func (b2g *bpf2go) convert(tgt target, arches []string) (err error) {
func (b2g *bpf2go) convert(tgt target, goarches []goarch) (err error) {
removeOnError := func(f *os.File) {
if err != nil {
os.Remove(f.Name())
Expand All @@ -323,8 +320,8 @@ func (b2g *bpf2go) convert(tgt target, arches []string) (err error) {
}

var archConstraint constraint.Expr
for _, arch := range arches {
tag := &constraint.TagExpr{Tag: arch}
for _, goarch := range goarches {
tag := &constraint.TagExpr{Tag: string(goarch)}
archConstraint = orConstraints(archConstraint, tag)
}

Expand Down Expand Up @@ -419,17 +416,23 @@ func (b2g *bpf2go) convert(tgt target, arches []string) (err error) {
}

type target struct {
// Clang arch string, used to define the clang -target flag, as per
// "clang -print-targets".
clang string
// Linux arch string, used to define __TARGET_ARCH_xzy macros used by
// https://github.com/libbpf/libbpf/blob/master/src/bpf_tracing.h
linux string
}

type goarch string

func printTargets(w io.Writer) {
var arches []string
for arch, archTarget := range targetByGoArch {
for goarch, archTarget := range targetByGoArch {
if archTarget.linux == "" {
continue
}
arches = append(arches, arch)
arches = append(arches, string(goarch))
}
sort.Strings(arches)

Expand All @@ -442,32 +445,32 @@ func printTargets(w io.Writer) {

var errInvalidTarget = errors.New("unsupported target")

func collectTargets(targets []string) (map[target][]string, error) {
result := make(map[target][]string)
func collectTargets(targets []string) (map[target][]goarch, error) {
result := make(map[target][]goarch)
for _, tgt := range targets {
switch tgt {
case "bpf", "bpfel", "bpfeb":
var goarches []string
var goarches []goarch
for arch, archTarget := range targetByGoArch {
if archTarget.clang == tgt {
// Include tags for all goarches that have the same endianness.
goarches = append(goarches, arch)
}
}
sort.Strings(goarches)
slices.Sort(goarches)
result[target{tgt, ""}] = goarches

case "native":
tgt = runtime.GOARCH
fallthrough

default:
archTarget, ok := targetByGoArch[tgt]
archTarget, ok := targetByGoArch[goarch(tgt)]
if !ok || archTarget.linux == "" {
return nil, fmt.Errorf("%q: %w", tgt, errInvalidTarget)
}

var goarches []string
var goarches []goarch
for goarch, lt := range targetByGoArch {
if lt == archTarget {
// Include tags for all goarches that have the same
Expand All @@ -476,7 +479,7 @@ func collectTargets(targets []string) (map[target][]string, error) {
}
}

sort.Strings(goarches)
slices.Sort(goarches)
result[archTarget] = goarches
}
}
Expand Down
50 changes: 34 additions & 16 deletions cmd/bpf2go/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ package main

import (
"bytes"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"testing"

"github.com/go-quicktest/qt"
"github.com/google/go-cmp/cmp"
"golang.org/x/exp/slices"
)

func TestRun(t *testing.T) {
Expand Down Expand Up @@ -127,9 +128,9 @@ func TestDisableStripping(t *testing.T) {
}

func TestCollectTargets(t *testing.T) {
clangArches := make(map[string][]string)
linuxArchesLE := make(map[string][]string)
linuxArchesBE := make(map[string][]string)
clangArches := make(map[string][]goarch)
linuxArchesLE := make(map[string][]goarch)
linuxArchesBE := make(map[string][]goarch)
for arch, archTarget := range targetByGoArch {
clangArches[archTarget.clang] = append(clangArches[archTarget.clang], arch)
if archTarget.clang == "bpfel" {
Expand All @@ -139,18 +140,18 @@ func TestCollectTargets(t *testing.T) {
linuxArchesBE[archTarget.linux] = append(linuxArchesBE[archTarget.linux], arch)
}
for i := range clangArches {
sort.Strings(clangArches[i])
slices.Sort(clangArches[i])
}
for i := range linuxArchesLE {
sort.Strings(linuxArchesLE[i])
slices.Sort(linuxArchesLE[i])
}
for i := range linuxArchesBE {
sort.Strings(linuxArchesBE[i])
slices.Sort(linuxArchesBE[i])
}

nativeTarget := make(map[target][]string)
nativeTarget := make(map[target][]goarch)
for arch, archTarget := range targetByGoArch {
if arch == runtime.GOARCH {
if arch == goarch(runtime.GOARCH) {
if archTarget.clang == "bpfel" {
nativeTarget[archTarget] = linuxArchesLE[archTarget.linux]
} else {
Expand All @@ -162,27 +163,27 @@ func TestCollectTargets(t *testing.T) {

tests := []struct {
targets []string
want map[target][]string
want map[target][]goarch
}{
{
[]string{"bpf", "bpfel", "bpfeb"},
map[target][]string{
map[target][]goarch{
{"bpf", ""}: nil,
{"bpfel", ""}: clangArches["bpfel"],
{"bpfeb", ""}: clangArches["bpfeb"],
},
},
{
[]string{"amd64", "386"},
map[target][]string{
map[target][]goarch{
{"bpfel", "x86"}: linuxArchesLE["x86"],
},
},
{
[]string{"amd64", "arm64be"},
map[target][]string{
{"bpfeb", "arm64"}: linuxArchesBE["arm64"],
{"bpfel", "x86"}: linuxArchesLE["x86"],
[]string{"amd64", "ppc64"},
map[target][]goarch{
{"bpfeb", "powerpc"}: linuxArchesBE["powerpc"],
{"bpfel", "x86"}: linuxArchesLE["x86"],
},
},
{
Expand Down Expand Up @@ -430,6 +431,23 @@ func TestParseArgs(t *testing.T) {
})
}

func TestGoarches(t *testing.T) {
exe, err := exec.LookPath("go")
if errors.Is(err, exec.ErrNotFound) {
t.Skip("go binary is not in PATH")
}
qt.Assert(t, qt.IsNil(err))

for goarch := range targetByGoArch {
t.Run(string(goarch), func(t *testing.T) {
goEnv := exec.Command(exe, "env")
goEnv.Env = []string{"GOOS=linux", "GOARCH=" + string(goarch)}
output, err := goEnv.CombinedOutput()
qt.Assert(t, qt.IsNil(err), qt.Commentf("go output is:\n%s", string(output)))
})
}
}

func clangBin(t *testing.T) string {
t.Helper()

Expand Down
2 changes: 1 addition & 1 deletion cmd/bpf2go/test/test_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cmd/bpf2go/test/test_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/examples/getting_started/counter_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/examples/getting_started/counter_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/cgroup_skb/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/cgroup_skb/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/fentry/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/fentry/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobe/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobe/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobe_percpu/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobe_percpu/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobepin/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/kprobepin/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/ringbuffer/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/ringbuffer/bpf_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/tcprtt/bpf_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading