authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 06:43:33+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:26+02:00
log801f038c2ced9c0d7147f4304834ac6ae68e4cb0
treecfbb49b2f0f6d3181ffc3c695874d29f62061782
parenteeec50d2515c5a3b65cab697ba3e28d89cc3b14c

elf: do not pad placeholders coming from input object files

This is currently not entirely accurate since no padding will affect the last-most atom of ZigObject that should be padded.

3 files changed, 30 insertions(+), 16 deletions(-)

src/link/Elf.zig+19-14
...@@ -659,12 +659,17 @@ const AllocateChunkResult = struct {...@@ -659,12 +659,17 @@ const AllocateChunkResult = struct {
659 placement: Ref,659 placement: Ref,
660};660};
661661
662pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignment) !AllocateChunkResult {662pub fn allocateChunk(self: *Elf, args: struct {
663 size: u64,
664 shndx: u32,
665 alignment: Atom.Alignment,
666 requires_padding: bool = true,
667}) !AllocateChunkResult {
663 const slice = self.sections.slice();668 const slice = self.sections.slice();
664 const shdr = &slice.items(.shdr)[shndx];669 const shdr = &slice.items(.shdr)[args.shndx];
665 const free_list = &slice.items(.free_list)[shndx];670 const free_list = &slice.items(.free_list)[args.shndx];
666 const last_atom_ref = &slice.items(.last_atom)[shndx];671 const last_atom_ref = &slice.items(.last_atom)[args.shndx];
667 const new_atom_ideal_capacity = padToIdeal(size);672 const new_atom_ideal_capacity = if (args.requires_padding) padToIdeal(args.size) else args.size;
668673
669 // First we look for an appropriately sized free list node.674 // First we look for an appropriately sized free list node.
670 // The list is unordered. We'll just take the first thing that works.675 // The list is unordered. We'll just take the first thing that works.
...@@ -676,11 +681,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen...@@ -676,11 +681,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen
676 // We now have a pointer to a live atom that has too much capacity.681 // We now have a pointer to a live atom that has too much capacity.
677 // Is it enough that we could fit this new atom?682 // Is it enough that we could fit this new atom?
678 const cap = big_atom.capacity(self);683 const cap = big_atom.capacity(self);
679 const ideal_capacity = padToIdeal(cap);684 const ideal_capacity = if (args.requires_padding) padToIdeal(cap) else cap;
680 const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity;685 const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity;
681 const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap;686 const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap;
682 const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity;687 const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity;
683 const new_start_vaddr = alignment.backward(new_start_vaddr_unaligned);688 const new_start_vaddr = args.alignment.backward(new_start_vaddr_unaligned);
684 if (new_start_vaddr < ideal_capacity_end_vaddr) {689 if (new_start_vaddr < ideal_capacity_end_vaddr) {
685 // Additional bookkeeping here to notice if this free list node690 // Additional bookkeeping here to notice if this free list node
686 // should be deleted because the block that it points to has grown to take up691 // should be deleted because the block that it points to has grown to take up
...@@ -703,9 +708,9 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen...@@ -703,9 +708,9 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen
703 }708 }
704 break :blk .{ .value = new_start_vaddr, .placement = big_atom_ref };709 break :blk .{ .value = new_start_vaddr, .placement = big_atom_ref };
705 } else if (self.atom(last_atom_ref.*)) |last_atom| {710 } else if (self.atom(last_atom_ref.*)) |last_atom| {
706 const ideal_capacity = padToIdeal(last_atom.size);711 const ideal_capacity = if (args.requires_padding) padToIdeal(last_atom.size) else last_atom.size;
707 const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity;712 const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity;
708 const new_start_vaddr = alignment.forward(ideal_capacity_end_vaddr);713 const new_start_vaddr = args.alignment.forward(ideal_capacity_end_vaddr);
709 break :blk .{ .value = new_start_vaddr, .placement = last_atom.ref() };714 break :blk .{ .value = new_start_vaddr, .placement = last_atom.ref() };
710 } else {715 } else {
711 break :blk .{ .value = 0, .placement = .{} };716 break :blk .{ .value = 0, .placement = .{} };
...@@ -713,8 +718,8 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen...@@ -713,8 +718,8 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen
713 };718 };
714719
715 log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{720 log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{
716 size,721 args.size,
717 alignment.toByteUnits().?,722 args.alignment.toByteUnits().?,
718 shdr.sh_addr + res.value,723 shdr.sh_addr + res.value,
719 shdr.sh_offset + res.value,724 shdr.sh_offset + res.value,
720 });725 });
...@@ -724,11 +729,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen...@@ -724,11 +729,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen
724 else729 else
725 true;730 true;
726 if (expand_section) {731 if (expand_section) {
727 const needed_size = res.value + size;732 const needed_size = res.value + args.size;
728 if (shdr.sh_flags & elf.SHF_ALLOC != 0)733 if (shdr.sh_flags & elf.SHF_ALLOC != 0)
729 try self.growAllocSection(shndx, needed_size, alignment.toByteUnits().?)734 try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?)
730 else735 else
731 try self.growNonAllocSection(shndx, needed_size, alignment.toByteUnits().?, true);736 try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true);
732 }737 }
733738
734 return res;739 return res;
src/link/Elf/Object.zig+6-1
...@@ -969,7 +969,12 @@ pub fn allocateAtoms(self: *Object, elf_file: *Elf) !void {...@@ -969,7 +969,12 @@ pub fn allocateAtoms(self: *Object, elf_file: *Elf) !void {
969 }969 }
970970
971 for (self.section_chunks.items) |*chunk| {971 for (self.section_chunks.items) |*chunk| {
972 const alloc_res = try elf_file.allocateChunk(chunk.output_section_index, chunk.size, chunk.alignment);972 const alloc_res = try elf_file.allocateChunk(.{
973 .shndx = chunk.output_section_index,
974 .size = chunk.size,
975 .alignment = chunk.alignment,
976 .requires_padding = false,
977 });
973 chunk.value = @intCast(alloc_res.value);978 chunk.value = @intCast(alloc_res.value);
974979
975 const slice = elf_file.sections.slice();980 const slice = elf_file.sections.slice();
src/link/Elf/ZigObject.zig+5-1
...@@ -1996,7 +1996,11 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {...@@ -1996,7 +1996,11 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
1996}1996}
19971997
1998fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {1998fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
1999 const alloc_res = try elf_file.allocateChunk(atom_ptr.output_section_index, atom_ptr.size, atom_ptr.alignment);1999 const alloc_res = try elf_file.allocateChunk(.{
2000 .shndx = atom_ptr.output_section_index,
2001 .size = atom_ptr.size,
2002 .alignment = atom_ptr.alignment,
2003 });
2000 atom_ptr.value = @intCast(alloc_res.value);2004 atom_ptr.value = @intCast(alloc_res.value);
20012005
2002 const slice = elf_file.sections.slice();2006 const slice = elf_file.sections.slice();