authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-15 17:57:52+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-16 13:02:06+02:00
logb7a544c527f0d54cf9d044f26daf272e9297a786
treeb61320bffbaf1c7e45a457d19a25591ab022f89e
parent9ff926bb1e47ebad0f13835355841ef4654fbe60

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.

1 files changed, 81 insertions(+), 21 deletions(-)

src/link/Elf2.zig+81-21
...@@ -3254,7 +3254,7 @@ fn initHeaders(...@@ -3254,7 +3254,7 @@ fn initHeaders(
3254 // `FINI_ARRAY`/`PREINIT_ARRAY` sections are instead created by `createInitFiniArraySection`3254 // `FINI_ARRAY`/`PREINIT_ARRAY` sections are instead created by `createInitFiniArraySection`
3255 // when needed (it seems to be legal to leave those undefined if the section doesn't exist).3255 // when needed (it seems to be legal to leave those undefined if the section doesn't exist).
32563256
3257 try elf.ensureUnusedSymbolCapacity(4, .maybe_global);3257 try elf.ensureUnusedSymbolCapacity(10, .maybe_global);
3258 // Despite the name, `__dso_handle` is necessary even in static binaries.3258 // Despite the name, `__dso_handle` is necessary even in static binaries.
3259 _ = elf.addGlobalSymbolAssumeCapacity(.{3259 _ = elf.addGlobalSymbolAssumeCapacity(.{
3260 .node = Section.Index.text.get(elf).ni,3260 .node = Section.Index.text.get(elf).ni,
...@@ -3292,6 +3292,78 @@ fn initHeaders(...@@ -3292,6 +3292,78 @@ fn initHeaders(
3292 }) catch |err| switch (err) {3292 }) catch |err| switch (err) {
3293 error.MultipleDefinitions => unreachable, // no inputs are processed yet3293 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3294 };3294 };
3295 _ = elf.addGlobalSymbolAssumeCapacity(.{
3296 .node = .none,
3297 .name = try .string(elf, "__init_array_start"),
3298 .value = 0,
3299 .size = 0,
3300 .type = .NOTYPE,
3301 .bind = .strong,
3302 .visibility = .HIDDEN,
3303 .shndx = .ABS,
3304 }) catch |err| switch (err) {
3305 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3306 };
3307 _ = elf.addGlobalSymbolAssumeCapacity(.{
3308 .node = .none,
3309 .name = try .string(elf, "__init_array_end"),
3310 .value = 0,
3311 .size = 0,
3312 .type = .NOTYPE,
3313 .bind = .strong,
3314 .visibility = .HIDDEN,
3315 .shndx = .ABS,
3316 }) catch |err| switch (err) {
3317 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3318 };
3319 _ = elf.addGlobalSymbolAssumeCapacity(.{
3320 .node = .none,
3321 .name = try .string(elf, "__fini_array_start"),
3322 .value = 0,
3323 .size = 0,
3324 .type = .NOTYPE,
3325 .bind = .strong,
3326 .visibility = .HIDDEN,
3327 .shndx = .ABS,
3328 }) catch |err| switch (err) {
3329 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3330 };
3331 _ = elf.addGlobalSymbolAssumeCapacity(.{
3332 .node = .none,
3333 .name = try .string(elf, "__fini_array_end"),
3334 .value = 0,
3335 .size = 0,
3336 .type = .NOTYPE,
3337 .bind = .strong,
3338 .visibility = .HIDDEN,
3339 .shndx = .ABS,
3340 }) catch |err| switch (err) {
3341 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3342 };
3343 _ = elf.addGlobalSymbolAssumeCapacity(.{
3344 .node = .none,
3345 .name = try .string(elf, "__preinit_array_start"),
3346 .value = 0,
3347 .size = 0,
3348 .type = .NOTYPE,
3349 .bind = .strong,
3350 .visibility = .HIDDEN,
3351 .shndx = .ABS,
3352 }) catch |err| switch (err) {
3353 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3354 };
3355 _ = elf.addGlobalSymbolAssumeCapacity(.{
3356 .node = .none,
3357 .name = try .string(elf, "__preinit_array_end"),
3358 .value = 0,
3359 .size = 0,
3360 .type = .NOTYPE,
3361 .bind = .strong,
3362 .visibility = .HIDDEN,
3363 .shndx = .ABS,
3364 }) catch |err| switch (err) {
3365 error.MultipleDefinitions => unreachable, // no inputs are processed yet
3366 };
3295 if (have_dynamic_section) {3367 if (have_dynamic_section) {
3296 _ = elf.addGlobalSymbolAssumeCapacity(.{3368 _ = elf.addGlobalSymbolAssumeCapacity(.{
3297 .node = elf.shndx.dynamic.get(elf).ni,3369 .node = elf.shndx.dynamic.get(elf).ni,
...@@ -4759,36 +4831,24 @@ fn createInitFiniArraySection(...@@ -4759,36 +4831,24 @@ fn createInitFiniArraySection(
4759 });4831 });
4760 elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {});4832 elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {});
4761 try elf.ensureUnusedSymbolCapacity(2, .maybe_global);4833 try elf.ensureUnusedSymbolCapacity(2, .maybe_global);
4762 _ = elf.addGlobalSymbolAssumeCapacity(.{4834 // These symbols definitely already have strong definitions, because we added them alongside the
4835 // other linker-defined symbols, all the way back in `initHeaders`.
4836 const start_sym_name = try elf.string(.strtab, "__" ++ name ++ "_start");
4837 const end_sym_name = try elf.string(.strtab, "__" ++ name ++ "_end");
4838 elf.setGlobalSymbolValue(start_sym_name, elf.globals.strong_def.getPtr(start_sym_name).?, .{
4763 .node = shndx.get(elf).ni,4839 .node = shndx.get(elf).ni,
4764 .name = try .string(elf, "__" ++ name ++ "_start"),
4765 .value = shndx.vaddr(elf),4840 .value = shndx.vaddr(elf),
4766 .size = 0,4841 .size = 0,
4767 .type = .NOTYPE,4842 .type = .NOTYPE,
4768 .bind = .strong,
4769 .visibility = .HIDDEN,
4770 .shndx = shndx.*,4843 .shndx = shndx.*,
4771 }) catch |err| switch (err) {4844 });
4772 error.MultipleDefinitions => return elf.base.comp.link_diags.fail(4845 elf.setGlobalSymbolValue(end_sym_name, elf.globals.strong_def.getPtr(end_sym_name).?, .{
4773 "multiple definitions of '{s}'",
4774 .{"__" ++ name ++ "_start"},
4775 ),
4776 };
4777 _ = elf.addGlobalSymbolAssumeCapacity(.{
4778 .node = shndx.get(elf).ni,4846 .node = shndx.get(elf).ni,
4779 .name = try .string(elf, "__" ++ name ++ "_end"),
4780 .value = shndx.vaddr(elf),4847 .value = shndx.vaddr(elf),
4781 .size = 0,4848 .size = 0,
4782 .type = .NOTYPE,4849 .type = .NOTYPE,
4783 .bind = .strong,
4784 .visibility = .HIDDEN,
4785 .shndx = shndx.*,4850 .shndx = shndx.*,
4786 }) catch |err| switch (err) {4851 });
4787 error.MultipleDefinitions => return elf.base.comp.link_diags.fail(
4788 "multiple definitions of '{s}'",
4789 .{"__" ++ name ++ "_end"},
4790 ),
4791 };
4792}4852}
4793fn updateInitFiniArraySectionSize(4853fn updateInitFiniArraySectionSize(
4794 elf: *Elf,4854 elf: *Elf,