History

kbuild: Build kernel module BTFs if BTF is enabled and pahole supports it

Detect if pahole supports split BTF generation, and generate BTF for each selected kernel module, if it does. This is exposed to Makefiles and C code as CONFIG_DEBUG_INFO_BTF_MODULES flag. Kernel module BTF has to be re-generated if either vmlinux's BTF changes or module's .ko changes. To achieve that, I needed a helper similar to if_changed, but that would allow to filter out vmlinux from the list of updated dependencies for .ko building. I've put it next to the only place that uses and needs it, but it might be a better idea to just add it along the other if_changed variants into scripts/Kbuild.include. Each kernel module's BTF deduplication is pretty fast, as it does only incremental BTF deduplication on top of already deduplicated vmlinux BTF. To show the added build time, I've first ran make only just built kernel (to establish the baseline) and then forced only BTF re-generation, without regenerating .ko files. The build was performed with -j60 parallelization on 56-core machine. The final time also includes bzImage building, so it's not a pure BTF overhead. $ time make -j60 ... make -j60 27.65s user 10.96s system 782% cpu 4.933 total $ touch ~/linux-build/default/vmlinux && time make -j60 ... make -j60 123.69s user 27.85s system 1566% cpu 9.675 total So 4.6 seconds real time, with noticeable part spent in compressed vmlinux and bzImage building. To show size savings, I've built my kernel configuration with about 700 kernel modules with full BTF per each kernel module (without deduplicating against vmlinux) and with split BTF against deduplicated vmlinux (approach in this patch). Below are top 10 modules with biggest BTF sizes. And total size of BTF data across all kernel modules. It shows that split BTF "compresses" 115MB down to 5MB total. And the biggest kernel modules get a downsize from 500-570KB down to 200-300KB. FULL BTF ======== $ for f in $(find . -name '*.ko'); do size -A -d $f | grep BTF | awk '{print $2}'; done | awk '{ s += $1 } END { print s }' 115710691 $ for f in $(find . -name '*.ko'); do printf "%s %d\n" $f $(size -A -d $f | grep BTF | awk '{print $2}'); done | sort -nr -k2 | head -n10 ./drivers/gpu/drm/i915/i915.ko 570570 ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko 520240 ./drivers/gpu/drm/radeon/radeon.ko 503849 ./drivers/infiniband/hw/mlx5/mlx5_ib.ko 491777 ./fs/xfs/xfs.ko 411544 ./drivers/net/ethernet/intel/i40e/i40e.ko 403904 ./drivers/net/ethernet/broadcom/bnx2x/bnx2x.ko 398754 ./drivers/infiniband/core/ib_core.ko 397224 ./fs/cifs/cifs.ko 386249 ./fs/nfsd/nfsd.ko 379738 SPLIT BTF ========= $ for f in $(find . -name '*.ko'); do size -A -d $f | grep BTF | awk '{print $2}'; done | awk '{ s += $1 } END { print s }' 5194047 $ for f in $(find . -name '*.ko'); do printf "%s %d\n" $f $(size -A -d $f | grep BTF | awk '{print $2}'); done | sort -nr -k2 | head -n10 ./drivers/gpu/drm/i915/i915.ko 293206 ./drivers/gpu/drm/radeon/radeon.ko 282103 ./fs/xfs/xfs.ko 222150 ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko 198503 ./drivers/infiniband/hw/mlx5/mlx5_ib.ko 198356 ./drivers/net/ethernet/broadcom/bnx2x/bnx2x.ko 113444 ./fs/cifs/cifs.ko 109379 ./arch/x86/kvm/kvm.ko 100225 ./drivers/gpu/drm/drm.ko 94827 ./drivers/infiniband/core/ib_core.ko 91188

Andrii Nakryiko committed 6 years ago

Commit 5f9ae911 parent 53297222 files · +27 −2Browse files

Unified · Split

2 files
  1. lib/Kconfig.debug +9 −0
  2. scripts/Makefile.modfinal +18 −2
lib/Kconfig.debug+9−0
@@ -274,6 +274,15 @@ config DEBUG_INFO_BTF · 273 unmodified lines
274274 Turning this on expects presence of pahole tool, which will convert
275275 DWARF type info into equivalent deduplicated BTF type info.
276276
277+config PAHOLE_HAS_SPLIT_BTF
278+ def_bool $(success, test `$(PAHOLE) --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/'` -ge "119")
279+
280+config DEBUG_INFO_BTF_MODULES
281+ def_bool y
282+ depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF
283+ help
284+ Generate compact split BTF type information for kernel modules.
285+
277286 config GDB_SCRIPTS
278287 bool "Provide GDB scripts for kernel debugging"
279288 help
scripts/Makefile.modfinal+18−2
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 PHONY := __modfinal
77 __modfinal:
88
9+include include/config/auto.conf
910 include $(srctree)/scripts/Kbuild.include
1011
1112 # for c_flags
@@ -36,8 +37,23 @@ quiet_cmd_ld_ko_o = LD [M] $@ · 24 unmodified lines
3637 -T scripts/module.lds -o $@ $(filter %.o, $^); \
3738 $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
3839
39−$(modules): %.ko: %.o %.mod.o scripts/module.lds FORCE
40− +$(call if_changed,ld_ko_o)
40+quiet_cmd_btf_ko = BTF [M] $@
41+ cmd_btf_ko = LLVM_OBJCOPY=$(OBJCOPY) $(PAHOLE) -J --btf_base vmlinux $@
42+
43+# Same as newer-prereqs, but allows to exclude specified extra dependencies
44+newer_prereqs_except = $(filter-out $(PHONY) $(1),$?)
45+
46+# Same as if_changed, but allows to exclude specified extra dependencies
47+if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
48+ $(cmd); \
49+ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
50+
51+# Re-generate module BTFs if either module's .ko or vmlinux changed
52+$(modules): %.ko: %.o %.mod.o scripts/module.lds vmlinux FORCE
53+ +$(call if_changed_except,ld_ko_o,vmlinux)
54+ifdef CONFIG_DEBUG_INFO_BTF_MODULES
55+ +$(if $(newer-prereqs),$(call cmd,btf_ko))
56+endif
4157
4258 targets += $(modules) $(modules:.ko=.mod.o)
4359