[lld] [lld] Add target support for SystemZ (s390x) (PR #75643)
Nathan Chancellor via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 7 11:52:03 PST 2024
nathanchance wrote:
> the `.ipldata` section _should_ be residing at [0x0, 0x1ff], which apparently it isn't. Everything else seems to be follow-on problems.
>
> Not sure why lld doesn't appear to respect the `. = 0` setting here.
This appears to be related to differences in the orphan section placement between `ld.lld` and `ld.bfd`.
If I add `--orphan-handling=warn` to `arch/s390/boot/Makefile` like so:
```diff
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index c7c81e5f9218..f99407b5430c 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -73,11 +73,11 @@ $(obj)/bzImage: $(obj)/vmlinux $(obj)/section_cmp.boot.data $(obj)/section_cmp.b
$(obj)/section_cmp%: vmlinux $(obj)/vmlinux FORCE
$(call if_changed,section_cmp)
-LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup $(if $(CONFIG_VMLINUX_MAP),-Map=$(obj)/vmlinux.map) --build-id=sha1 -T
+LDFLAGS_vmlinux := --orphan-handling=warn --oformat $(LD_BFD) -e startup $(if $(CONFIG_VMLINUX_MAP),-Map=$(obj)/vmlinux.map) --build-id=sha1 -T
$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS_ALL) FORCE
$(call if_changed,ld)
-LDFLAGS_vmlinux.syms := --oformat $(LD_BFD) -e startup -T
+LDFLAGS_vmlinux.syms := --orphan-handling=warn --oformat $(LD_BFD) -e startup -T
$(obj)/vmlinux.syms: $(obj)/vmlinux.lds $(OBJECTS) FORCE
$(call if_changed,ld)
```
It reveals:
```
ld.lld: warning: arch/s390/boot/decompressor.o:(.export_symbol) is being placed in '.export_symbol'
ld.lld: warning: arch/s390/boot/decompressor.o:(.modinfo) is being placed in '.modinfo'
ld.lld: warning: arch/s390/boot/decompressor.o:(.discard.addressable) is being placed in '.discard.addressable'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_loc) is being placed in '.debug_loc'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_abbrev) is being placed in '.debug_abbrev'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_info) is being placed in '.debug_info'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_ranges) is being placed in '.debug_ranges'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_str) is being placed in '.debug_str'
ld.lld: warning: arch/s390/boot/decompressor.o:(.comment) is being placed in '.comment'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_frame) is being placed in '.debug_frame'
ld.lld: warning: arch/s390/boot/decompressor.o:(.debug_line) is being placed in '.debug_line'
ld.lld: warning: <internal>:(.comment) is being placed in '.comment'
ld.lld: warning: <internal>:(.got) is being placed in '.got'
ld.lld: warning: <internal>:(.symtab) is being placed in '.symtab'
ld.lld: warning: <internal>:(.shstrtab) is being placed in '.shstrtab'
ld.lld: warning: <internal>:(.strtab) is being placed in '.strtab'
```
So handling those sections in the linker script (this may be entirely incorrect for where to place things):
```diff
diff --git a/arch/s390/boot/vmlinux.lds.S b/arch/s390/boot/vmlinux.lds.S
index 389df0e0d9e5..303928263f46 100644
--- a/arch/s390/boot/vmlinux.lds.S
+++ b/arch/s390/boot/vmlinux.lds.S
@@ -31,6 +31,7 @@ SECTIONS
_text = .; /* Text */
*(.text)
*(.text.*)
+ INIT_TEXT
_etext = . ;
}
.rodata : {
@@ -74,6 +75,10 @@ SECTIONS
_ebss = .;
}
+ .got : {
+ *(.got)
+ }
+
/*
* uncompressed image info used by the decompressor it should match
* struct vmlinux_info. It comes from .vmlinux.info section of
@@ -118,8 +123,12 @@ SECTIONS
}
_end = .;
+ DWARF_DEBUG
+ ELF_DETAILS
+
/* Sections to be discarded */
/DISCARD/ : {
+ COMMON_DISCARDS
*(.eh_frame)
*(__ex_table)
*(*__ksymtab*)
```
and adding `-z notext` to `LDFLAGS_vmlinux` like previously suggested
```diff
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 73873e451686..994f9b3d575f 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -15,7 +15,7 @@ KBUILD_CFLAGS_MODULE += -fPIC
KBUILD_AFLAGS += -m64
KBUILD_CFLAGS += -m64
KBUILD_CFLAGS += -fPIE
-LDFLAGS_vmlinux := -pie
+LDFLAGS_vmlinux := -pie -z notext
aflags_dwarf := -Wa,-gdwarf-2
KBUILD_AFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -D__ASSEMBLY__
ifndef CONFIG_AS_IS_LLVM
```
and disabling `CONFIG_BUG` like noted before, I can get a kernel image that links successfully with `ld.lld` and boots in QEMU :)
```
$ qemu-system-s390x -display none -nodefaults -M s390-ccw-virtio -kernel arch/s390/boot/bzImage -initrd rootfs.cpio -m 512m -serial mon:stdio
KASLR disabled: CPU has no PRNG
KASLR disabled: CPU has no PRNG
[ 0.867414] Linux version 6.8.0-rc3-00045-g95fc50189e45-dirty (nathan at dev-fedora.aadp) (ClangBuiltLinux clang version 19.0.0git (https://github.com/llvm/llvm-project 417075e56aeba5a5b20301c7bfeba9c2a800982b), ClangBuiltLinux LLD 19.0.0) #1 SMP Wed Feb 7 12:47:57 MST 2024
[ 0.870159] setup: Linux is running under KVM in 64-bit mode
[ 0.893253] setup: The maximum memory size is 512MB
...
```
All and all, not too bad! I think most of those fixes can be sent upstream, I'll see if I can talk to the s390 kernel folks about the bug tables issue, maybe the kernel can workaround that as well...
https://github.com/llvm/llvm-project/pull/75643
More information about the llvm-commits
mailing list