elf: make init/fini sorting deterministic
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user