authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-28 16:01:44+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-28 16:42:06+02:00
log39064347460d1f8cd72ada1e77618fc2b83f8d0d
treead5277dd522f6b0d8110fce283eb341810370f62
parentce198b7c28e89c0bb502d215f9f9de99abb25f08
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

link.Elf: implement .preinit_array support


3 files changed, 17 insertions(+), 3 deletions(-)

src/link/Elf.zig+5-3
...@@ -1392,9 +1392,9 @@ pub fn initOutputSection(self: *Elf, args: struct {...@@ -1392,9 +1392,9 @@ pub fn initOutputSection(self: *Elf, args: struct {
1392 if (self.base.isRelocatable()) break :blk args.name;1392 if (self.base.isRelocatable()) break :blk args.name;
1393 if (args.flags & elf.SHF_MERGE != 0) break :blk args.name;1393 if (args.flags & elf.SHF_MERGE != 0) break :blk args.name;
1394 const name_prefixes: []const [:0]const u8 = &.{1394 const name_prefixes: []const [:0]const u8 = &.{
1395 ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",1395 ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
1396 ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors",1396 ".preinit_array", ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table",
1397 ".dtors", ".gnu.warning",1397 ".ctors", ".dtors", ".gnu.warning",
1398 };1398 };
1399 inline for (name_prefixes) |prefix| {1399 inline for (name_prefixes) |prefix| {
1400 if (mem.eql(u8, args.name, prefix) or mem.startsWith(u8, args.name, prefix ++ ".")) {1400 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 {...@@ -1409,6 +1409,8 @@ pub fn initOutputSection(self: *Elf, args: struct {
1409 switch (args.type) {1409 switch (args.type) {
1410 elf.SHT_NULL => unreachable,1410 elf.SHT_NULL => unreachable,
1411 elf.SHT_PROGBITS => {1411 elf.SHT_PROGBITS => {
1412 if (mem.eql(u8, args.name, ".preinit_array") or mem.startsWith(u8, args.name, ".preinit_array."))
1413 break :tt elf.SHT_PREINIT_ARRAY;
1412 if (mem.eql(u8, args.name, ".init_array") or mem.startsWith(u8, args.name, ".init_array."))1414 if (mem.eql(u8, args.name, ".init_array") or mem.startsWith(u8, args.name, ".init_array."))
1413 break :tt elf.SHT_INIT_ARRAY;1415 break :tt elf.SHT_INIT_ARRAY;
1414 if (mem.eql(u8, args.name, ".fini_array") or mem.startsWith(u8, args.name, ".fini_array."))1416 if (mem.eql(u8, args.name, ".fini_array") or mem.startsWith(u8, args.name, ".fini_array."))
src/link/Elf/ZigObject.zig+4
...@@ -1237,6 +1237,10 @@ fn getNavShdrIndex(...@@ -1237,6 +1237,10 @@ fn getNavShdrIndex(
1237 self.debug_rnglists_index = section_index;1237 self.debug_rnglists_index = section_index;
1238 } else if (std.mem.startsWith(u8, section_name, ".debug")) {1238 } else if (std.mem.startsWith(u8, section_name, ".debug")) {
1239 elf_file.sections.items(.shdr)[osec].sh_flags = 0;1239 elf_file.sections.items(.shdr)[osec].sh_flags = 0;
1240 } else if (std.mem.eql(u8, section_name, ".preinit_array") or std.mem.startsWith(u8, section_name, ".preinit_array.")) {
1241 const shdr = &elf_file.sections.items(.shdr)[osec];
1242 shdr.sh_type = elf.SHT_PREINIT_ARRAY;
1243 shdr.sh_flags = elf.SHF_ALLOC | elf.SHF_WRITE;
1240 } else if (std.mem.eql(u8, section_name, ".init_array") or std.mem.startsWith(u8, section_name, ".init_array.")) {1244 } else if (std.mem.eql(u8, section_name, ".init_array") or std.mem.startsWith(u8, section_name, ".init_array.")) {
1241 const shdr = &elf_file.sections.items(.shdr)[osec];1245 const shdr = &elf_file.sections.items(.shdr)[osec];
1242 shdr.sh_type = elf.SHT_INIT_ARRAY;1246 shdr.sh_type = elf.SHT_INIT_ARRAY;
src/link/Elf/synthetic_sections.zig+8
...@@ -73,6 +73,7 @@ pub const DynamicSection = struct {...@@ -73,6 +73,7 @@ pub const DynamicSection = struct {
73 if (dt.rpath > 0) nentries += 1; // RUNPATH73 if (dt.rpath > 0) nentries += 1; // RUNPATH
74 if (elf_file.sectionByName(".init") != null) nentries += 1; // INIT74 if (elf_file.sectionByName(".init") != null) nentries += 1; // INIT
75 if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI75 if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI
76 if (elf_file.sectionByName(".preinit_array") != null) nentries += 2; // PREINIT_ARRAY
76 if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY77 if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY
77 if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY78 if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY
78 if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA79 if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA
...@@ -124,6 +125,13 @@ pub const DynamicSection = struct {...@@ -124,6 +125,13 @@ pub const DynamicSection = struct {
124 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little);125 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little);
125 }126 }
126127
128 // PREINIT_ARRAY
129 if (elf_file.sectionByName(".preinit_array")) |shndx| {
130 const shdr = shdrs[shndx];
131 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PREINIT_ARRAY, .d_val = shdr.sh_addr }), .little);
132 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PREINIT_ARRAYSZ, .d_val = shdr.sh_size }), .little);
133 }
134
127 // INIT_ARRAY135 // INIT_ARRAY
128 if (elf_file.sectionByName(".init_array")) |shndx| {136 if (elf_file.sectionByName(".init_array")) |shndx| {
129 const shdr = shdrs[shndx];137 const shdr = shdrs[shndx];