Skip to content

With LTO and LTO cache, .incbin in assembly is not handled properly during incremental builds #2021

Description

@jacky8hyf

Bug description

To reproduce the error:

  • Checkout Linux kernel source tree from Linus Torvald's tree. I am at: 00dcf5d ("Merge tag 'acpi-6.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm")
  • Get clang prebuilts. I am at: clang-r522817.

Then do the following:

PATH=$PATH:/path/to/clang-r522817/bin/ make ARCH=arm64 LLVM=1 tinyconfig
PATH=$PATH:/path/to/clang-r522817/bin/ make ARCH=arm64 LLVM=1 menuconfig

In menuconfig, enable the following:

  • LTO_CLANG_THIN=y: Enables LTO
  • IKCONFIG=y: Enables /proc/config.gz
  • HEADERS_INSTALL=y: Any config will do. I use this one as an example.

Then:

PATH=$PATH:/path/to/clang-r522817/bin/ make ARCH=arm64 LLVM=1 -j64
zcat kernel/config_data.gz | grep HEADER
scripts/extract-ikconfig vmlinux | grep HEADER

The last two commands will both say CONFIG_HEADERS_INSTALL=y.

Now, run PATH=$PATH:/path/to/clang-r522817/bin/ make ARCH=arm64 LLVM=1 menuconfig again, and disable HEADERS_INSTALL, then build again:

PATH=$PATH:/path/to/clang-r522817/bin/ make ARCH=arm64 LLVM=1 -j64
zcat kernel/config_data.gz | grep HEADER
scripts/extract-ikconfig vmlinux | grep HEADER

The first command will emit # CONFIG_HEADERS_INSTALL is not set correctly, but the last command will still emit CONFIG_HEADERS_INSTALL=y.

Analysis

The config_data.gz file is embedded in vmlinux using a .incbin instruction: https://github.com/torvalds/linux/blob/96fca68c4fbf77a8185eb10f7557e23352732ea2/kernel/configs.c#L28

From the build log and from the output of the above commands, Kbuild correctly updates kernel/config_data.gz, but the change is not reflected in vmlinux, even though it is rebuilt.

LTO (specifically caching) may play a part in this.

  • If I disable LTO in the above make menuconfig commands, vmlinux will correctly have # CONFIG_HEADERS_INSTALL is not set.
  • In addition, if I delete .thinlto-cache directory (--thinlto-cache-dir 1) before rebuilding, vmlinux will also correctly have # CONFIG_HEADERS_INSTALL is not set.
  • If I apply this workaround, this will link configs.o with -fno-lto, and vmlinux will also correctly have # CONFIG_HEADERS_INSTALL is not set.
From 10eacc104cb39c26a753796c981e46d0cba233c2 Mon Sep 17 00:00:00 2001
From: Yifan Hong <elsk@google.com>
Date: Mon, 8 Apr 2024 23:49:38 -0700
Subject: [PATCH] config: Disable LTO on kernel/configs.o

Signed-off-by: Yifan Hong <elsk@google.com>
---
 kernel/Makefile | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/Makefile b/kernel/Makefile
index 2e0dac3da346..0db1e9357668 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -140,6 +140,10 @@ obj-$(CONFIG_SCF_TORTURE_TEST) += scftorture.o

 $(obj)/configs.o: $(obj)/config_data.gz

+# Disable LTO on configs.o so changes in .config is reflected
+# in vmlinux.
+CFLAGS_REMOVE_configs.o += $(CC_FLAGS_LTO)
+
 targets += config_data config_data.gz
 $(obj)/config_data.gz: $(obj)/config_data FORCE
 	$(call if_changed,gzip)
--
2.44.0.769.g3c40516874-goog

Hence, I believe this is a bug in LTO caching. Please help, thanks!

I am going to upload this workaround patch to Linux upstream, but the root issue should be fixed.

Footnotes

  1. https://github.com/torvalds/linux/blob/96fca68c4fbf77a8185eb10f7557e23352732ea2/Makefile#L945

Metadata

Metadata

Assignees

No one assigned

    Labels

    [BUG] llvmA bug that should be fixed in upstream LLVM[FEATURE] LTORelated to building the kernel with LLVM Link Time Optimization[WORKAROUND] AcceptedThis bug has an accepted workaround

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions