[PATCH v2 kernel 9/9] bpf: add support for CONFIG_DEBUG_INFO_BTF_VARS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Alan Maguire <alan.maguire@xxxxxxxxxx>

This patch implements a proof-of-concept of the kernel side of
global variable support discussed in [1].

Add new tristate CONFIG_DEBUG_INFO_BTF_VARS; when it is 'y'
both per-CPU and global variables are added to vmlinux BTF.
When set to 'm',  variable BTF is added to module
kernel/bpf/vmlinux_btf_extra.ko; as a result, global variables
will be available in /sys/kernel/btf/vmlinux_btf_extra using
split BTF to store variables.

To achieve this, we add a "target" option to scripts/pahole-flags.sh
which - if set to "extra" - gives us the flags to be used for
extra vmlinux BTF generation.  Module building and BTF generation
are skipped if CONFIG_DEBUG_INFO_BTF_VARS is 'y' or 'n'.

Depends on having a v1.24 of dwarves which provides support for
encoding all variables as per patch 1-7 of [1].  To put the pieces
together, apply those patches to pahole.  Eventually, like other
functionality it would likely require dependending on a newer
version of pahole like v1.25.

CMakeLists.txt before building so that the pahole version can be
a proxy for detecting the "encode all variables" feature.

Prior to fixes [2] and [3] dedup failed and was highly
redundant, but with those fixes in pahole and libbpf we see
that in the module case, vmlinux_btf_extra.ko only defines
two non-VAR kinds; one for the percpu DATASEC and one for
the 'double' type:

$ bpftool btf dump -B ~/src/bpf/vmlinux file ~/src/bpf/kernel/bpf/vmlinux_btf_extra.ko|egrep -v VAR
[115981] INT 'double' size=8 bits_offset=0 nr_bits=64 encoding=(none)
[159904] DATASEC '.data..percpu' size=209156 vlen=378

Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>

[1] TBD (requires resyncing patches with dwarves)
[2] https://lore.kernel.org/bpf/1666364523-9648-1-git-send-email-alan.maguire@xxxxxxxxxx/
[3] https://lore.kernel.org/bpf/1666622309-22289-1-git-send-email-alan.maguire@xxxxxxxxxx/
---
 Makefile                       |  3 ++-
 kernel/bpf/Makefile            |  4 ++++
 kernel/bpf/vmlinux_btf_extra.c | 22 ++++++++++++++++++++
 lib/Kconfig.debug              |  9 ++++++++
 scripts/Makefile.modfinal      |  6 ++++++
 scripts/pahole-flags.sh        | 38 ++++++++++++++++++++++++++++++++++
 6 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 kernel/bpf/vmlinux_btf_extra.c

diff --git a/Makefile b/Makefile
index f659d3085121..7cc99a424a85 100644
--- a/Makefile
+++ b/Makefile
@@ -527,6 +527,7 @@ XZ		= xz
 ZSTD		= zstd
 
 PAHOLE_FLAGS	= $(shell PAHOLE=$(PAHOLE) $(srctree)/scripts/pahole-flags.sh)
+EXTRA_PAHOLE_FLAGS = $(shell PAHOLE=$(PAHOLE) $(srctree)/scripts/pahole-flags.sh extra)
 
 CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
 		  -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
@@ -614,7 +615,7 @@ export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
 export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
 export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
-export PAHOLE_FLAGS
+export PAHOLE_FLAGS EXTRA_PAHOLE_FLAGS
 
 # Files to ignore in find ... statements
 
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 341c94f208f4..8e3ee5c98f23 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -43,3 +43,7 @@ obj-$(CONFIG_BPF_PRELOAD) += preload/
 obj-$(CONFIG_BPF_SYSCALL) += relo_core.o
 $(obj)/relo_core.o: $(srctree)/tools/lib/bpf/relo_core.c FORCE
 	$(call if_changed_rule,cc_o_c)
+
+ifeq ($(CONFIG_DEBUG_INFO_BTF_VARS),m)
+obj-m = vmlinux_btf_extra.o
+endif
diff --git a/kernel/bpf/vmlinux_btf_extra.c b/kernel/bpf/vmlinux_btf_extra.c
new file mode 100644
index 000000000000..9aa682287a1e
--- /dev/null
+++ b/kernel/bpf/vmlinux_btf_extra.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022, Oracle and/or its affiliates. */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/* Dummy module used as a container for extra vmlinux BTF information;
+ * to be used if vmlinux BTF size is a concern.
+ */
+static int __init vmlinux_btf_extra_init(void)
+{
+	return 0;
+}
+module_init(vmlinux_btf_extra_init);
+
+static void __exit vmlinux_btf_extra_exit(void)
+{
+	return;
+}
+module_exit(vmlinux_btf_extra_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f473f7d8a0a2..3c7df82a37db 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -364,6 +364,15 @@ config DEBUG_INFO_BTF_MODULES
 	help
 	  Generate compact split BTF type information for kernel modules.
 
+config DEBUG_INFO_BTF_VARS
+	tristate "Encode kernel variables in BTF"
+	depends on DEBUG_INFO_BTF && PAHOLE_VERSION >= 124
+	help
+	   Decide whether pahole emits variable definitions for all
+	   variables.  If 'm', variables are stored in vmlinux-btf-extra
+	   module, which has BTF for variables only (it is deduplicated
+	   with vmlinux BTF).
+
 config MODULE_ALLOW_BTF_MISMATCH
 	bool "Allow loading modules with non-matching BTF type info"
 	depends on DEBUG_INFO_BTF_MODULES
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 9a1fa6aa30fe..210d7869c14f 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -43,6 +43,12 @@ quiet_cmd_btf_ko = BTF [M] $@
 		printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
 	elif [ -n "$(CONFIG_RUST)" ] && $(srctree)/scripts/is_rust_module.sh $@; then 		\
 		printf "Skipping BTF generation for %s because it's a Rust module\n" $@ 1>&2; \
+	elif [ $@ == "kernel/bpf/vmlinux_btf_extra.ko" ]; then		\
+		LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J			\
+		    --btf_encode_detached=$@.btf --btf_base vmlinux	\
+		    $(EXTRA_PAHOLE_FLAGS) vmlinux;			\
+		$(OBJCOPY) --add-section .BTF=$(@).btf			\
+		    --set-section-flags .BTF=alloc,readonly $(@);	\
 	else								\
 		LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) --btf_base vmlinux $@; \
 		$(RESOLVE_BTFIDS) -b vmlinux $@; 			\
diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh
index 0d99ef17e4a5..44bc714fe926 100755
--- a/scripts/pahole-flags.sh
+++ b/scripts/pahole-flags.sh
@@ -1,6 +1,16 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 
+config_value() {
+	awk -v name=$1 -F '=' '$1 == name { print $2 }' include/config/auto.conf
+}
+
+# target is set to "extra" for vmlinux_btf_extra module encoding flags.
+# If CONFIG_DEBUG_INFO_BTF_VARS is 'm', we encode variables in
+# the module, otherwise if 'y' encode them in vmlinux BTF directly.
+
+target=$1
+
 extra_paholeopt=
 
 if ! [ -x "$(command -v ${PAHOLE})" ]; then
@@ -20,4 +30,32 @@ if [ "${pahole_ver}" -ge "122" ]; then
 	extra_paholeopt="${extra_paholeopt} -j"
 fi
 
+case $(config_value CONFIG_DEBUG_INFO_BTF_VARS) in
+y)
+	# variables are encoded in core vmlinux BTF; nothing is encoded
+	# in vmlinux_btf_extra module BTF.
+	if [[ $target == "extra" ]]; then
+		extra_paholeopt=""
+	else
+		extra_paholeopt="${extra_paholeopt} --encode_all_btf_vars"
+	fi
+	;;
+m)
+	# global variables are encoded in vmlinux_btf_extra; per-CPU
+	# variables are still found in vmlinux BTF.
+	if [[ $target == "extra" ]]; then
+		extra_paholeopt="--encode_all_btf_vars"
+	else
+		extra_paholeopt="${extra_paholeopt}"
+	fi
+	;;
+*)
+	# nothing is encoded in vmlinux_btf_extra; no global variables
+	# are encoded in core vmlinux BTF.
+	if [[ $target == "extra" ]]; then
+		extra_paholeopt=""
+	fi
+	;;
+esac
+
 echo ${extra_paholeopt}
-- 
2.31.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux