[bpf-next] selftests/bpf: add bpf-gcc support
diff mbox series

Message ID 20190910234140.53363-1-iii@linux.ibm.com
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series
  • [bpf-next] selftests/bpf: add bpf-gcc support
Related show

Commit Message

Ilya Leoshkevich Sept. 10, 2019, 11:41 p.m. UTC
Now that binutils and gcc support for BPF is upstream, make use of it in
BPF selftests using alu32-like approach. Share as much as possible of
CFLAGS calculation with clang.

In order to activate the new bpf-gcc support, one needs to configure
binutils and gcc with --target=bpf and make them available in $PATH. In
particular, gcc must be installed as `bpf-gcc`, which is the default.

Right now with binutils 25a2915e8dba and gcc r275589 only a handful of
tests work:

	# ./test_progs_bpf_gcc
	Summary: 5/39 PASSED, 1 SKIPPED, 100 FAILED

The reason is that a lot of progs fail to build with the following
errors:

	error: indirect call in function, which are not supported by eBPF
	error: too many function arguments for eBPF

The next step is to understand those issues and fix them.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 tools/testing/selftests/bpf/Makefile | 61 +++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 15 deletions(-)

Comments

Jose E. Marchesi Sept. 11, 2019, 10:30 a.m. UTC | #1
Hi Ilya.

    Now that binutils and gcc support for BPF is upstream, make use of it in
    BPF selftests using alu32-like approach. Share as much as possible of
    CFLAGS calculation with clang.

    In order to activate the new bpf-gcc support, one needs to configure
    binutils and gcc with --target=bpf and make them available in $PATH. In
    particular, gcc must be installed as `bpf-gcc`, which is the default.
    
    Right now with binutils 25a2915e8dba and gcc r275589 only a handful of
    tests work:
    
    	# ./test_progs_bpf_gcc
    	Summary: 5/39 PASSED, 1 SKIPPED, 100 FAILED
    
    The reason is that a lot of progs fail to build with the following
    errors:
    
    	error: indirect call in function, which are not supported by eBPF
    	error: too many function arguments for eBPF
    
    The next step is to understand those issues and fix them.

Will install your patch and take a look.

Maybe GCC is not inlining something it should be inlining, or clang may
be silently generating callx %reg instructions, or maybe there are bugs
in my diagnostics... in any case this is useful feedback :)

Thanks!
Ilya Leoshkevich Sept. 11, 2019, 11:12 a.m. UTC | #2
> Am 11.09.2019 um 11:30 schrieb Jose E. Marchesi <jose.marchesi@oracle.com>:
> 
> 
> Hi Ilya.
> 
>    Now that binutils and gcc support for BPF is upstream, make use of it in
>    BPF selftests using alu32-like approach. Share as much as possible of
>    CFLAGS calculation with clang.
> 
>    In order to activate the new bpf-gcc support, one needs to configure
>    binutils and gcc with --target=bpf and make them available in $PATH. In
>    particular, gcc must be installed as `bpf-gcc`, which is the default.
> 
>    Right now with binutils 25a2915e8dba and gcc r275589 only a handful of
>    tests work:
> 
>    	# ./test_progs_bpf_gcc
>    	Summary: 5/39 PASSED, 1 SKIPPED, 100 FAILED
> 
>    The reason is that a lot of progs fail to build with the following
>    errors:
> 
>    	error: indirect call in function, which are not supported by eBPF
>    	error: too many function arguments for eBPF
> 
>    The next step is to understand those issues and fix them.
> 
> Will install your patch and take a look.
> 
> Maybe GCC is not inlining something it should be inlining, or clang may
> be silently generating callx %reg instructions, or maybe there are bugs
> in my diagnostics... in any case this is useful feedback :)
> 
> Thanks!

Hi Jose,

I have realised this morning that I must have missed what you said
yesterday about bpf-helpers.h -- using gcc version of this header clears
a lot of errors, but the remaning ones are more curious. I plan to
post a v2 of this patch today or tomorrow with more details on the
remaining failures.

Thanks!
Ilya

Patch
diff mbox series

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 7f3196af1ae4..5493882fc19b 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -17,6 +17,7 @@  LLC		?= llc
 LLVM_OBJCOPY	?= llvm-objcopy
 LLVM_READELF	?= llvm-readelf
 BTF_PAHOLE	?= pahole
+BPF_GCC		?= $(shell command -v bpf-gcc;)
 CFLAGS += -g -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(BPFDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include \
 	  -Dbpf_prog_load=bpf_prog_test_load \
 	  -Dbpf_load_program=bpf_test_load_program
@@ -46,6 +47,10 @@  ifneq ($(SUBREG_CODEGEN),)
 TEST_GEN_FILES += $(patsubst %.o,alu32/%.o, $(BPF_OBJ_FILES))
 endif
 
+ifneq ($(BPF_GCC),)
+TEST_GEN_FILES += $(patsubst %.o,bpf_gcc/%.o, $(BPF_OBJ_FILES))
+endif
+
 # Order correspond to 'make run_tests' order
 TEST_PROGS := test_kmod.sh \
 	test_libbpf.sh \
@@ -137,16 +142,19 @@  endif
 #
 # Use '-idirafter': Don't interfere with include mechanics except where the
 # build would have failed anyways.
-CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \
+define get_sys_includes
+$(shell $(1) -v -E - </dev/null 2>&1 \
 	| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
+endef
+CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
+BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \
+	     -D__TARGET_ARCH_$(SRCARCH)
 
-CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \
-	      $(CLANG_SYS_INCLUDES) \
-	      -Wno-compare-distinct-pointer-types \
-	      -D__TARGET_ARCH_$(SRCARCH)
+CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \
+	       -Wno-compare-distinct-pointer-types
 
-$(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline
-$(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline
+$(OUTPUT)/test_l4lb_noinline.o: BPF_CFLAGS += -fno-inline
+$(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline
 
 $(OUTPUT)/test_queue_map.o: test_queue_stack_map.h
 $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h
@@ -163,12 +171,12 @@  BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \
 			  /bin/rm -f ./llvm_btf_verify.o)
 
 ifneq ($(BTF_LLVM_PROBE),)
-	CLANG_FLAGS += -g
+	BPF_CFLAGS += -g
 else
 ifneq ($(BTF_LLC_PROBE),)
 ifneq ($(BTF_PAHOLE_PROBE),)
 ifneq ($(BTF_OBJCOPY_PROBE),)
-	CLANG_FLAGS += -g
+	BPF_CFLAGS += -g
 	LLC_FLAGS += -mattr=dwarfris
 	DWARF2BTF = y
 endif
@@ -202,8 +210,8 @@  $(ALU32_BUILD_DIR)/test_progs_32: prog_tests/*.c
 
 $(ALU32_BUILD_DIR)/%.o: progs/%.c $(ALU32_BUILD_DIR)/test_progs_32 \
 					| $(ALU32_BUILD_DIR)
-	($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \
-		echo "clang failed") | \
+	($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
+		-c $< -o - || echo "clang failed") | \
 	$(LLC) -march=bpf -mattr=+alu32 -mcpu=$(CPU) $(LLC_FLAGS) \
 		-filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
@@ -211,10 +219,33 @@  ifeq ($(DWARF2BTF),y)
 endif
 endif
 
+ifneq ($(BPF_GCC),)
+GCC_SYS_INCLUDES = $(call get_sys_includes,gcc)
+BPF_GCC_CFLAGS = $(GCC_SYS_INCLUDES)
+BPF_GCC_BUILD_DIR = $(OUTPUT)/bpf_gcc
+TEST_CUSTOM_PROGS += $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc
+$(BPF_GCC_BUILD_DIR):
+	mkdir -p $@
+
+$(BPF_GCC_BUILD_DIR)/urandom_read: $(OUTPUT)/urandom_read | $(BPF_GCC_BUILD_DIR)
+	cp $< $@
+
+$(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc: $(OUTPUT)/test_progs \
+					 | $(BPF_GCC_BUILD_DIR)
+	cp $< $@
+
+$(BPF_GCC_BUILD_DIR)/%.o: progs/%.c $(BPF_GCC_BUILD_DIR)/test_progs_bpf_gcc \
+			  | $(BPF_GCC_BUILD_DIR)
+	$(BPF_GCC) $(BPF_CFLAGS) $(BPF_GCC_CFLAGS) -O2 -c $< -o $@
+ifeq ($(DWARF2BTF),y)
+	$(BTF_PAHOLE) -J $@
+endif
+endif
+
 # Have one program compiled without "-target bpf" to test whether libbpf loads
 # it successfully
 $(OUTPUT)/test_xdp.o: progs/test_xdp.c
-	($(CLANG) $(CLANG_FLAGS) -O2 -emit-llvm -c $< -o - || \
+	($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -emit-llvm -c $< -o - || \
 		echo "clang failed") | \
 	$(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
@@ -222,8 +253,8 @@  ifeq ($(DWARF2BTF),y)
 endif
 
 $(OUTPUT)/%.o: progs/%.c
-	($(CLANG) $(CLANG_FLAGS) -O2 -target bpf -emit-llvm -c $< -o - || \
-		echo "clang failed") | \
+	($(CLANG) $(BPF_CFLAGS) $(CLANG_CFLAGS) -O2 -target bpf -emit-llvm \
+		-c $< -o - || echo "clang failed") | \
 	$(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
 	$(BTF_PAHOLE) -J $@
@@ -282,6 +313,6 @@  $(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR)
 		  echo '#endif' \
 		 ) > $(VERIFIER_TESTS_H))
 
-EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) \
+EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(ALU32_BUILD_DIR) $(BPF_GCC_BUILD_DIR) \
 	$(VERIFIER_TESTS_H) $(PROG_TESTS_H) $(MAP_TESTS_H) \
 	feature