From 46cf4c5d9343af5da484b808a5c3153736ec62e9 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 15 Oct 2023 16:05:43 +0200 Subject: [PATCH] elf: sort phdr table --- src/link/Elf.zig | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 589a13d0ad..6d7a459965 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1573,6 +1573,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node self.allocatePhdrTable(); try self.allocateAllocSections(); + try self.sortPhdrs(); try self.allocateNonAllocSections(); self.allocateSpecialPhdrs(); self.allocateAtoms(); @@ -4076,6 +4077,77 @@ fn setHashSections(self: *Elf) !void { } } +fn phdrRank(self: *Elf, phndx: u16) u8 { + const phdr = self.phdrs.items[phndx]; + const flags = phdr.p_flags; + switch (phdr.p_type) { + elf.PT_NULL => return 0, + elf.PT_PHDR => return 1, + elf.PT_INTERP => return 2, + elf.PT_LOAD => if (flags & elf.PF_X != 0) { + return 4; + } else if (flags & elf.PF_W != 0) { + return 5; + } else { + return 3; + }, + elf.PT_DYNAMIC, elf.PT_TLS => return 6, + elf.PT_GNU_EH_FRAME => return 7, + elf.PT_GNU_STACK => return 8, + else => return 0xf, + } +} + +fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { + const Entry = struct { + phndx: u16, + + pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { + return elf_file.phdrRank(lhs.phndx) < elf_file.phdrRank(rhs.phndx); + } + }; + + const gpa = self.base.allocator; + var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len); + defer entries.deinit(); + for (0..self.phdrs.items.len) |phndx| { + entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) }); + } + + mem.sort(Entry, entries.items, self, Entry.lessThan); + + const backlinks = try gpa.alloc(u16, entries.items.len); + defer gpa.free(backlinks); + for (entries.items, 0..) |entry, i| { + backlinks[entry.phndx] = @as(u16, @intCast(i)); + } + + var slice = try self.phdrs.toOwnedSlice(gpa); + defer gpa.free(slice); + + try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len); + for (entries.items) |sorted| { + self.phdrs.appendAssumeCapacity(slice[sorted.phndx]); + } + + for (&[_]*?u16{ + &self.phdr_zig_load_re_index, + &self.phdr_zig_got_index, + &self.phdr_zig_load_ro_index, + &self.phdr_zig_load_zerofill_index, + &self.phdr_table_index, + &self.phdr_table_load_index, + &self.phdr_interp_index, + &self.phdr_dynamic_index, + &self.phdr_gnu_eh_frame_index, + &self.phdr_tls_index, + }) |maybe_index| { + if (maybe_index.*) |*index| { + index.* = backlinks[index.*]; + } + } +} + fn sectionRank(self: *Elf, shndx: u16) u8 { const shdr = self.shdrs.items[shndx]; const name = self.shstrtab.getAssumeExists(shdr.sh_name);