Operations 21 min read

Mastering Pure C eBPF Compilation from Kernel Source: A Step‑by‑Step Guide

This article walks you through the complete process of compiling pure‑C eBPF programs using the Linux 4.18 kernel source, covering environment setup, kernel source acquisition, essential build steps, detailed make command analysis, and verification of both user‑space and kernel‑space components.

Alibaba Cloud Big Data AI Platform
Alibaba Cloud Big Data AI Platform
Alibaba Cloud Big Data AI Platform
Mastering Pure C eBPF Compilation from Kernel Source: A Step‑by‑Step Guide

1. Introduction

Understanding and mastering pure‑C eBPF compilation deepens knowledge of eBPF principles and enables development of high‑performance eBPF programs tailored to specific business needs.

2. Acquiring the Kernel Source

Most servers run CentOS 8 + 4.18 kernel; we recommend using this version. If you lack a compatible OS, you can purchase a CentOS 8 or Anolis 8 instance from Alibaba Cloud.

$ cat /etc/centos-release
CentOS Linux release 8.5.2111
$ uname -r
4.18.0-348.7.1.el8_5.x86_64

Download the 4.18 source:

$ cd /tmp/
$ wget https://mirrors.aliyun.com/linux-kernel/v4.x/linux-4.18.tar.gz
$ tar -zxvf linux-4.18.tar.gz
$ cd linux-4.18

Ensure the kernel version matches the OS because eBPF checks VERSION, PATCHLEVEL, and SUBLEVEL macros.

$ cat Makefile | grep -P '^VERSION|^PATCHLEVEL|^SUBLEVEL'
VERSION = 4
PATCHLEVEL = 18
SUBLEVEL = 0

3. Initializing the Basic Environment

Install required packages:

$ sudo yum install bison flex openssl-devel
$ sudo yum install clang llvm elfutils-libelf-devel

4. Compiling the Kernel‑Source eBPF Sample

Initialize the kernel build environment:

$ cd /tmp/linux-4.18
$ make oldconfig && make init
$ make headers_install

Compile the user‑space part of the sample:

$ make M=samples/bpf
$ gcc -g -fPIC -c -o libbpf.o libbpf.c
$ gcc -g -fPIC -c -o bpf.o bpf.c
$ gcc -g -fPIC -c -o btf.o btf.c
$ gcc -g -fPIC -c -o nlattr.o nlattr.c
$ ld -r -o libbpf-in.o libbpf.o bpf.o nlattr.o btf.o
$ ar rcs libbpf.a libbpf-in.o
$ gcc -O2 -std=gnu89 -c -o bpf_load.o bpf_load.c
$ gcc -O2 -std=gnu89 -c -o trace_output_user.o trace_output_user.c
$ gcc -O2 -std=gnu89 -c -o trace_helpers.o trace_helpers.c
$ gcc -o trace_output bpf_load.o trace_output_user.o trace_helpers.o libbpf.a -lelf -lrt
$ clang -O2 -emit-llvm -c trace_output_kern.c -o - | llc -march=bpf -filetype=obj -o trace_output_kern.o

Run the compiled sample to verify:

$ sudo ./samples/bpf/trace_output
recv 1766352 events per sec

5. Extracting Key Steps of the eBPF Build Process

The make headers_install step generates a usr/include/ directory with ~931 files, of which 677 match the system’s /usr/include/ provided by the kernel-headers package, effectively reproducing the kernel‑headers content.

$ make headers_install
$ ls usr/include/ -R | wc -l
931
$ diff -rs usr/include/ /usr/include/ | grep '^Files' | wc -l
677

6. Manual Step‑by‑Step Analysis

We break the compilation into steps A‑H, showing exact commands and the purpose of each flag.

# Step A1‑A4: Compile libbpf, bpf, btf, nlattr with -fPIC and include paths.
# Step B: ld -r to combine objects.
# Step C: ar rcs to create static libbpf.a.
# Step D‑F: Compile user‑space objects with -O2, -std=gnu89, and multiple -I include directories.
# Step G: Link final trace_output binary with libbpf.a, -lelf, -lrt.
# Step H: clang + llc to compile kernel‑space eBPF object.

7. Exploring Kernel 4.9 Differences

On kernel 4.9 the final link command uses libbpf.o instead of the static library:

$ gcc -o samples/bpf/trace_output samples/bpf/bpf_load.o samples/bpf/libbpf.o samples/bpf/trace_output_user.o -lelf -lrt

8. Further Exploration

This is the first article of the eBPF hands‑on series; the next part will investigate compiling eBPF programs completely independent of the kernel source.

9. Appendix: Full Command List for Manual Pure‑C eBPF Compilation

cd /tmp/
rm -fr /tmp/linux-4.18
tar -zxvf linux-4.18.tar.gz
cd /tmp/linux-4.18
make oldconfig && make init
make headers_install
cd tools/lib/bpf/
# A1‑A4
gcc -g -DHAVE_LIBELF_MMAP_SUPPORT -DCOMPAT_NEED_REALLOCARRAY -fPIC -I. -I/tmp/linux-4.18/tools/include -I/tmp/linux-4.18/tools/arch/x86/include/uapi -I/tmp/linux-4.18/tools/include/uapi -I/tmp/linux-4.18/tools/perf -D"BUILD_STR(s)=#s" -c -o libbpf.o libbpf.c
gcc -g -DHAVE_LIBELF_MMAP_SUPPORT -DCOMPAT_NEED_REALLOCARRAY -fPIC -I. -I/tmp/linux-4.18/tools/include -I/tmp/linux-4.18/tools/arch/x86/include/uapi -I/tmp/linux-4.18/tools/include/uapi -I/tmp/linux-4.18/tools/perf -D"BUILD_STR(s)=#s" -c -o bpf.o bpf.c
gcc -g -DHAVE_LIBELF_MMAP_SUPPORT -DCOMPAT_NEED_REALLOCARRAY -fPIC -I. -I/tmp/linux-4.18/tools/include -I/tmp/linux-4.18/tools/arch/x86/include/uapi -I/tmp/linux-4.18/tools/include/uapi -I/tmp/linux-4.18/tools/perf -D"BUILD_STR(s)=#s" -c -o btf.o btf.c
gcc -g -DHAVE_LIBELF_MMAP_SUPPORT -DCOMPAT_NEED_REALLOCARRAY -fPIC -I. -I/tmp/linux-4.18/tools/include -I/tmp/linux-4.18/tools/arch/x86/include/uapi -I/tmp/linux-4.18/tools/include/uapi -I/tmp/linux-4.18/tools/perf -D"BUILD_STR(s)=#s" -c -o nlattr.o nlattr.c
# B
ld -r -o libbpf-in.o libbpf.o bpf.o nlattr.o btf.o
# C
ar rcs libbpf.a libbpf-in.o
# D‑F
gcc -O2 -fomit-frame-pointer -std=gnu89 -I./usr/include -I./tools/lib/ -I./tools/testing/selftests/bpf/ -I./tools/lib/ -I./tools/include -I./tools/perf -I./usr/include -Wno-unused-variable -c -o samples/bpf/bpf_load.o samples/bpf/bpf_load.c
gcc -O2 -fomit-frame-pointer -std=gnu89 -I./usr/include -I./tools/lib/ -I./tools/testing/selftests/bpf/ -I./tools/lib/ -I./tools/include -I./tools/perf -I./tools/lib/bpf/ -c -o samples/bpf/trace_output_user.o samples/bpf/trace_output_user.c
gcc -O2 -fomit-frame-pointer -std=gnu89 -I./usr/include -I./tools/lib/ -I./tools/testing/selftests/bpf/ -I./tools/lib/ -I./tools/include -I./tools/perf -I./tools/lib/bpf/ -c -o samples/bpf/../../tools/testing/selftests/bpf/trace_helpers.o samples/bpf/../../tools/testing/selftests/bpf/trace_helpers.c
# G
gcc -o samples/bpf/trace_output samples/bpf/bpf_load.o samples/bpf/trace_output_user.o samples/bpf/../../tools/testing/selftests/bpf/trace_helpers.o /tmp/linux-4.18/samples/bpf/../../tools/lib/bpf/libbpf.a -lelf -lrt
# H
clang -nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/8/include -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -Isamples/bpf -I./tools/testing/selftests/bpf/ -D__KERNEL__ -D__BPF_TRACING__ -D__TARGET_ARCH_x86 -O2 -emit-llvm -c samples/bpf/trace_output_kern.c -o - | llc -march=bpf -filetype=obj -o samples/bpf/trace_output_kern.o
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KernelCompilationCLinuxeBPF
Alibaba Cloud Big Data AI Platform
Written by

Alibaba Cloud Big Data AI Platform

The Alibaba Cloud Big Data AI Platform builds on Alibaba’s leading cloud infrastructure, big‑data and AI engineering capabilities, scenario algorithms, and extensive industry experience to offer enterprises and developers a one‑stop, cloud‑native big‑data and AI capability suite. It boosts AI development efficiency, enables large‑scale AI deployment across industries, and drives business value.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.