[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