From 5ff12003eeb88ae0d02318f6147cccd09a3149ea Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 11 Oct 2023 20:55:03 +0200 Subject: elf: dynamically allocate SHDR table --- src/link/Elf.zig | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 57baede94b..1b2b6a0311 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -531,6 +531,16 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { const end = start + padToIdeal(size); + if (self.shdr_table_offset) |off| { + const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); + const tight_size = self.shdrs.items.len * shdr_size; + const increased_size = padToIdeal(tight_size); + const test_end = off + increased_size; + if (end > off and start < test_end) { + return test_end; + } + } + for (self.shdrs.items) |shdr| { // SHT_NOBITS takes no physical space in the output file so set its size to 0. const sh_size = if (shdr.sh_type == elf.SHT_NOBITS) 0 else shdr.sh_size; @@ -553,6 +563,9 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { fn allocatedSize(self: *Elf, start: u64) u64 { if (start == 0) return 0; var min_pos: u64 = std.math.maxInt(u64); + if (self.shdr_table_offset) |off| { + if (off > start and off < min_pos) min_pos = off; + } for (self.shdrs.items) |section| { if (section.sh_offset <= start) continue; if (section.sh_offset < min_pos) min_pos = section.sh_offset; @@ -1673,8 +1686,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } } - try self.writeShdrTable(); try self.writePhdrTable(); + try self.writeShdrTable(); try self.writeAtoms(); try self.writeSyntheticSections(); @@ -2773,14 +2786,20 @@ fn writeShdrTable(self: *Elf) !void { .p32 => @alignOf(elf.Elf32_Shdr), .p64 => @alignOf(elf.Elf64_Shdr), }; + + const shoff = self.shdr_table_offset orelse 0; const needed_size = self.shdrs.items.len * shsize; - var shoff: u64 = 0; - for (self.shdrs.items) |shdr| { - const off = mem.alignForward(u64, shdr.sh_offset + shdr.sh_size, shalign); - shoff = @max(shoff, off); + + if (needed_size > self.allocatedSize(shoff)) { + self.shdr_table_offset = null; + self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); } - self.shdr_table_offset = shoff; - log.debug("writing section headers from 0x{x} to 0x{x}", .{ shoff, shoff + needed_size }); + + log.debug("writing section headers from 0x{x} to 0x{x}", .{ + self.shdr_table_offset.?, + self.shdr_table_offset.? + needed_size, + }); + switch (self.ptr_width) { .p32 => { const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len); -- cgit v1.2.3