authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-15 16:05:43+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:06+02:00
log46cf4c5d9343af5da484b808a5c3153736ec62e9
tree1d0a48666e4e10b66af197d2459ece265a470b92
parent5423778f6f9d1ec424bf74d40c16c433f20681b2

elf: sort phdr table


1 files changed, 72 insertions(+), 0 deletions(-)

src/link/Elf.zig+72
......@@ -1573,6 +1573,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15731573
15741574 self.allocatePhdrTable();
15751575 try self.allocateAllocSections();
1576 try self.sortPhdrs();
15761577 try self.allocateNonAllocSections();
15771578 self.allocateSpecialPhdrs();
15781579 self.allocateAtoms();
......@@ -4076,6 +4077,77 @@ fn setHashSections(self: *Elf) !void {
40764077 }
40774078}
40784079
4080fn phdrRank(self: *Elf, phndx: u16) u8 {
4081 const phdr = self.phdrs.items[phndx];
4082 const flags = phdr.p_flags;
4083 switch (phdr.p_type) {
4084 elf.PT_NULL => return 0,
4085 elf.PT_PHDR => return 1,
4086 elf.PT_INTERP => return 2,
4087 elf.PT_LOAD => if (flags & elf.PF_X != 0) {
4088 return 4;
4089 } else if (flags & elf.PF_W != 0) {
4090 return 5;
4091 } else {
4092 return 3;
4093 },
4094 elf.PT_DYNAMIC, elf.PT_TLS => return 6,
4095 elf.PT_GNU_EH_FRAME => return 7,
4096 elf.PT_GNU_STACK => return 8,
4097 else => return 0xf,
4098 }
4099}
4100
4101fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
4102 const Entry = struct {
4103 phndx: u16,
4104
4105 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {
4106 return elf_file.phdrRank(lhs.phndx) < elf_file.phdrRank(rhs.phndx);
4107 }
4108 };
4109
4110 const gpa = self.base.allocator;
4111 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);
4112 defer entries.deinit();
4113 for (0..self.phdrs.items.len) |phndx| {
4114 entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) });
4115 }
4116
4117 mem.sort(Entry, entries.items, self, Entry.lessThan);
4118
4119 const backlinks = try gpa.alloc(u16, entries.items.len);
4120 defer gpa.free(backlinks);
4121 for (entries.items, 0..) |entry, i| {
4122 backlinks[entry.phndx] = @as(u16, @intCast(i));
4123 }
4124
4125 var slice = try self.phdrs.toOwnedSlice(gpa);
4126 defer gpa.free(slice);
4127
4128 try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len);
4129 for (entries.items) |sorted| {
4130 self.phdrs.appendAssumeCapacity(slice[sorted.phndx]);
4131 }
4132
4133 for (&[_]*?u16{
4134 &self.phdr_zig_load_re_index,
4135 &self.phdr_zig_got_index,
4136 &self.phdr_zig_load_ro_index,
4137 &self.phdr_zig_load_zerofill_index,
4138 &self.phdr_table_index,
4139 &self.phdr_table_load_index,
4140 &self.phdr_interp_index,
4141 &self.phdr_dynamic_index,
4142 &self.phdr_gnu_eh_frame_index,
4143 &self.phdr_tls_index,
4144 }) |maybe_index| {
4145 if (maybe_index.*) |*index| {
4146 index.* = backlinks[index.*];
4147 }
4148 }
4149}
4150
40794151fn sectionRank(self: *Elf, shndx: u16) u8 {
40804152 const shdr = self.shdrs.items[shndx];
40814153 const name = self.shstrtab.getAssumeExists(shdr.sh_name);