authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-09 14:23:46+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log1efc0519ce711ba8e7ee4d621a5bd13766c23020
tree68bcbe45a77cde87b12d391afde9257554253021
parent44f30858515935a8b02c23e8d6663ac9a090e251

elf: make init/fini sorting deterministic


2 files changed, 34 insertions(+), 21 deletions(-)

src/link/Elf.zig+34-7
......@@ -4123,6 +4123,21 @@ fn initSections(self: *Elf) !void {
41234123 }
41244124}
41254125
4126/// We need to sort constructors/destuctors in the following sections:
4127/// * .init_array
4128/// * .fini_array
4129/// * .preinit_array
4130/// * .ctors
4131/// * .dtors
4132/// The prority of inclusion is defined as part of the input section's name. For example, .init_array.10000.
4133/// If no priority value has been specified,
4134/// * for .init_array, .fini_array and .preinit_array, we automatically assign that section max value of maxInt(i32)
4135/// and push it to the back of the queue,
4136/// * for .ctors and .dtors, we automatically assign that section min value of -1
4137/// and push it to the front of the queue,
4138/// crtbegin and ctrend are assigned minInt(i32) and maxInt(i32) respectively.
4139/// Ties are broken by the file prority which corresponds to the inclusion of input sections in this output section
4140/// we are about to sort.
41264141fn sortInitFini(self: *Elf) !void {
41274142 const gpa = self.base.allocator;
41284143
......@@ -4130,8 +4145,10 @@ fn sortInitFini(self: *Elf) !void {
41304145 priority: i32,
41314146 atom_index: Atom.Index,
41324147
4133 pub fn lessThan(ctx: void, lhs: @This(), rhs: @This()) bool {
4134 _ = ctx;
4148 pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool {
4149 if (lhs.priority == rhs.priority) {
4150 return ctx.atom(lhs.atom_index).?.priority(ctx) < ctx.atom(rhs.atom_index).?.priority(ctx);
4151 }
41354152 return lhs.priority < rhs.priority;
41364153 }
41374154 };
......@@ -4177,7 +4194,7 @@ fn sortInitFini(self: *Elf) !void {
41774194 entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index });
41784195 }
41794196
4180 mem.sort(Entry, entries.items, {}, Entry.lessThan);
4197 mem.sort(Entry, entries.items, self, Entry.lessThan);
41814198
41824199 atom_list.clearRetainingCapacity();
41834200 for (entries.items) |entry| {
......@@ -4387,8 +4404,18 @@ fn sortSections(self: *Elf) !void {
43874404}
43884405
43894406fn updateSectionSizes(self: *Elf) !void {
4390 for (self.objects.items) |index| {
4391 self.file(index).?.object.updateSectionSizes(self);
4407 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
4408 if (atom_list.items.len == 0) continue;
4409 const shdr = &self.shdrs.items[shndx];
4410 for (atom_list.items) |atom_index| {
4411 const atom_ptr = self.atom(atom_index) orelse continue;
4412 if (!atom_ptr.flags.alive) continue;
4413 const offset = atom_ptr.alignment.forward(shdr.sh_size);
4414 const padding = offset - shdr.sh_size;
4415 atom_ptr.value = offset;
4416 shdr.sh_size += padding + atom_ptr.size;
4417 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1));
4418 }
43924419 }
43934420
43944421 if (self.eh_frame_section_index) |index| {
......@@ -4668,12 +4695,12 @@ fn allocateSectionsInMemory(self: *Elf, base_offset: u64) !void {
46684695 tls_start_align: u64 = 1,
46694696 first_tls_index: ?usize = null,
46704697
4671 inline fn isFirstTlsShdr(this: @This(), other: usize) bool {
4698 fn isFirstTlsShdr(this: @This(), other: usize) bool {
46724699 if (this.first_tls_index) |index| return index == other;
46734700 return false;
46744701 }
46754702
4676 inline fn @"align"(this: @This(), index: usize, sh_addralign: u64, addr: u64) u64 {
4703 fn @"align"(this: @This(), index: usize, sh_addralign: u64, addr: u64) u64 {
46774704 const alignment = if (this.isFirstTlsShdr(index)) this.tls_start_align else sh_addralign;
46784705 return mem.alignForward(u64, addr, alignment);
46794706 }
src/link/Elf/Object.zig-14
......@@ -630,7 +630,6 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
630630 const shdr = atom.inputShdr(elf_file);
631631 atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
632632
633 if (shdr.sh_type == elf.SHT_NOBITS) continue;
634633 const gpa = elf_file.base.allocator;
635634 const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index);
636635 if (!gop.found_existing) gop.value_ptr.* = .{};
......@@ -638,19 +637,6 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
638637 }
639638}
640639
641pub fn updateSectionSizes(self: Object, elf_file: *Elf) void {
642 for (self.atoms.items) |atom_index| {
643 const atom = elf_file.atom(atom_index) orelse continue;
644 if (!atom.flags.alive) continue;
645 const shdr = &elf_file.shdrs.items[atom.output_section_index];
646 const offset = atom.alignment.forward(shdr.sh_size);
647 const padding = offset - shdr.sh_size;
648 atom.value = offset;
649 shdr.sh_size += padding + atom.size;
650 shdr.sh_addralign = @max(shdr.sh_addralign, atom.alignment.toByteUnits(1));
651 }
652}
653
654640pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
655641 for (self.atoms.items) |atom_index| {
656642 const atom = elf_file.atom(atom_index) orelse continue;