Commit 887f9a29f3

Jakub Konka <kubkon@jakubkonka.com>
2024-10-01 07:31:13
elf: combine growAllocSection and growNonAllocSection into growSection
1 parent 0aa24ac
Changed files (2)
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);
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;