[lld] [llvm] [MC,ELF] Set sh_entsize for SHT_INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY (PR #226875)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 27 20:27:45 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/226875
Match GNU Assembler: set sh_entsize to 4/8, regardless of sh_size. This
is mostly cosmetic: sh_entsize is not a useful member for non-merge
sections.
When clang-produced and GCC-produced objects are linked together, the
mismatch makes lld's output sh_entsize 0.
>From f9066e2342cfdf0534673567a4f0c26724c6f512 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 27 Sep 2026 20:20:11 -0700
Subject: [PATCH] [MC,ELF] Set sh_entsize for
SHT_INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY
Match GNU Assembler: set sh_entsize to 4/8, regardless of sh_size. This
is mostly cosmetic: sh_entsize is not a useful member for non-merge
sections.
When clang-produced and GCC-produced objects are linked together, the
mismatch makes lld's output sh_entsize 0.
---
lld/test/ELF/pre_init_fini_array.s | 6 +--
llvm/lib/MC/ELFObjectWriter.cpp | 11 +++-
llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll | 4 +-
llvm/test/MC/AsmParser/section_names.s | 56 ++++++++++-----------
llvm/test/MC/ELF/section.s | 38 ++++++++++++++
5 files changed, 81 insertions(+), 34 deletions(-)
diff --git a/lld/test/ELF/pre_init_fini_array.s b/lld/test/ELF/pre_init_fini_array.s
index 7ebc6ad40bdd4..fec1f2d401dbd 100644
--- a/lld/test/ELF/pre_init_fini_array.s
+++ b/lld/test/ELF/pre_init_fini_array.s
@@ -29,9 +29,9 @@ _start:
// CHECK-LABEL: Section Headers:
// CHECK: Name Type Address Off Size ES Flg
-// CHECK: .init_array INIT_ARRAY [[# %x, INIT_ADDR:]] [[# %x,]] [[# %x, INIT_SIZE:]] 00 WA
-// CHECK-NEXT: .preinit_array PREINIT_ARRAY [[# %x, PREINIT_ADDR:]] [[# %x,]] [[# %x, PREINIT_SIZE:]] 00 WA
-// CHECK-NEXT: .fini_array FINI_ARRAY [[# %x, FINI_ADDR:]] [[# %x,]] [[# %x, FINI_SIZE:]] 00 WA
+// CHECK: .init_array INIT_ARRAY [[# %x, INIT_ADDR:]] [[# %x,]] [[# %x, INIT_SIZE:]] 08 WA
+// CHECK-NEXT: .preinit_array PREINIT_ARRAY [[# %x, PREINIT_ADDR:]] [[# %x,]] [[# %x, PREINIT_SIZE:]] 08 WA
+// CHECK-NEXT: .fini_array FINI_ARRAY [[# %x, FINI_ADDR:]] [[# %x,]] [[# %x, FINI_SIZE:]] 08 WA
// CHECK-LABEL: Dynamic section
// CHECK: (PREINIT_ARRAY) 0x[[# PREINIT_ADDR]]
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 6e52fcbdbb0fe..47b6347d82f8c 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -867,6 +867,7 @@ void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
uint64_t Size, const MCSectionELF &Section) {
uint64_t sh_link = 0;
uint64_t sh_info = 0;
+ uint64_t EntrySize = Section.getEntrySize();
switch(Section.getType()) {
default:
@@ -901,6 +902,14 @@ void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
sh_link = SymbolTableIndex;
sh_info = GroupSymbolIndex;
break;
+
+ case ELF::SHT_INIT_ARRAY:
+ case ELF::SHT_FINI_ARRAY:
+ case ELF::SHT_PREINIT_ARRAY:
+ // Match GAS, which uses the pointer size regardless of sh_size.
+ if (!EntrySize)
+ EntrySize = is64Bit() ? 8 : 4;
+ break;
}
if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
@@ -914,7 +923,7 @@ void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()),
Section.getType(), Section.getFlags(), 0, Offset,
Size, sh_link, sh_info, Section.getAlign(),
- Section.getEntrySize());
+ EntrySize);
}
void ELFWriter::writeSectionHeaders() {
diff --git a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
index d4f3ec2387e60..8438934a649fc 100644
--- a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
+++ b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
@@ -17,8 +17,8 @@
; VISIBILITY: FUNC WEAK PROTECTED {{.*}} amdgcn.device.fini
; VISIBILITY: OBJECT WEAK DEFAULT {{.*}} amdgcn.device.fini.kd
-; SECTION: .init_array.1 INIT_ARRAY {{.*}} {{.*}} 000008 00 WA 0 0 8
-; SECTION: .fini_array.1 FINI_ARRAY {{.*}} {{.*}} 000008 00 WA 0 0 8
+; SECTION: .init_array.1 INIT_ARRAY {{.*}} {{.*}} 000008 08 WA 0 0 8
+; SECTION: .fini_array.1 FINI_ARRAY {{.*}} {{.*}} 000008 08 WA 0 0 8
; DISABLED-NOT: FUNC GLOBAL PROTECTED {{.*}} amdgcn.device.init
; DISABLED-NOT: OBJECT GLOBAL DEFAULT {{.*}} amdgcn.device.init.kd
diff --git a/llvm/test/MC/AsmParser/section_names.s b/llvm/test/MC/AsmParser/section_names.s
index 2e8d1f957b9a1..e37e166f7c130 100644
--- a/llvm/test/MC/AsmParser/section_names.s
+++ b/llvm/test/MC/AsmParser/section_names.s
@@ -1,34 +1,34 @@
# RUN: llvm-mc -triple i386-pc-linux-gnu -filetype=obj -o %t %s
# RUN: llvm-readelf -S %t | FileCheck %s
-# CHECK: Name Type {{.*}} Flg Lk Inf Al
-# CHECK: .note NOTE {{.*}} 0 0 1
-# CHECK-NEXT: .note2 NOTE {{.*}} 0 0 1
-# CHECK-NEXT: .notefoo NOTE {{.*}} 0 0 1
-# CHECK-NEXT: .rodata.foo PROGBITS {{.*}} A 0 0 1
-# CHECK-NEXT: .rodatafoo PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .rodata1 PROGBITS {{.*}} A 0 0 1
-# CHECK-NEXT: .tdata.foo PROGBITS {{.*}} WAT 0 0 1
-# CHECK-NEXT: .tbss NOBITS {{.*}} WAT 0 0 1
-# CHECK-NEXT: .tbss.foo NOBITS {{.*}} WAT 0 0 1
-# CHECK-NEXT: .init_array INIT_ARRAY {{.*}} WA 0 0 1
-# CHECK-NEXT: .init_array.42 INIT_ARRAY {{.*}} WA 0 0 1
-# CHECK-NEXT: .init_array2 PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .init_arrayfoo PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .fini_array FINI_ARRAY {{.*}} WA 0 0 1
-# CHECK-NEXT: .fini_array2 PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .fini_arrayfoo PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .preinit_array PREINIT_ARRAY {{.*}} WA 0 0 1
-# CHECK-NEXT: .preinit_array2 PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .preinit_array.x PREINIT_ARRAY {{.*}} WA 0 0 1
-# CHECK-NEXT: .data.foo PROGBITS {{.*}} WA 0 0 1
-# CHECK-NEXT: .data1 PROGBITS {{.*}} WA 0 0 1
-# CHECK-NEXT: .data2 PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .bss NOBITS {{.*}} WA 0 0 1
-# CHECK-NEXT: .bss.foo NOBITS {{.*}} WA 0 0 1
-# CHECK-NEXT: .nobits PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .nobits2 PROGBITS {{.*}} 0 0 1
-# CHECK-NEXT: .nobitsfoo PROGBITS {{.*}} 0 0 1
+# CHECK: Name Type {{.*}} ES Flg Lk Inf Al
+# CHECK: .note NOTE {{.*}} 00 0 0 1
+# CHECK-NEXT: .note2 NOTE {{.*}} 00 0 0 1
+# CHECK-NEXT: .notefoo NOTE {{.*}} 00 0 0 1
+# CHECK-NEXT: .rodata.foo PROGBITS {{.*}} 00 A 0 0 1
+# CHECK-NEXT: .rodatafoo PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .rodata1 PROGBITS {{.*}} 00 A 0 0 1
+# CHECK-NEXT: .tdata.foo PROGBITS {{.*}} 00 WAT 0 0 1
+# CHECK-NEXT: .tbss NOBITS {{.*}} 00 WAT 0 0 1
+# CHECK-NEXT: .tbss.foo NOBITS {{.*}} 00 WAT 0 0 1
+# CHECK-NEXT: .init_array INIT_ARRAY {{.*}} 04 WA 0 0 1
+# CHECK-NEXT: .init_array.42 INIT_ARRAY {{.*}} 04 WA 0 0 1
+# CHECK-NEXT: .init_array2 PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .init_arrayfoo PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .fini_array FINI_ARRAY {{.*}} 04 WA 0 0 1
+# CHECK-NEXT: .fini_array2 PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .fini_arrayfoo PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .preinit_array PREINIT_ARRAY {{.*}} 04 WA 0 0 1
+# CHECK-NEXT: .preinit_array2 PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .preinit_array.x PREINIT_ARRAY {{.*}} 04 WA 0 0 1
+# CHECK-NEXT: .data.foo PROGBITS {{.*}} 00 WA 0 0 1
+# CHECK-NEXT: .data1 PROGBITS {{.*}} 00 WA 0 0 1
+# CHECK-NEXT: .data2 PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .bss NOBITS {{.*}} 00 WA 0 0 1
+# CHECK-NEXT: .bss.foo NOBITS {{.*}} 00 WA 0 0 1
+# CHECK-NEXT: .nobits PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .nobits2 PROGBITS {{.*}} 00 0 0 1
+# CHECK-NEXT: .nobitsfoo PROGBITS {{.*}} 00 0 0 1
.section .note
diff --git a/llvm/test/MC/ELF/section.s b/llvm/test/MC/ELF/section.s
index f062311427364..97d7537398b07 100644
--- a/llvm/test/MC/ELF/section.s
+++ b/llvm/test/MC/ELF/section.s
@@ -290,6 +290,44 @@ bar:
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
+.section .init_array,"aw", at init_array
+.byte 0
+// ASM: .section .init_array,"aw", at init_array
+
+// CHECK: Section {
+// CHECK: Name: .init_array
+// CHECK-NEXT: Type: SHT_INIT_ARRAY
+// CHECK: Size: 1
+// CHECK: EntrySize: 8
+// CHECK-NEXT: }
+
+.section .fini_array,"aw", at fini_array
+// ASM: .section .fini_array,"aw", at fini_array
+
+// CHECK: Section {
+// CHECK: Name: .fini_array
+// CHECK-NEXT: Type: SHT_FINI_ARRAY
+// CHECK: EntrySize: 8
+// CHECK-NEXT: }
+
+.section .preinit_array,"aw", at preinit_array
+// ASM: .section .preinit_array,"aw", at preinit_array
+
+// CHECK: Section {
+// CHECK: Name: .preinit_array
+// CHECK-NEXT: Type: SHT_PREINIT_ARRAY
+// CHECK: EntrySize: 8
+// CHECK-NEXT: }
+
+.section .init_array.16,"awM", at init_array,16
+// ASM: .section .init_array.16,"awM", at init_array,16
+
+// CHECK: Section {
+// CHECK: Name: .init_array.16
+// CHECK-NEXT: Type: SHT_INIT_ARRAY
+// CHECK: EntrySize: 16
+// CHECK-NEXT: }
+
.section .large,"l"
// ASM: .section .large,"l"
More information about the llvm-commits
mailing list