1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
//go:build !windows
package gen
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
type CompileArgs struct {
// Which compiler to use.
CC string
// Command used to strip DWARF from the ELF.
Strip string
// Flags to pass to the compiler.
Flags []string
// Absolute working directory
Workdir string
// Absolute input file name
Source string
// Absolute output file name
Dest string
// Target to compile for, defaults to compiling generic BPF in host endianness.
Target Target
DisableStripping bool
}
// Compile C to a BPF ELF file.
func Compile(args CompileArgs) error {
// Default cflags that can be overridden by args.cFlags
overrideFlags := []string{
// Code needs to be optimized, otherwise the verifier will often fail
// to understand it.
"-O2",
// Clang defaults to mcpu=probe which checks the kernel that we are
// compiling on. This isn't appropriate for ahead of time
// compiled code so force the most compatible version.
"-mcpu=v1",
}
cmd := exec.Command(args.CC, append(overrideFlags, args.Flags...)...)
cmd.Stderr = os.Stderr
inputDir := filepath.Dir(args.Source)
relInputDir, err := filepath.Rel(args.Workdir, inputDir)
if err != nil {
return err
}
target := args.Target
if target == (Target{}) {
target.clang = "bpf"
}
// C flags that can't be overridden.
if linux := target.linux; linux != "" {
cmd.Args = append(cmd.Args, "-D__TARGET_ARCH_"+linux)
}
cmd.Args = append(cmd.Args,
"-Wunused-command-line-argument",
"-target", target.clang,
"-c", args.Source,
"-o", args.Dest,
// Don't include clang version
"-fno-ident",
// Don't output inputDir into debug info
"-fdebug-prefix-map="+inputDir+"="+relInputDir,
"-fdebug-compilation-dir", ".",
// We always want BTF to be generated, so enforce debug symbols
"-g",
fmt.Sprintf("-D__BPF_TARGET_MISSING=%q", "GCC error \"The eBPF is using target specific macros, please provide -target that is not bpf, bpfel or bpfeb\""),
)
cmd.Dir = args.Workdir
if err := cmd.Run(); err != nil {
return err
}
if args.DisableStripping {
return nil
}
cmd = exec.Command(args.Strip, "-g", args.Dest)
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("strip %s: %w", args.Dest, err)
}
return nil
}
|