Skip to content

Commit 306b267

Browse files
rdnaAlexei Starovoitov
authored andcommitted
libbpf: Verify versioned symbols
Since ABI versioning info is kept separately from the code it's easy to forget to update it while adding a new API. Add simple verification that all global symbols exported with LIBBPF_API are versioned in libbpf.map version script. The idea is to check that number of global symbols in libbpf-in.o, that is the input to the linker, matches with number of unique versioned symbols in libbpf.so, that is the output of the linker. If these numbers don't match, it may mean some symbol was not versioned and make will fail. "Unique" means that if a symbol is present in more than one version of ABI due to ABI changes, it'll be counted once. Another option to calculate number of global symbols in the "input" could be to count number of LIBBPF_ABI entries in C headers but it seems to be fragile. Example of output when a symbol is missing in version script: ... LD libbpf-in.o LINK libbpf.a LINK libbpf.so Warning: Num of global symbols in libbpf-in.o (115) does NOT match with num of versioned symbols in libbpf.so (114). Please make sure all LIBBPF_API symbols are versioned in libbpf.map. make: *** [check_abi] Error 1 Signed-off-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 16192a7 commit 306b267

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

tools/lib/bpf/Makefile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ BPF_IN := $(OUTPUT)libbpf-in.o
147147
LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
148148
VERSION_SCRIPT := libbpf.map
149149

150+
GLOBAL_SYM_COUNT = $(shell readelf -s $(BPF_IN) | \
151+
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}')
152+
VERSIONED_SYM_COUNT = $(shell readelf -s $(OUTPUT)libbpf.so | \
153+
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
154+
150155
CMD_TARGETS = $(LIB_FILE)
151156

152157
CXX_TEST_TARGET = $(OUTPUT)test_libbpf
@@ -159,7 +164,7 @@ TARGETS = $(CMD_TARGETS)
159164

160165
all: fixdep all_cmd
161166

162-
all_cmd: $(CMD_TARGETS)
167+
all_cmd: $(CMD_TARGETS) check
163168

164169
$(BPF_IN): force elfdep bpfdep
165170
@(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
@@ -186,6 +191,18 @@ $(OUTPUT)libbpf.a: $(BPF_IN)
186191
$(OUTPUT)test_libbpf: test_libbpf.cpp $(OUTPUT)libbpf.a
187192
$(QUIET_LINK)$(CXX) $^ -lelf -o $@
188193

194+
check: check_abi
195+
196+
check_abi: $(OUTPUT)libbpf.so
197+
@if [ "$(GLOBAL_SYM_COUNT)" != "$(VERSIONED_SYM_COUNT)" ]; then \
198+
echo "Warning: Num of global symbols in $(BPF_IN)" \
199+
"($(GLOBAL_SYM_COUNT)) does NOT match with num of" \
200+
"versioned symbols in $^ ($(VERSIONED_SYM_COUNT))." \
201+
"Please make sure all LIBBPF_API symbols are" \
202+
"versioned in $(VERSION_SCRIPT)." >&2; \
203+
exit 1; \
204+
fi
205+
189206
define do_install
190207
if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
191208
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \

0 commit comments

Comments
 (0)