Re: [PATCH -next] arm32: enable HAVE_LD_DEAD_CODE_DATA_ELIMINATION

From: liuyuntao (F)
Date: Tue Feb 27 2024 - 03:07:11 EST




On 2024/2/23 0:04, Arnd Bergmann wrote:
On Thu, Feb 22, 2024, at 12:24, liuyuntao (F) wrote:

The position of the caret has been moved below the right brace
of { KEEP(*(.vectors.bhb.loop8)) }, indicating that lld is treating
the entire `KEEP(*(.vectors))` as a file name. This could potentially be
a bug in lld. Perhaps we can temporarily
enable the DCE option only when option LD_IS_LLD is disabled,
like risc-v:

`select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !LD_IS_LLD`.

I would really like to see this working with lld if at all
possible, as it allows the combination of gc-sections with
lto and CONFIG_TRIM_UNUSED_KSYMS.

I experimented with lld myself now and I did get a booting
kernel even without the the KEEP() on the vectors. I also
see that this is the only use of OVERLAY in the kernel, so
I hope that we can find a way to make it work with existing
lld after all, either without the KEEP or without the OVERLAY.

Did you see any problems without the KEEP() on the vectors?

Arnd

Hi, Arnd. I have added a global symbol g_keep1 in .vectors, g_keep2 in vectors.bhb.loop8 and g_keep3 in .vectors.bhb.bpiall respectively. I also added another section to reference these three global symbols, to prevent these sections from being removed during linking with --gc-sections.

It worked,but there should be a better way to achieve it. the patch:

diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h
index f2ff79f740ab..d60f6e83a9f7 100644
--- a/arch/arm/include/asm/vmlinux.lds.h
+++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -125,13 +125,13 @@
__vectors_lma = .; \
OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \
.vectors { \
- KEEP(*(.vectors)) \
+ *(.vectors) \
} \
.vectors.bhb.loop8 { \
- KEEP(*(.vectors.bhb.loop8)) \
+ *(.vectors.bhb.loop8) \
} \
.vectors.bhb.bpiall { \
- KEEP(*(.vectors.bhb.bpiall)) \
+ *(.vectors.bhb.bpiall) \
} \
} \
ARM_LMA(__vectors, .vectors); \
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 6150a716828c..84536e805da0 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -1075,6 +1075,9 @@ THUMB( .reloc ., R_ARM_THM_PC12, L__vector_swi )
W(b) vector_addrexcptn
W(b) vector_irq
W(b) vector_fiq
+ .global g_keep1
+ g_keep1:
+ .word 0

#ifdef CONFIG_HARDEN_BRANCH_HISTORY
.section .vectors.bhb.loop8, "ax", %progbits
@@ -1088,6 +1091,9 @@ THUMB( .reloc ., R_ARM_THM_PC12, L__vector_bhb_loop8_swi )
W(b) vector_addrexcptn
W(b) vector_bhb_loop8_irq
W(b) vector_bhb_loop8_fiq
+ .global g_keep2
+ g_keep2:
+ .word 0

.section .vectors.bhb.bpiall, "ax", %progbits
W(b) vector_rst
@@ -1100,6 +1106,9 @@ THUMB( .reloc ., R_ARM_THM_PC12, L__vector_bhb_bpiall_swi )
W(b) vector_addrexcptn
W(b) vector_bhb_bpiall_irq
W(b) vector_bhb_bpiall_fiq
+ .global g_keep3
+ g_keep3:
+ .word 0
#endif

.data
@@ -1108,3 +1117,8 @@ THUMB( .reloc ., R_ARM_THM_PC12, L__vector_bhb_bpiall_swi )
.globl cr_alignment
cr_alignment:
.space 4
+
+.section .keep_vectors, "ax", %progbits
+ LDR r0, =g_keep1
+ LDR r1, =g_keep2
+ LDR r2, =g_keep3
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 01a887c1141a..5cdfb4ba3ac4 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -62,6 +62,7 @@ SECTIONS
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
ARM_TEXT
+ KEEP(*(.keep_vectors))
}

#ifdef CONFIG_DEBUG_ALIGN_RODATA
--
2.34.1

> I would really like to see this working with lld if at all
> possible, as it allows the combination of gc-sections with
> lto and CONFIG_TRIM_UNUSED_KSYMS.
Then, I enabled config CONFIG_LTO_CLANG_THIN in arm32, but
came across a link failure using clang/lld:

following symbols must have non local/private scope:
free_mem_end_ptr
free_mem_ptr
malloc_count
malloc_ptr
output_data

in file arch/arm/boot/compressed/Makefile:
# We need to prevent any GOTOFF relocs being used with references
# to symbols in the .bss section since we cannot relocate them
# independently from the rest at run time. This can be achieved by
# ensuring that no private .bss symbols exist, as global symbols
# always have a GOT entry which is what we need.
# The .data section is already discarded by the linker script so no need
# to bother about it here.
check_for_bad_syms = \
bad_syms=$$($(NM) $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
[ -z "$$bad_syms" ] || \
( echo "following symbols must have non local/private scope:" >&2; \
echo "$$bad_syms" >&2; false )

Turn on the config CONFIG_LTO_CLANG_THIN , use nm to check the type of these symbols as 'b', turn off the config type to 'B'. I tried to explicitly declare these variables using __attribute__((visibility("default")), but it didn't take effect on the variable `output_data`.
ld.lld: warning: thinlto-cache/llvmcache-285C4672B80361F1DA67C743A5C8350FDDEEC8E3:(.data.malloc_ptr) is being placed in '.data.':

ld.lld: warning: thinlto-cache/llvmcache-285C4672B80361F1DA67C743A5C8350FDDEEC8E3:(.data.malloc_ptr) is being placed in '.data.'
ld.lld: warning: thinlto-cache/llvmcache-285C4672B80361F1DA67C743A5C8350FDDEEC8E3:(.data.malloc_count) is being placed in '.dat'
following symbols must have non local/private scope:
output_data