From 887f9a29f35ca32521ac6786ba6aab6fd240421f Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 1 Oct 2024 07:31:13 +0200 Subject: [PATCH] elf: combine growAllocSection and growNonAllocSection into growSection --- src/link/Dwarf.zig | 15 ++++---- src/link/Elf.zig | 90 +++++++++++----------------------------------- 2 files changed, 28 insertions(+), 77 deletions(-) diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 6efa708d05..840cef69fe 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -390,14 +390,15 @@ pub const Section = struct { const zo = elf_file.zigObjectPtr().?; const atom = zo.symbol(sec.index).atom(elf_file).?; const shndx = atom.output_section_index; - if (sec == &dwarf.debug_frame.section) - try elf_file.growAllocSection(shndx, len, sec.alignment.toByteUnits().?) - else - try elf_file.growNonAllocSection(shndx, len, sec.alignment.toByteUnits().?, true); - const shdr = elf_file.sections.items(.shdr)[shndx]; - atom.size = shdr.sh_size; + const needed_size = len; + const min_alignment = sec.alignment.toByteUnits().?; + try elf_file.growSection(shndx, needed_size, min_alignment); + const shdr = &elf_file.sections.items(.shdr)[shndx]; + shdr.sh_size = needed_size; + elf_file.markDirty(shndx); + atom.size = needed_size; atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); - sec.len = shdr.sh_size; + sec.len = len; } else if (dwarf.bin_file.cast(.macho)) |macho_file| { const header = if (macho_file.d_sym) |*d_sym| header: { try d_sym.growSection(@intCast(sec.index), len, true, macho_file); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index a61cc5ef5f..fd7c54dd20 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 { return min_pos - start; } -fn allocatedVirtualSize(self: *Elf, start: u64) u64 { - if (start == 0) return 0; - var min_pos: u64 = std.math.maxInt(u64); - for (self.phdrs.items) |phdr| { - if (phdr.p_vaddr <= start) continue; - if (phdr.p_vaddr < min_pos) min_pos = phdr.p_vaddr; - } - return min_pos - start; -} - pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { var start: u64 = 0; while (try self.detectAllocCollision(start, object_size)) |item_end| { @@ -566,59 +556,21 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { return start; } -pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { - const slice = self.sections.slice(); - const shdr = &slice.items(.shdr)[shdr_index]; - assert(shdr.sh_flags & elf.SHF_ALLOC != 0); +pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { + const shdr = &self.sections.items(.shdr)[shdr_index]; + assert(shdr.sh_type != elf.SHT_NOBITS); - log.debug("allocated size {x} of {s}, needed size {x}", .{ - self.allocatedSize(shdr.sh_offset), + const allocated_size = self.allocatedSize(shdr.sh_offset); + log.debug("allocated size {x} of '{s}', needed size {x}", .{ + allocated_size, self.getShString(shdr.sh_name), needed_size, }); - if (shdr.sh_type != elf.SHT_NOBITS) { - const allocated_size = self.allocatedSize(shdr.sh_offset); - if (needed_size > allocated_size) { - const existing_size = shdr.sh_size; - shdr.sh_size = 0; - // Must move the entire section. - const new_offset = try self.findFreeSpace(needed_size, min_alignment); - - log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ - self.getShString(shdr.sh_name), - new_offset, - new_offset + existing_size, - }); - - const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, existing_size); - // TODO figure out what to about this error condition - how to communicate it up. - if (amt != existing_size) return error.InputOutput; - - shdr.sh_offset = new_offset; - } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { - try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); - } - } - shdr.sh_size = needed_size; - self.markDirty(shdr_index); -} - -pub fn growNonAllocSection( - self: *Elf, - shdr_index: u32, - needed_size: u64, - min_alignment: u64, - requires_file_copy: bool, -) !void { - const shdr = &self.sections.items(.shdr)[shdr_index]; - assert(shdr.sh_flags & elf.SHF_ALLOC == 0); - - const allocated_size = self.allocatedSize(shdr.sh_offset); if (needed_size > allocated_size) { const existing_size = shdr.sh_size; shdr.sh_size = 0; - // Move all the symbols to a new file location. + // Must move the entire section. const new_offset = try self.findFreeSpace(needed_size, min_alignment); log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ @@ -627,22 +579,19 @@ pub fn growNonAllocSection( new_offset + existing_size, }); - if (requires_file_copy) { - const amt = try self.base.file.?.copyRangeAll( - shdr.sh_offset, - self.base.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; - } + const amt = try self.base.file.?.copyRangeAll( + shdr.sh_offset, + self.base.file.?, + new_offset, + existing_size, + ); + // TODO figure out what to about this error condition - how to communicate it up. + if (amt != existing_size) return error.InputOutput; shdr.sh_offset = new_offset; } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); } - shdr.sh_size = needed_size; - self.markDirty(shdr_index); } pub fn markDirty(self: *Elf, shdr_index: u32) void { @@ -751,10 +700,11 @@ pub fn allocateChunk(self: *Elf, args: struct { true; if (expand_section) { const needed_size = res.value + args.size; - if (shdr.sh_flags & elf.SHF_ALLOC != 0) - try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?) - else - try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true); + if (shdr.sh_type != elf.SHT_NOBITS) { + try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?); + } + shdr.sh_size = needed_size; + self.markDirty(args.shndx); } return res;