github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/docs/ebpf/guides/portable-ebpf.md (about)

     1  # Shipping Portable eBPF-powered Applications
     2  
     3  !!! incomplete
     4      This guide builds on Getting Started.
     5      
     6      Document what the various ways are for making tools portable across kernel
     7      versions and what the various CO-RE techniques are.
     8  
     9  !!! tip ""
    10      We recommend building eBPF C code from within a container with a stable LLVM
    11      toolchain, as well as checking all generated `.o` and `.go` files into
    12      source control. This buys you fully-reproducible builds, prevents bugs due
    13      to team members using different LLVM versions and makes your packages fully
    14      independent and `go run`nable. It also prevents PII from leaking into ELFs
    15      in the form of absolute paths to `.c` source files in DWARF info.
    16  
    17  ### Cross-compiling
    18  
    19  You may have noticed bpf2go generating two sets of files:
    20  
    21  - `*_bpfel.o` and `*_bpfel.go` for little-endian architectures like amd64,
    22    arm64, riscv64 and loong64
    23  - `*_bpfeb.o` and `*_bpfeb.go` for big-endian architectures like s390(x), mips
    24    and sparc
    25  
    26  Both sets of .go files contain a `//go:embed` statement that slurps the contents
    27  of the respective .o files into a byte slice at compile time. The result is a
    28  standalone Go application binary that can be deployed to a target machine
    29  without any of the .o files included. To further reduce runtime dependencies,
    30  add `CGO_ENABLED=0` to `go build` and your application won't depend on libc.
    31  (assuming none of your other dependencies require cgo)
    32  
    33  Moreover, because both eBPF objects and Go scaffolding are generated for both
    34  big- and little-endian architectures, cross-compiling your Go application is as
    35  simple as setting the right `GOARCH` value at compile time.
    36  
    37  Pulling it all together, for building an eBPF-powered Go application for a
    38  Raspberry Pi running a 64-bit Linux distribution:
    39  
    40  ```shell-session
    41  CGO_ENABLED=0 GOARCH=arm64 go build
    42  ```
    43  
    44  ### Compile Once - Run Everywhere?
    45  
    46  Since we can generate a standalone binary and deploy it to any system, does that
    47  mean tools built using {{ proj }} will magically work anywhere? Unfortunately,
    48  no, not really.
    49  
    50  The kernel's internal data structures change as the kernel progresses in
    51  development, just like any other software. Differences in compile-time
    52  configuration affect data structures and the presence of certain kernel symbols.
    53  This means that, even when using the exact same kernel release, no two Linux
    54  distributions will be the same when it comes to data layout.
    55  
    56  This is problematic for authors that want to ship a single binary to their users
    57  and expect it to work across multiple distributions and kernel versions. In
    58  response to this, the term *Compile Once - Run Everywhere* was coined to
    59  describe the collection of techniques employed to achieve universal
    60  interoperability for eBPF. This technique relies on type information encoded in
    61  BPF Type Format (BTF) to be shipped with the kernel so memory accesses can be
    62  adjusted right before loading the eBPF program into the kernel.
    63  
    64  Alternatively, you may opt for shipping a full LLVM compiler toolchain along
    65  with your application and recompiling the eBPF C against Linux kernel headers
    66  present on the target machine. This approach is out of scope of the {{ proj }}
    67  documentation.