authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-11 20:55:03+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log5ff12003eeb88ae0d02318f6147cccd09a3149ea
tree7c61b457a270eeeed4c7e5535eec2b5dd70dca3b
parent1939c7d182e55d09b7968052b0cda652dab18b74

elf: dynamically allocate SHDR table


1 files changed, 26 insertions(+), 7 deletions(-)

src/link/Elf.zig+26-7
...@@ -531,6 +531,16 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {...@@ -531,6 +531,16 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
531531
532 const end = start + padToIdeal(size);532 const end = start + padToIdeal(size);
533533
534 if (self.shdr_table_offset) |off| {
535 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
536 const tight_size = self.shdrs.items.len * shdr_size;
537 const increased_size = padToIdeal(tight_size);
538 const test_end = off + increased_size;
539 if (end > off and start < test_end) {
540 return test_end;
541 }
542 }
543
534 for (self.shdrs.items) |shdr| {544 for (self.shdrs.items) |shdr| {
535 // SHT_NOBITS takes no physical space in the output file so set its size to 0.545 // SHT_NOBITS takes no physical space in the output file so set its size to 0.
536 const sh_size = if (shdr.sh_type == elf.SHT_NOBITS) 0 else shdr.sh_size;546 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 {...@@ -553,6 +563,9 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
553fn allocatedSize(self: *Elf, start: u64) u64 {563fn allocatedSize(self: *Elf, start: u64) u64 {
554 if (start == 0) return 0;564 if (start == 0) return 0;
555 var min_pos: u64 = std.math.maxInt(u64);565 var min_pos: u64 = std.math.maxInt(u64);
566 if (self.shdr_table_offset) |off| {
567 if (off > start and off < min_pos) min_pos = off;
568 }
556 for (self.shdrs.items) |section| {569 for (self.shdrs.items) |section| {
557 if (section.sh_offset <= start) continue;570 if (section.sh_offset <= start) continue;
558 if (section.sh_offset < min_pos) min_pos = section.sh_offset;571 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...@@ -1673,8 +1686,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1673 }1686 }
1674 }1687 }
16751688
1676 try self.writeShdrTable();
1677 try self.writePhdrTable();1689 try self.writePhdrTable();
1690 try self.writeShdrTable();
1678 try self.writeAtoms();1691 try self.writeAtoms();
1679 try self.writeSyntheticSections();1692 try self.writeSyntheticSections();
16801693
...@@ -2773,14 +2786,20 @@ fn writeShdrTable(self: *Elf) !void {...@@ -2773,14 +2786,20 @@ fn writeShdrTable(self: *Elf) !void {
2773 .p32 => @alignOf(elf.Elf32_Shdr),2786 .p32 => @alignOf(elf.Elf32_Shdr),
2774 .p64 => @alignOf(elf.Elf64_Shdr),2787 .p64 => @alignOf(elf.Elf64_Shdr),
2775 };2788 };
2789
2790 const shoff = self.shdr_table_offset orelse 0;
2776 const needed_size = self.shdrs.items.len * shsize;2791 const needed_size = self.shdrs.items.len * shsize;
2777 var shoff: u64 = 0;2792
2778 for (self.shdrs.items) |shdr| {2793 if (needed_size > self.allocatedSize(shoff)) {
2779 const off = mem.alignForward(u64, shdr.sh_offset + shdr.sh_size, shalign);2794 self.shdr_table_offset = null;
2780 shoff = @max(shoff, off);2795 self.shdr_table_offset = self.findFreeSpace(needed_size, shalign);
2781 }2796 }
2782 self.shdr_table_offset = shoff;2797
2783 log.debug("writing section headers from 0x{x} to 0x{x}", .{ shoff, shoff + needed_size });2798 log.debug("writing section headers from 0x{x} to 0x{x}", .{
2799 self.shdr_table_offset.?,
2800 self.shdr_table_offset.? + needed_size,
2801 });
2802
2784 switch (self.ptr_width) {2803 switch (self.ptr_width) {
2785 .p32 => {2804 .p32 => {
2786 const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);2805 const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);