Doing a binary diff of two objects can be problematic: - For intra-section references, the compiler might use hard-coded offsets rather than relocations. - Data references can be ambiguous if the compiler uses section symbol references: - Symbol overlap and zero-length symbols create ambiguity as to which symbol is being referenced. - An access to the end of a symbol (e.g., array bounds) could be incorrectly interpreted as an access to the beginning of the next symbol. Remove those ambiguities by turning on -ffunction-sections and -fdata-sections for CONFIG_LIVEPATCH. They could alternatively be turned on only during the comparison builds, rather than also in the production kernel, but that might theoretically leave the possibility open for unexpected differences between the kernels. The compared kernels should be identical to the original kernel as much as possible. The performance impact should be small. Intra-TU references are quite rare in practice. And the resulting final code layout is similar. Distros are likely going to start using these options soon anyway for things like LTO and fgKASLR. A potential alternative approach would be to add a toolchain option to always use (symbol) relocations. Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> --- Makefile | 9 +++++++++ include/asm-generic/vmlinux.lds.h | 2 +- scripts/Makefile.lib | 2 +- scripts/module.lds.S | 13 +++++++++---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 3d10e3aadeda..2a15b560ecc0 100644 --- a/Makefile +++ b/Makefile @@ -931,10 +931,19 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH KBUILD_CFLAGS += -fno-inline-functions-called-once endif +ifdef CONFIG_LIVEPATCH +KBUILD_CFLAGS += -ffunction-sections -fdata-sections # `rustc`'s `-Zfunction-sections` applies to data too (as of 1.59.0). +KBUILD_RUSTFLAGS += -Zfunction-sections=y +else ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections +# `rustc`'s `-Zfunction-sections` applies to data too (as of 1.59.0). KBUILD_RUSTFLAGS_KERNEL += -Zfunction-sections=y +endif +endif + +ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION LDFLAGS_vmlinux += --gc-sections endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 5703526d6ebf..a7ac3ca596ad 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -98,7 +98,7 @@ * RODATA_MAIN is not used because existing code already defines .rodata.x * sections to be brought in with rodata. */ -#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG) +#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG) || defined(CONFIG_LIVEPATCH) #define TEXT_MAIN .text .text.[0-9a-zA-Z_]* #define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..L* .data..compoundliteral* .data.$__unnamed_* .data.$L* #define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]* diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9f4708702ef7..ca7497f74247 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -289,7 +289,7 @@ objtool-args = $(objtool-args-y) \ $(if $(delay-objtool), --link) \ $(if $(part-of-module), --module) -delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT)) +delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT),$(CONFIG_LIVEPATCH)) cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool-args) $@) cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) diff --git a/scripts/module.lds.S b/scripts/module.lds.S index 3f43edef813c..5cbae820bca0 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -36,12 +36,17 @@ SECTIONS { __kcfi_traps : { KEEP(*(.kcfi_traps)) } #endif -#ifdef CONFIG_LTO_CLANG +#if defined(CONFIG_LTO_CLANG) || defined(CONFIG_LIVEPATCH) + /* - * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and - * -ffunction-sections, which increases the size of the final module. - * Merge the split sections in the final binary. + * Merge -ffunction-sections and -fdata-sections sections to decrease + * module size. */ + + .text : { + *(.text .text.[0-9a-zA-Z_]*) + } + .bss : { *(.bss .bss.[0-9a-zA-Z_]*) *(.bss..L*) -- 2.45.2