aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-10-11 20:55:03 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-10-16 19:33:05 +0200
commit5ff12003eeb88ae0d02318f6147cccd09a3149ea (patch)
tree7c61b457a270eeeed4c7e5535eec2b5dd70dca3b /src/link
parent1939c7d182e55d09b7968052b0cda652dab18b74 (diff)
downloadzig-5ff12003eeb88ae0d02318f6147cccd09a3149ea.tar.gz
zig-5ff12003eeb88ae0d02318f6147cccd09a3149ea.zip
elf: dynamically allocate SHDR table
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Elf.zig33
1 files changed, 26 insertions, 7 deletions
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);