ld.lld: error: can't create dynamic relocation R_386_32 against symbol: _bss in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in
>>> referenced by arch/x86/boot/compressed/head_32.o:(.text+0x4)
This is specific to i386 and LLD. Not yet submitted to LLVM bugzilla.
arch/x86/boot/compressed/Makefile resets KBUILD_CFLAGS and KBUILD_LDFLAGS. Can you try:
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 6b84afdd7538..90d59a064136 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -43,7 +43,7 @@ KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
GCOV_PROFILE := n
UBSAN_SANITIZE :=n
-KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
+KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE) -z notext
# Compressed kernel should be built as PIE since it may be loaded at any
# address by the bootloader.
ifeq ($(CONFIG_X86_32),y)
We do that in arch/arm64/Makefile if CONFIG_RELOCATABLE is set. So I'm guessing this issue might go away if KASLR (CONFIG_RANDOMIZE_BASE and CONFIG_RELOCATABLE) is used. If that's the case, then my diff above should probably similarly be guarded like in arch/arm64/Makefile by CONFIG_RELOCATABLE.
Builds fine with -z notext, confirmed.
I have tested with both CONFIG_RELOCATABLE set and unset and can confirm that the guess was right. I updated the patch:
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -55,6 +55,12 @@ else
KBUILD_LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
&& echo "-z noreloc-overflow -pie --no-dynamic-linker")
endif
+ifeq ($(CONFIG_RELOCATABLE), y)
+# LLD by default disallows relocations in read-only segments. For a relocatable
+# kernel, we pass -z notext to the linker to explicitly allow relocations. This
+# behavior is default for BFD.
+KBUILD_LDFLAGS += -z notext
+endif
LDFLAGS_vmlinux := -T
I like the check for CONFIG_RELOCATABLE. @tpimh did you test that LLD can link the image both w/ and w/o that config enabled? The comment can go in the commit message, rather than in source I think.
Tested with both CONFIG_RELOCATABLE set and unset. Links and boots fine in both cases.
Cool, send it.
With this series applied: https://lore.kernel.org/lkml/[email protected]/T/#u
I was able to link and boot an i386_defconfig with LLD. (Also https://lore.kernel.org/linux-next/[email protected]/, and a series I recently sent to Linus most of patches from Brian Gerst plus one). So this is close to working.