From e83b9f55448afce3fe1abcd1d10db9584f8042a6 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Tue, 2 Apr 2019 09:49:50 -0700 Subject: kbuild: add ability to generate BTF type info for vmlinux This patch adds new config option to trigger generation of BTF type information from DWARF debuginfo for vmlinux and kernel modules through pahole, which in turn relies on libbpf for btf_dedup() algorithm. The intent is to record compact type information of all types used inside kernel, including all the structs/unions/typedefs/etc. This enables BPF's compile-once-run-everywhere ([0]) approach, in which tracing programs that are inspecting kernel's internal data (e.g., struct task_struct) can be compiled on a system running some kernel version, but would be possible to run on other kernel versions (and configurations) without recompilation, even if the layout of structs changed and/or some of the fields were added, removed, or renamed. This is only possible if BPF loader can get kernel type info to adjust all the offsets correctly. This patch is a first time in this direction, making sure that BTF type info is part of Linux kernel image in non-loadable ELF section. BTF deduplication ([1]) algorithm typically provides 100x savings compared to DWARF data, so resulting .BTF section is not big as is typically about 2MB in size. [0] http://vger.kernel.org/lpc-bpf2018.html#session-2 [1] https://facebookmicrosites.github.io/bpf/blog/2018/11/14/btf-enhancement.html Cc: Masahiro Yamada Cc: Arnaldo Carvalho de Melo Cc: Daniel Borkmann Cc: Alexei Starovoitov Cc: Yonghong Song Cc: Martin KaFai Lau Signed-off-by: Andrii Nakryiko Acked-by: David S. Miller Acked-by: Alexei Starovoitov Acked-by: Daniel Borkmann Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dc0e8c5a1402..dd2b31ccca6a 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -35,7 +35,7 @@ set -e info() { if [ "${quiet}" != "silent_" ]; then - printf " %-7s %s\n" ${1} ${2} + printf " %-7s %s\n" "${1}" "${2}" fi } @@ -91,6 +91,20 @@ vmlinux_link() fi } +# generate .BTF typeinfo from DWARF debuginfo +gen_btf() +{ + local pahole_ver; + + pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') + if [ "${pahole_ver}" -lt "113" ]; then + info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" + exit 0 + fi + + info "BTF" ${1} + LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1} +} # Create ${2} .o file with all symbols from the ${1} object file kallsyms() @@ -248,6 +262,10 @@ fi info LD vmlinux vmlinux_link "${kallsymso}" vmlinux +if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then + gen_btf vmlinux +fi + if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then info SORTEX vmlinux sortextable vmlinux -- cgit From 68e5ab1fc8bd9c17ed94ac172ffe0b9b7e85a59a Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 15 Apr 2019 14:58:39 -0700 Subject: kbuild: handle old pahole more gracefully when generating BTF When CONFIG_DEBUG_INFO_BTF is enabled but available version of pahole is too old to support BTF generation, build script is supposed to emit warning and proceed with the build. Due to using exit instead of return from BASH function, existing handling code prematurely exits exit code 0, not completing some of the build steps. This patch fixes issue by correctly returning just from gen_btf() function only. Fixes: e83b9f55448a ("kbuild: add ability to generate BTF type info for vmlinux") Cc: Masahiro Yamada Cc: Arnaldo Carvalho de Melo Cc: Daniel Borkmann Cc: Alexei Starovoitov Cc: Yonghong Song Cc: Martin KaFai Lau Signed-off-by: Andrii Nakryiko Acked-by: Song Liu Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dd2b31ccca6a..6a148d0d51bf 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -99,7 +99,7 @@ gen_btf() pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" - exit 0 + return 0 fi info "BTF" ${1} -- cgit From 581b31c36cfc58df603c415ab6f3c795611c0ca1 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Sun, 5 May 2019 17:10:33 -0700 Subject: kbuild: tolerate missing pahole when generating BTF When BTF generation is enabled through CONFIG_DEBUG_INFO_BTF, scripts/link-vmlinux.sh detects if pahole version is too old and gracefully continues build process, skipping BTF generation build step. But if pahole is not available, build will still fail. This patch adds check for whether pahole exists at all and bails out gracefully, if not. Cc: Alexei Starovoitov Reported-by: Yonghong Song Fixes: e83b9f55448a ("kbuild: add ability to generate BTF type info for vmlinux") Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann --- scripts/link-vmlinux.sh | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts/link-vmlinux.sh') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 6a148d0d51bf..e3c06b9482a2 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -96,6 +96,11 @@ gen_btf() { local pahole_ver; + if ! [ -x "$(command -v ${PAHOLE})" ]; then + info "BTF" "${1}: pahole (${PAHOLE}) is not available" + return 0 + fi + pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" -- cgit From 898490c010b5d2e499e03b7e815fc214209ac583 Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Mon, 29 Apr 2019 18:11:14 +0200 Subject: moduleparam: Save information about built-in modules in separate file Problem: When a kernel module is compiled as a separate module, some important information about the kernel module is available via .modinfo section of the module. In contrast, when the kernel module is compiled into the kernel, that information is not available. Information about built-in modules is necessary in the following cases: 1. When it is necessary to find out what additional parameters can be passed to the kernel at boot time. 2. When you need to know which module names and their aliases are in the kernel. This is very useful for creating an initrd image. Proposal: The proposed patch does not remove .modinfo section with module information from the vmlinux at the build time and saves it into a separate file after kernel linking. So, the kernel does not increase in size and no additional information remains in it. Information is stored in the same format as in the separate modules (null-terminated string array). Because the .modinfo section is already exported with a separate modules, we are not creating a new API. It can be easily read in the userspace: $ tr '\0' '\n' < modules.builtin.modinfo ext4.softdep=pre: crc32c ext4.license=GPL ext4.description=Fourth Extended Filesystem ext4.author=Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others ext4.alias=fs-ext4 ext4.alias=ext3 ext4.alias=fs-ext3 ext4.alias=ext2 ext4.alias=fs-ext2 md_mod.alias=block-major-9-* md_mod.alias=md md_mod.description=MD RAID framework md_mod.license=GPL md_mod.parmtype=create_on_open:bool md_mod.parmtype=start_dirty_degraded:int ... Co-Developed-by: Gleb Fotengauer-Malinovskiy Signed-off-by: Gleb Fotengauer-Malinovskiy Signed-off-by: Alexey Gladkov Acked-by: Jessica Yu Signed-off-by: Masahiro Yamada --- .gitignore | 1 + Documentation/dontdiff | 1 + Documentation/kbuild/kbuild.txt | 5 +++++ Makefile | 2 ++ include/asm-generic/vmlinux.lds.h | 1 + include/linux/module.h | 1 + include/linux/moduleparam.h | 12 +++++------- scripts/link-vmlinux.sh | 3 +++ 8 files changed, 19 insertions(+), 7 deletions(-) (limited to 'scripts/link-vmlinux.sh') diff --git a/.gitignore b/.gitignore index e7bb6c6edbae..2fb1765c33b0 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ modules.builtin /vmlinuz /System.map /Module.markers +/modules.builtin.modinfo # # RPM spec file (make rpm-pkg) diff --git a/Documentation/dontdiff b/Documentation/dontdiff index ef25a066d952..512fa0239ebf 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -178,6 +178,7 @@ mktables mktree modpost modules.builtin +modules.builtin.modinfo modules.order modversions.h* nconf diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index 8a3830b39c7d..9c230ea71963 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -11,6 +11,11 @@ modules.builtin This file lists all modules that are built into the kernel. This is used by modprobe to not fail when trying to load something builtin. +modules.builtin.modinfo +-------------------------------------------------- +This file contains modinfo from all modules that are built into the kernel. +Unlike modinfo of a separate module, all fields are prefixed with module name. + Environment variables diff --git a/Makefile b/Makefile index 85dd977f4232..9a8b3f94633d 100644 --- a/Makefile +++ b/Makefile @@ -1308,6 +1308,7 @@ _modinst_: fi @cp -f $(objtree)/modules.order $(MODLIB)/ @cp -f $(objtree)/modules.builtin $(MODLIB)/ + @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst # This depmod is only for convenience to give the initial @@ -1348,6 +1349,7 @@ endif # CONFIG_MODULES # Directories & files removed with 'make clean' CLEAN_DIRS += $(MODVERDIR) include/ksym +CLEAN_FILES += modules.builtin.modinfo # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config usr/include include/generated \ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f8f6f04c4453..bbb9e332f2fe 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -844,6 +844,7 @@ EXIT_CALL \ *(.discard) \ *(.discard.*) \ + *(.modinfo) \ } /** diff --git a/include/linux/module.h b/include/linux/module.h index 5bf5dcd91009..5f7007430d35 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -253,6 +253,7 @@ extern typeof(name) __mod_##type##__##name##_device_table \ #define MODULE_VERSION(_version) MODULE_INFO(version, _version) #else #define MODULE_VERSION(_version) \ + MODULE_INFO(version, _version); \ static struct module_version_attribute ___modver_attr = { \ .mattr = { \ .attr = { \ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ba36506db4fb..5ba250d9172a 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -10,23 +10,21 @@ module name. */ #ifdef MODULE #define MODULE_PARAM_PREFIX /* empty */ +#define __MODULE_INFO_PREFIX /* empty */ #else #define MODULE_PARAM_PREFIX KBUILD_MODNAME "." +/* We cannot use MODULE_PARAM_PREFIX because some modules override it. */ +#define __MODULE_INFO_PREFIX KBUILD_MODNAME "." #endif /* Chosen so that structs with an unsigned long line up. */ #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) -#ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __UNIQUE_ID(name)[] \ __used __attribute__((section(".modinfo"), unused, aligned(1))) \ - = __stringify(tag) "=" info -#else /* !MODULE */ -/* This struct is here for syntactic coherency, it is not used */ -#define __MODULE_INFO(tag, name, info) \ - struct __UNIQUE_ID(name) {} -#endif + = __MODULE_INFO_PREFIX __stringify(tag) "=" info + #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index dc0e8c5a1402..e4383e0f476e 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -193,6 +193,9 @@ modpost_link vmlinux.o # modpost vmlinux.o to check for section mismatches ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o +info MODINFO modules.builtin.modinfo +${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo + kallsymso="" kallsyms_vmlinux="" if [ -n "${CONFIG_KALLSYMS}" ]; then -- cgit