diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 318c1c8a03af772cd776c214ba7da44f974697ae..a5fb6163ee3881ed50eeb7f55c2f0c1e2d763907 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -4123,6 +4123,21 @@ fn initSections(self: *Elf) !void { } } +/// We need to sort constructors/destuctors in the following sections: +/// * .init_array +/// * .fini_array +/// * .preinit_array +/// * .ctors +/// * .dtors +/// The prority of inclusion is defined as part of the input section's name. For example, .init_array.10000. +/// If no priority value has been specified, +/// * for .init_array, .fini_array and .preinit_array, we automatically assign that section max value of maxInt(i32) +/// and push it to the back of the queue, +/// * for .ctors and .dtors, we automatically assign that section min value of -1 +/// and push it to the front of the queue, +/// crtbegin and ctrend are assigned minInt(i32) and maxInt(i32) respectively. +/// Ties are broken by the file prority which corresponds to the inclusion of input sections in this output section +/// we are about to sort. fn sortInitFini(self: *Elf) !void { const gpa = self.base.allocator; @@ -4130,8 +4145,10 @@ fn sortInitFini(self: *Elf) !void { priority: i32, atom_index: Atom.Index, - pub fn lessThan(ctx: void, lhs: @This(), rhs: @This()) bool { - _ = ctx; + pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool { + if (lhs.priority == rhs.priority) { + return ctx.atom(lhs.atom_index).?.priority(ctx) < ctx.atom(rhs.atom_index).?.priority(ctx); + } return lhs.priority < rhs.priority; } }; @@ -4177,7 +4194,7 @@ fn sortInitFini(self: *Elf) !void { entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index }); } - mem.sort(Entry, entries.items, {}, Entry.lessThan); + mem.sort(Entry, entries.items, self, Entry.lessThan); atom_list.clearRetainingCapacity(); for (entries.items) |entry| { @@ -4387,8 +4404,18 @@ fn sortSections(self: *Elf) !void { } fn updateSectionSizes(self: *Elf) !void { - for (self.objects.items) |index| { - self.file(index).?.object.updateSectionSizes(self); + for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { + if (atom_list.items.len == 0) continue; + const shdr = &self.shdrs.items[shndx]; + for (atom_list.items) |atom_index| { + const atom_ptr = self.atom(atom_index) orelse continue; + if (!atom_ptr.flags.alive) continue; + const offset = atom_ptr.alignment.forward(shdr.sh_size); + const padding = offset - shdr.sh_size; + atom_ptr.value = offset; + shdr.sh_size += padding + atom_ptr.size; + shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); + } } if (self.eh_frame_section_index) |index| { @@ -4668,12 +4695,12 @@ fn allocateSectionsInMemory(self: *Elf, base_offset: u64) !void { tls_start_align: u64 = 1, first_tls_index: ?usize = null, - inline fn isFirstTlsShdr(this: @This(), other: usize) bool { + fn isFirstTlsShdr(this: @This(), other: usize) bool { if (this.first_tls_index) |index| return index == other; return false; } - inline fn @"align"(this: @This(), index: usize, sh_addralign: u64, addr: u64) u64 { + fn @"align"(this: @This(), index: usize, sh_addralign: u64, addr: u64) u64 { const alignment = if (this.isFirstTlsShdr(index)) this.tls_start_align else sh_addralign; return mem.alignForward(u64, addr, alignment); } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 1d7406324064c30d795186ae526c300dcefb0519..3c42a0e3495690998bac1822721c37282136d835 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -630,7 +630,6 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { const shdr = atom.inputShdr(elf_file); atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; - if (shdr.sh_type == elf.SHT_NOBITS) continue; const gpa = elf_file.base.allocator; const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -638,19 +637,6 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { } } -pub fn updateSectionSizes(self: Object, elf_file: *Elf) void { - for (self.atoms.items) |atom_index| { - const atom = elf_file.atom(atom_index) orelse continue; - if (!atom.flags.alive) continue; - const shdr = &elf_file.shdrs.items[atom.output_section_index]; - const offset = atom.alignment.forward(shdr.sh_size); - const padding = offset - shdr.sh_size; - atom.value = offset; - shdr.sh_size += padding + atom.size; - shdr.sh_addralign = @max(shdr.sh_addralign, atom.alignment.toByteUnits(1)); - } -} - pub fn allocateAtoms(self: Object, elf_file: *Elf) void { for (self.atoms.items) |atom_index| { const atom = elf_file.atom(atom_index) orelse continue;