-
Notifications
You must be signed in to change notification settings - Fork 9
/
Makefile
157 lines (132 loc) · 4.82 KB
/
Makefile
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
OUTPUT := .output
CLANG ?= clang
OPT ?= opt
LLC ?= llc
JQ ?= jq
SED ?= sed
ARCH := $(shell uname -m | $(SED) 's/x86_64/x86/' | $(SED) 's/aarch64/arm64/' | $(SED) 's/ppc64le/powerpc/' | $(SED) 's/mips.*/mips/')
BPFCOVLIB_DIR ?= $(abspath ../../build/lib)
BPFTOOL_LOCAL ?= ../tools/bpftool
BPFTOOL = $(abspath $(BPFTOOL_LOCAL))
LIBBPF_DIR := $(abspath ../libbpf)
LIBBPF_SRC := $(abspath $(LIBBPF_DIR)/src)
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
VMLINUX := $(abspath $(OUTPUT)/vmlinux/vmlinux.h)
INCLUDES := -I$(LIBBPF_DIR)/include/uapi -I$(dir $(VMLINUX))
CLANG_BPF_SYS_INCLUDES = $(shell $(CLANG) -v -E - </dev/null 2>&1 \
| $(SED) -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
# List your examples here
EXAMPLES = raw_enter fentry lsm
ifeq ($(V),1)
Q =
msg =
else
Q = @
msg = @printf ' %-8s %s%s\n' \
"$(1)" \
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
"$(if $(3), $(3))";
MAKEFLAGS += --no-print-directory
endif
.PHONY: all
all: $(EXAMPLES)
.PHONY: cov
cov: $(patsubst %,cov/%,$(EXAMPLES))
.PHONY: distclean
distclean:
$(call msg,DISTCLEAN)
$(Q)rm -rf $(OUTPUT)
$(Q)unlink $(BPFTOOL)
.PHONY: clean
clean:
$(call msg,CLEAN)
$(Q)rm -rf $(OUTPUT)/*.{o,bpf.o,skel.h}
$(Q)rm -rf $(OUTPUT)/cov
$(Q)rm -rf $(patsubst %,$(OUTPUT)/%,$(EXAMPLES))
# Create output directory
$(OUTPUT) $(OUTPUT)/cov $(OUTPUT)/libbpf:
$(call msg,MKDIR,$@)
$(Q)mkdir -p $@
# Build libbpf
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
$(call msg,LIB,$@)
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
INCLUDEDIR= LIBDIR= UAPIDIR= \
install
# Link bpftool
$(BPFTOOL): $(shell command -v bpftool)
$(call msg,BPFTOOL,$(BPFTOOL_LOCAL))
$(Q)$(shell ln -s $< $@)
$(Q)$(BPFTOOL) version -j | $(JQ) -e '.features.skeletons' || $(error "A bptfool with the skeletons feature is required")
# Generate vmlinux.h
$(VMLINUX): $(BPFTOOL) /sys/kernel/btf/vmlinux
$(call msg,MKDIR,$(dir $@))
$(Q)mkdir -p $(dir $@)
$(call msg,VMLINUX,$@)
$(Q)$(BPFTOOL) btf dump file $(word 2,$^) format c > $@
# Compile the eBPF example as is
$(OUTPUT)/%.bpf.o: %.bpf.c $(wildcard %.h) $(VMLINUX) $(LIBBPF_OBJ) | $(OUTPUT)
$(call msg,OBJ,$@)
$(Q)$(CLANG) -g -O2 \
-target bpf -D__TARGET_ARCH_$(ARCH) -I$(OUTPUT) $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
-c $(filter %.c,$^) \
-o $@
# Obtain the LLVM IR instrumenting profiling and coverage mappings
$(OUTPUT)/cov/%.bpf.ll: %.bpf.c $(wildcard %.h) $(VMLINUX) $(LIBBPF_OBJ) | $(OUTPUT)/cov
$(call msg,LL,$@)
$(Q)$(CLANG) -g -O2 \
-target bpf -D__TARGET_ARCH_$(ARCH) -I$(OUTPUT)/cov $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
-fprofile-instr-generate -fcoverage-mapping \
-emit-llvm -S \
-c $(filter %.c,$^) \
-o $@
# Create the object file for coverage (not for loading, only for llvm-cov)
$(OUTPUT)/cov/%.bpf.obj: $(OUTPUT)/cov/%.bpf.ll | $(OUTPUT)/cov
$(call msg,ARCHIVE,$@)
$(Q)$(OPT) \
-load $(BPFCOVLIB_DIR)/libBPFCov.so -strip-initializers-only -bpf-cov $< \
| $(LLC) -march=bpf -filetype=obj -o $@
# Make the LLVM IR valid for eBPF
$(OUTPUT)/cov/%.bpf.cov.ll: $(OUTPUT)/cov/%.bpf.ll | $(OUTPUT)/cov
$(call msg,COV,$@)
$(Q)$(OPT) \
-load-pass-plugin $(BPFCOVLIB_DIR)/libBPFCov.so -passes="bpf-cov" \
-S $< -o $@
# Build the instrumented ELF
$(patsubst %,$(OUTPUT)/cov/%.bpf.o,$(EXAMPLES)): %.bpf.o: %.bpf.cov.ll %.bpf.obj
$(OUTPUT)/cov/%.bpf.o: $(OUTPUT)/cov/%.bpf.cov.ll | $(OUTPUT)/cov
$(call msg,OBJ,$@)
$(Q)$(LLC) -march=bpf -filetype=obj -o $@ $<
# Generate the skeleton for the eBPF example as is
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o $(BPFTOOL) | $(OUTPUT)
$(call msg,SKEL,$@)
$(Q)$(BPFTOOL) gen skeleton $< name $* > $@
# Generate the skeleton for the instrumented ELF
$(OUTPUT)/cov/%.skel.h: $(OUTPUT)/cov/%.bpf.o $(BPFTOOL) | $(OUTPUT)/cov
$(call msg,SKEL,$@)
$(Q)$(BPFTOOL) gen skeleton $< name $* > $@
# Build userspace code
$(patsubst %,$(OUTPUT)/%.o,$(EXAMPLES)): %.o: %.skel.h
# Build the eBPF application as is
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
$(call msg,CC,$@)
$(Q)$(CC) -g -Wall -I$(OUTPUT) $(INCLUDES) -c $(filter %.c,$^) -o $@
# Build userspace code using the instrumented skeleton
$(patsubst %,$(OUTPUT)/cov/%.o,$(EXAMPLES)): %.o: %.skel.h
# Build the instrumented eBPF application
$(OUTPUT)/cov/%.o: %.c $(wildcard %.h) | $(OUTPUT)/cov
$(call msg,CC,$@)
$(Q)$(CC) -g -Wall -I$(OUTPUT)/cov $(INCLUDES) -c $(filter %.c,$^) -o $@
# Build the binary as is
%: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
$(call msg,BIN,$(OUTPUT)/$@)
$(Q)$(CC) -g -Wall $^ -lelf -lz -o $(OUTPUT)/$@
# Build the instrumented eBPF binary
cov/%: $(OUTPUT)/cov/%.o $(LIBBPF_OBJ) | $(OUTPUT)/cov
$(call msg,BIN,$(OUTPUT)/$@)
$(Q)$(CC) -g -Wall $^ -lelf -lz -o $(OUTPUT)/$@
# Delete failed targets
.DELETE_ON_ERROR:
# Keep intermediate (.bpf.o, etc.) targets
.SECONDARY: