commit 39064347460d1f8cd72ada1e77618fc2b83f8d0d (tree)
parent ce198b7c28e89c0bb502d215f9f9de99abb25f08
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Tue, 28 Apr 2026 16:01:44 +0200
link.Elf: implement .preinit_array support
Diffstat:
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -1392,9 +1392,9 @@ pub fn initOutputSection(self: *Elf, args: struct {
if (self.base.isRelocatable()) break :blk args.name;
if (args.flags & elf.SHF_MERGE != 0) break :blk args.name;
const name_prefixes: []const [:0]const u8 = &.{
- ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
- ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors",
- ".dtors", ".gnu.warning",
+ ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
+ ".preinit_array", ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table",
+ ".ctors", ".dtors", ".gnu.warning",
};
inline for (name_prefixes) |prefix| {
if (mem.eql(u8, args.name, prefix) or mem.startsWith(u8, args.name, prefix ++ ".")) {
@@ -1409,6 +1409,8 @@ pub fn initOutputSection(self: *Elf, args: struct {
switch (args.type) {
elf.SHT_NULL => unreachable,
elf.SHT_PROGBITS => {
+ if (mem.eql(u8, args.name, ".preinit_array") or mem.startsWith(u8, args.name, ".preinit_array."))
+ break :tt elf.SHT_PREINIT_ARRAY;
if (mem.eql(u8, args.name, ".init_array") or mem.startsWith(u8, args.name, ".init_array."))
break :tt elf.SHT_INIT_ARRAY;
if (mem.eql(u8, args.name, ".fini_array") or mem.startsWith(u8, args.name, ".fini_array."))
diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig
@@ -1237,6 +1237,10 @@ fn getNavShdrIndex(
self.debug_rnglists_index = section_index;
} else if (std.mem.startsWith(u8, section_name, ".debug")) {
elf_file.sections.items(.shdr)[osec].sh_flags = 0;
+ } else if (std.mem.eql(u8, section_name, ".preinit_array") or std.mem.startsWith(u8, section_name, ".preinit_array.")) {
+ const shdr = &elf_file.sections.items(.shdr)[osec];
+ shdr.sh_type = elf.SHT_PREINIT_ARRAY;
+ shdr.sh_flags = elf.SHF_ALLOC | elf.SHF_WRITE;
} else if (std.mem.eql(u8, section_name, ".init_array") or std.mem.startsWith(u8, section_name, ".init_array.")) {
const shdr = &elf_file.sections.items(.shdr)[osec];
shdr.sh_type = elf.SHT_INIT_ARRAY;
diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig
@@ -73,6 +73,7 @@ pub const DynamicSection = struct {
if (dt.rpath > 0) nentries += 1; // RUNPATH
if (elf_file.sectionByName(".init") != null) nentries += 1; // INIT
if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI
+ if (elf_file.sectionByName(".preinit_array") != null) nentries += 2; // PREINIT_ARRAY
if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY
if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY
if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA
@@ -124,6 +125,13 @@ pub const DynamicSection = struct {
try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little);
}
+ // PREINIT_ARRAY
+ if (elf_file.sectionByName(".preinit_array")) |shndx| {
+ const shdr = shdrs[shndx];
+ try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PREINIT_ARRAY, .d_val = shdr.sh_addr }), .little);
+ try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PREINIT_ARRAYSZ, .d_val = shdr.sh_size }), .little);
+ }
+
// INIT_ARRAY
if (elf_file.sectionByName(".init_array")) |shndx| {
const shdr = shdrs[shndx];