File: compile.go

package info (click to toggle)
golang-github-cilium-ebpf 0.17.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 4,684 kB
  • sloc: ansic: 1,259; makefile: 127; python: 113; awk: 29; sh: 24
file content (93 lines) | stat: -rw-r--r-- 2,279 bytes parent folder | download
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
}