zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit b7a544c527f0d54cf9d044f26daf272e9297a786 (tree)
parent 9ff926bb1e47ebad0f13835355841ef4654fbe60
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date:   Mon, 15 Jun 2026 17:57:52 +0100

Elf2: always define `__init_array_start` and friends

These symbols should exist even if there is no actual `.init_array` (or
whichever) section. So, always define them, and if we end up creating
the corresponding section, just update the symbols' values.

Diffstat:
Msrc/link/Elf2.zig | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 81 insertions(+), 21 deletions(-)

diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig @@ -3254,7 +3254,7 @@ fn initHeaders( // `FINI_ARRAY`/`PREINIT_ARRAY` sections are instead created by `createInitFiniArraySection` // when needed (it seems to be legal to leave those undefined if the section doesn't exist). - try elf.ensureUnusedSymbolCapacity(4, .maybe_global); + try elf.ensureUnusedSymbolCapacity(10, .maybe_global); // Despite the name, `__dso_handle` is necessary even in static binaries. _ = elf.addGlobalSymbolAssumeCapacity(.{ .node = Section.Index.text.get(elf).ni, @@ -3292,6 +3292,78 @@ fn initHeaders( }) catch |err| switch (err) { error.MultipleDefinitions => unreachable, // no inputs are processed yet }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__init_array_start"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__init_array_end"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__fini_array_start"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__fini_array_end"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__preinit_array_start"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; + _ = elf.addGlobalSymbolAssumeCapacity(.{ + .node = .none, + .name = try .string(elf, "__preinit_array_end"), + .value = 0, + .size = 0, + .type = .NOTYPE, + .bind = .strong, + .visibility = .HIDDEN, + .shndx = .ABS, + }) catch |err| switch (err) { + error.MultipleDefinitions => unreachable, // no inputs are processed yet + }; if (have_dynamic_section) { _ = elf.addGlobalSymbolAssumeCapacity(.{ .node = elf.shndx.dynamic.get(elf).ni, @@ -4759,36 +4831,24 @@ fn createInitFiniArraySection( }); elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); try elf.ensureUnusedSymbolCapacity(2, .maybe_global); - _ = elf.addGlobalSymbolAssumeCapacity(.{ + // These symbols definitely already have strong definitions, because we added them alongside the + // other linker-defined symbols, all the way back in `initHeaders`. + const start_sym_name = try elf.string(.strtab, "__" ++ name ++ "_start"); + const end_sym_name = try elf.string(.strtab, "__" ++ name ++ "_end"); + elf.setGlobalSymbolValue(start_sym_name, elf.globals.strong_def.getPtr(start_sym_name).?, .{ .node = shndx.get(elf).ni, - .name = try .string(elf, "__" ++ name ++ "_start"), .value = shndx.vaddr(elf), .size = 0, .type = .NOTYPE, - .bind = .strong, - .visibility = .HIDDEN, .shndx = shndx.*, - }) catch |err| switch (err) { - error.MultipleDefinitions => return elf.base.comp.link_diags.fail( - "multiple definitions of '{s}'", - .{"__" ++ name ++ "_start"}, - ), - }; - _ = elf.addGlobalSymbolAssumeCapacity(.{ + }); + elf.setGlobalSymbolValue(end_sym_name, elf.globals.strong_def.getPtr(end_sym_name).?, .{ .node = shndx.get(elf).ni, - .name = try .string(elf, "__" ++ name ++ "_end"), .value = shndx.vaddr(elf), .size = 0, .type = .NOTYPE, - .bind = .strong, - .visibility = .HIDDEN, .shndx = shndx.*, - }) catch |err| switch (err) { - error.MultipleDefinitions => return elf.base.comp.link_diags.fail( - "multiple definitions of '{s}'", - .{"__" ++ name ++ "_end"}, - ), - }; + }); } fn updateInitFiniArraySectionSize( elf: *Elf,