Commit d302a1068e

Jakub Konka <kubkon@jakubkonka.com>
2024-09-04 11:40:56
elf: rename SectionChunk into AtomList and store as part of Section
1 parent 64ad6ef
Changed files (3)
src/link/Elf/Object.zig
@@ -17,7 +17,6 @@ relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
 atoms: std.ArrayListUnmanaged(Atom) = .{},
 atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
 atoms_extra: std.ArrayListUnmanaged(u32) = .{},
-section_chunks: std.ArrayListUnmanaged(SectionChunk) = .{},
 
 comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},
 comdat_group_data: std.ArrayListUnmanaged(u32) = .{},
@@ -59,10 +58,6 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
     self.atoms.deinit(allocator);
     self.atoms_indexes.deinit(allocator);
     self.atoms_extra.deinit(allocator);
-    for (self.section_chunks.items) |*chunk| {
-        chunk.deinit(allocator);
-    }
-    self.section_chunks.deinit(allocator);
     self.comdat_groups.deinit(allocator);
     self.comdat_group_data.deinit(allocator);
     self.relocs.deinit(allocator);
@@ -952,166 +947,9 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
             .flags = shdr.sh_flags,
             .type = shdr.sh_type,
         });
-        const chunk = for (self.section_chunks.items) |*chunk| {
-            if (chunk.output_section_index == osec) break chunk;
-        } else blk: {
-            const chunk = try self.section_chunks.addOne(elf_file.base.comp.gpa);
-            chunk.* = .{ .output_section_index = osec };
-            break :blk chunk;
-        };
-        try chunk.atoms.append(elf_file.base.comp.gpa, atom_index);
-    }
-}
-
-pub fn allocateAtoms(self: *Object, elf_file: *Elf) !void {
-    for (self.section_chunks.items) |*chunk| {
-        chunk.updateSize(self);
-    }
-
-    for (self.section_chunks.items) |*chunk| {
-        const alloc_res = try elf_file.allocateChunk(.{
-            .shndx = chunk.output_section_index,
-            .size = chunk.size,
-            .alignment = chunk.alignment,
-            .requires_padding = false,
-        });
-        chunk.value = @intCast(alloc_res.value);
-
-        const slice = elf_file.sections.slice();
-        const shdr = &slice.items(.shdr)[chunk.output_section_index];
-        const last_atom_ref = &slice.items(.last_atom)[chunk.output_section_index];
-
-        const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|
-            placement_atom.nextAtom(elf_file) == null
-        else
-            true;
-        if (expand_section) last_atom_ref.* = chunk.lastAtom(self).ref();
-        shdr.sh_addralign = @max(shdr.sh_addralign, chunk.alignment.toByteUnits().?);
-
-        {
-            var idx: usize = 0;
-            while (idx < chunk.atoms.items.len) : (idx += 1) {
-                const curr_atom_ptr = self.atom(chunk.atoms.items[idx]).?;
-                if (idx > 0) {
-                    curr_atom_ptr.prev_atom_ref = .{ .index = chunk.atoms.items[idx - 1], .file = self.index };
-                }
-                if (idx + 1 < chunk.atoms.items.len) {
-                    curr_atom_ptr.next_atom_ref = .{ .index = chunk.atoms.items[idx + 1], .file = self.index };
-                }
-            }
-        }
-
-        if (elf_file.atom(alloc_res.placement)) |placement_atom| {
-            chunk.firstAtom(self).prev_atom_ref = placement_atom.ref();
-            chunk.lastAtom(self).next_atom_ref = placement_atom.next_atom_ref;
-            placement_atom.next_atom_ref = chunk.firstAtom(self).ref();
-        }
-
-        // TODO if we had a link from Atom to parent Chunk we would not need to update Atom's value or osec index
-        for (chunk.atoms.items) |atom_index| {
-            const atom_ptr = self.atom(atom_index).?;
-            atom_ptr.output_section_index = chunk.output_section_index;
-            atom_ptr.value += chunk.value;
-        }
-    }
-}
-
-pub fn writeAtoms(self: *Object, elf_file: *Elf) !void {
-    const gpa = elf_file.base.comp.gpa;
-
-    var undefs = std.AutoArrayHashMap(Elf.SymbolResolver.Index, std.ArrayList(Elf.Ref)).init(gpa);
-    defer {
-        for (undefs.values()) |*refs| {
-            refs.deinit();
-        }
-        undefs.deinit();
-    }
-
-    var buffer = std.ArrayList(u8).init(gpa);
-    defer buffer.deinit();
-
-    log.debug("writing atoms in {}", .{self.fmtPath()});
-
-    var has_reloc_errors = false;
-    for (self.section_chunks.items) |chunk| {
-        const osec = elf_file.sections.items(.shdr)[chunk.output_section_index];
-        if (osec.sh_type == elf.SHT_NOBITS) continue;
-
-        log.debug("  in section '{s}'", .{elf_file.getShString(osec.sh_name)});
-
-        try buffer.ensureUnusedCapacity(chunk.size);
-        buffer.appendNTimesAssumeCapacity(0, chunk.size);
-
-        for (chunk.atoms.items) |atom_index| {
-            const atom_ptr = self.atom(atom_index).?;
-            assert(atom_ptr.alive);
-
-            const offset = math.cast(usize, atom_ptr.value - chunk.value) orelse return error.Overflow;
-            const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
-
-            log.debug("    * atom({d}) at 0x{x}", .{ atom_index, chunk.offset(elf_file) + offset });
-
-            const code = try self.codeDecompressAlloc(elf_file, atom_index);
-            defer gpa.free(code);
-            const out_code = buffer.items[offset..][0..size];
-            @memcpy(out_code, code);
-
-            const res = if (osec.sh_flags & elf.SHF_ALLOC == 0)
-                atom_ptr.resolveRelocsNonAlloc(elf_file, out_code, &undefs)
-            else
-                atom_ptr.resolveRelocsAlloc(elf_file, out_code);
-            _ = res catch |err| switch (err) {
-                error.UnsupportedCpuArch => {
-                    try elf_file.reportUnsupportedCpuArch();
-                    return error.FlushFailure;
-                },
-                error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
-                else => |e| return e,
-            };
-        }
-
-        try elf_file.base.file.?.pwriteAll(buffer.items, chunk.offset(elf_file));
-        buffer.clearRetainingCapacity();
-    }
-
-    try elf_file.reportUndefinedSymbols(&undefs);
-    if (has_reloc_errors) return error.FlushFailure;
-}
-
-pub fn writeAtomsRelocatable(self: *Object, elf_file: *Elf) !void {
-    const gpa = elf_file.base.comp.gpa;
-
-    var buffer = std.ArrayList(u8).init(gpa);
-    defer buffer.deinit();
-
-    log.debug("writing atoms in {}", .{self.fmtPath()});
-
-    for (self.section_chunks.items) |chunk| {
-        const osec = elf_file.sections.items(.shdr)[chunk.output_section_index];
-        if (osec.sh_type == elf.SHT_NOBITS) continue;
-
-        log.debug("  in section '{s}'", .{elf_file.getShString(osec.sh_name)});
-
-        try buffer.ensureUnusedCapacity(chunk.size);
-        buffer.appendNTimesAssumeCapacity(0, chunk.size);
-
-        for (chunk.atoms.items) |atom_index| {
-            const atom_ptr = self.atom(atom_index).?;
-            assert(atom_ptr.alive);
-
-            const offset = math.cast(usize, atom_ptr.value - chunk.value) orelse return error.Overflow;
-            const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
-
-            log.debug("    * atom({d}) at 0x{x}", .{ atom_index, chunk.offset(elf_file) + offset });
-
-            const code = try self.codeDecompressAlloc(elf_file, atom_index);
-            defer gpa.free(code);
-            const out_code = buffer.items[offset..][0..size];
-            @memcpy(out_code, code);
-        }
-
-        try elf_file.base.file.?.pwriteAll(buffer.items, chunk.offset(elf_file));
-        buffer.clearRetainingCapacity();
+        const atom_list = &elf_file.sections.items(.atom_list_2)[osec];
+        atom_list.output_section_index = osec;
+        try atom_list.atoms.append(elf_file.base.comp.gpa, atom_ptr.ref());
     }
 }
 
@@ -1585,29 +1423,6 @@ fn formatAtoms(
     }
 }
 
-pub fn fmtSectionChunks(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatSectionChunks) {
-    return .{ .data = .{
-        .object = self,
-        .elf_file = elf_file,
-    } };
-}
-
-fn formatSectionChunks(
-    ctx: FormatContext,
-    comptime unused_fmt_string: []const u8,
-    options: std.fmt.FormatOptions,
-    writer: anytype,
-) !void {
-    _ = unused_fmt_string;
-    _ = options;
-    const object = ctx.object;
-    const elf_file = ctx.elf_file;
-    try writer.writeAll("  section chunks\n");
-    for (object.section_chunks.items) |chunk| {
-        try writer.print("    {}\n", .{chunk.fmt(elf_file)});
-    }
-}
-
 pub fn fmtCies(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatCies) {
     return .{ .data = .{
         .object = self,
@@ -1709,90 +1524,6 @@ const InArchive = struct {
     size: u32,
 };
 
-const SectionChunk = struct {
-    value: i64 = 0,
-    size: u64 = 0,
-    alignment: Atom.Alignment = .@"1",
-    output_section_index: u32 = 0,
-    atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
-
-    fn deinit(chunk: *SectionChunk, allocator: Allocator) void {
-        chunk.atoms.deinit(allocator);
-    }
-
-    fn address(chunk: SectionChunk, elf_file: *Elf) i64 {
-        const shdr = elf_file.sections.items(.shdr)[chunk.output_section_index];
-        return @as(i64, @intCast(shdr.sh_addr)) + chunk.value;
-    }
-
-    fn offset(chunk: SectionChunk, elf_file: *Elf) u64 {
-        const shdr = elf_file.sections.items(.shdr)[chunk.output_section_index];
-        return shdr.sh_offset + @as(u64, @intCast(chunk.value));
-    }
-
-    fn updateSize(chunk: *SectionChunk, object: *Object) void {
-        for (chunk.atoms.items) |atom_index| {
-            const atom_ptr = object.atom(atom_index).?;
-            assert(atom_ptr.alive);
-            const off = atom_ptr.alignment.forward(chunk.size);
-            const padding = off - chunk.size;
-            atom_ptr.value = @intCast(off);
-            chunk.size += padding + atom_ptr.size;
-            chunk.alignment = chunk.alignment.max(atom_ptr.alignment);
-        }
-    }
-
-    fn firstAtom(chunk: SectionChunk, object: *Object) *Atom {
-        assert(chunk.atoms.items.len > 0);
-        return object.atom(chunk.atoms.items[0]).?;
-    }
-
-    fn lastAtom(chunk: SectionChunk, object: *Object) *Atom {
-        assert(chunk.atoms.items.len > 0);
-        return object.atom(chunk.atoms.items[chunk.atoms.items.len - 1]).?;
-    }
-
-    pub fn format(
-        chunk: SectionChunk,
-        comptime unused_fmt_string: []const u8,
-        options: std.fmt.FormatOptions,
-        writer: anytype,
-    ) !void {
-        _ = chunk;
-        _ = unused_fmt_string;
-        _ = options;
-        _ = writer;
-        @compileError("do not format SectionChunk directly");
-    }
-
-    const FormatCtx = struct { SectionChunk, *Elf };
-
-    pub fn fmt(chunk: SectionChunk, elf_file: *Elf) std.fmt.Formatter(format2) {
-        return .{ .data = .{ chunk, elf_file } };
-    }
-
-    fn format2(
-        ctx: FormatCtx,
-        comptime unused_fmt_string: []const u8,
-        options: std.fmt.FormatOptions,
-        writer: anytype,
-    ) !void {
-        _ = unused_fmt_string;
-        _ = options;
-        const chunk, const elf_file = ctx;
-        try writer.print("chunk : @{x} : shdr({d}) : align({x}) : size({x})", .{
-            chunk.address(elf_file),                chunk.output_section_index,
-            chunk.alignment.toByteUnits() orelse 0, chunk.size,
-        });
-        try writer.writeAll(" : atoms{ ");
-        for (chunk.atoms.items, 0..) |atom_index, i| {
-            try writer.print("{d}", .{atom_index});
-            if (i < chunk.atoms.items.len - 1) try writer.writeAll(", ");
-        }
-        try writer.writeAll(" }");
-    }
-};
-
 const Object = @This();
 
 const std = @import("std");
@@ -1807,6 +1538,7 @@ const mem = std.mem;
 const Allocator = mem.Allocator;
 const Archive = @import("Archive.zig");
 const Atom = @import("Atom.zig");
+const AtomList = @import("AtomList.zig");
 const Cie = eh_frame.Cie;
 const Elf = @import("../Elf.zig");
 const Fde = eh_frame.Fde;
src/link/Elf/relocatable.zig
@@ -353,11 +353,13 @@ fn initComdatGroups(elf_file: *Elf) !void {
 }
 
 fn updateSectionSizes(elf_file: *Elf) !void {
-    for (elf_file.objects.items) |index| {
-        try elf_file.file(index).?.object.allocateAtoms(elf_file);
+    const slice = elf_file.sections.slice();
+    for (slice.items(.atom_list_2)) |*atom_list| {
+        if (atom_list.atoms.items.len == 0) continue;
+        atom_list.updateSize(elf_file);
+        try atom_list.allocate(elf_file);
     }
 
-    const slice = elf_file.sections.slice();
     for (slice.items(.shdr), 0..) |*shdr, shndx| {
         const atom_list = slice.items(.atom_list)[shndx];
         if (shdr.sh_type != elf.SHT_RELA) continue;
@@ -444,8 +446,16 @@ fn allocateAllocSections(elf_file: *Elf) !void {
 }
 
 fn writeAtoms(elf_file: *Elf) !void {
-    for (elf_file.objects.items) |index| {
-        try elf_file.file(index).?.object.writeAtomsRelocatable(elf_file);
+    const gpa = elf_file.base.comp.gpa;
+
+    var buffer = std.ArrayList(u8).init(gpa);
+    defer buffer.deinit();
+
+    const slice = elf_file.sections.slice();
+    for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
+        if (shdr.sh_type == elf.SHT_NOBITS) continue;
+        if (atom_list.atoms.items.len == 0) continue;
+        try atom_list.writeRelocatable(&buffer, elf_file);
     }
 }
 
src/link/Elf.zig
@@ -393,7 +393,8 @@ pub fn deinit(self: *Elf) void {
     self.objects.deinit(gpa);
     self.shared_objects.deinit(gpa);
 
-    for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| {
+    for (self.sections.items(.atom_list_2), self.sections.items(.atom_list), self.sections.items(.free_list)) |*atom_list, *atoms, *free_list| {
+        atom_list.deinit(gpa);
         atoms.deinit(gpa);
         free_list.deinit(gpa);
     }
@@ -3204,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void {
         }
     };
 
-    for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| {
+    for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
         if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
+        if (atom_list.atoms.items.len == 0) continue;
 
         var is_init_fini = false;
         var is_ctor_dtor = false;
@@ -3219,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void {
                 is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null;
             },
         }
-
         if (!is_init_fini and !is_ctor_dtor) continue;
-        if (atom_list.items.len == 0) continue;
 
         var entries = std.ArrayList(Entry).init(gpa);
-        try entries.ensureTotalCapacityPrecise(atom_list.items.len);
+        try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len);
         defer entries.deinit();
 
-        for (atom_list.items) |ref| {
+        for (atom_list.atoms.items) |ref| {
             const atom_ptr = self.atom(ref).?;
             const object = atom_ptr.file(self).?.object;
             const priority = blk: {
@@ -3246,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void {
 
         mem.sort(Entry, entries.items, self, Entry.lessThan);
 
-        atom_list.clearRetainingCapacity();
+        atom_list.atoms.clearRetainingCapacity();
         for (entries.items) |entry| {
-            atom_list.appendAssumeCapacity(entry.atom_ref);
+            atom_list.atoms.appendAssumeCapacity(entry.atom_ref);
         }
     }
 }
@@ -3491,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
         msec.output_section_index = backlinks[msec.output_section_index];
     }
 
-    for (self.sections.items(.shdr)) |*shdr| {
-        if (shdr.sh_type != elf.SHT_RELA) continue;
-        // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
-        // to point at symtab
-        // shdr.sh_link = backlinks[shdr.sh_link];
-        shdr.sh_link = self.symtab_section_index.?;
-        shdr.sh_info = backlinks[shdr.sh_info];
+    const slice = self.sections.slice();
+    for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
+        atom_list.output_section_index = backlinks[atom_list.output_section_index];
+        for (atom_list.atoms.items) |ref| {
+            self.atom(ref).?.output_section_index = atom_list.output_section_index;
+        }
+        if (shdr.sh_type == elf.SHT_RELA) {
+            // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
+            // to point at symtab
+            // shdr.sh_link = backlinks[shdr.sh_link];
+            shdr.sh_link = self.symtab_section_index.?;
+            shdr.sh_info = backlinks[shdr.sh_info];
+        }
     }
 
     if (self.zigObjectPtr()) |zo| {
@@ -3507,79 +3513,71 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
         }
     }
 
-    for (self.objects.items) |index| {
-        const object = self.file(index).?.object;
-        for (object.section_chunks.items) |*chunk| {
-            chunk.output_section_index = backlinks[chunk.output_section_index];
-            for (chunk.atoms.items) |atom_index| {
-                object.atom(atom_index).?.output_section_index = chunk.output_section_index;
-            }
-        }
-    }
-
     for (self.comdat_group_sections.items) |*cg| {
         cg.shndx = backlinks[cg.shndx];
     }
 
     if (self.symtab_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.strtab_section_index.?;
     }
 
     if (self.dynamic_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynstrtab_section_index.?;
     }
 
     if (self.dynsymtab_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynstrtab_section_index.?;
     }
 
     if (self.hash_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynsymtab_section_index.?;
     }
 
     if (self.gnu_hash_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynsymtab_section_index.?;
     }
 
     if (self.versym_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynsymtab_section_index.?;
     }
 
     if (self.verneed_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynstrtab_section_index.?;
     }
 
     if (self.rela_dyn_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynsymtab_section_index orelse 0;
     }
 
     if (self.rela_plt_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.dynsymtab_section_index.?;
         shdr.sh_info = self.plt_section_index.?;
     }
 
     if (self.eh_frame_rela_section_index) |index| {
-        const shdr = &self.sections.items(.shdr)[index];
+        const shdr = &slice.items(.shdr)[index];
         shdr.sh_link = self.symtab_section_index.?;
         shdr.sh_info = self.eh_frame_section_index.?;
     }
 }
 
 fn updateSectionSizes(self: *Elf) !void {
-    for (self.objects.items) |index| {
-        try self.file(index).?.object.allocateAtoms(self);
+    const slice = self.sections.slice();
+    for (slice.items(.atom_list_2)) |*atom_list| {
+        if (atom_list.atoms.items.len == 0) continue;
+        atom_list.updateSize(self);
+        try atom_list.allocate(self);
     }
 
-    const slice = self.sections.slice();
     if (self.requiresThunks()) {
         for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| {
             if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
@@ -4033,15 +4031,38 @@ fn allocateSpecialPhdrs(self: *Elf) void {
 }
 
 fn writeAtoms(self: *Elf) !void {
-    for (self.objects.items) |index| {
-        try self.file(index).?.object.writeAtoms(self);
+    const gpa = self.base.comp.gpa;
+
+    var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
+    defer {
+        for (undefs.values()) |*refs| {
+            refs.deinit();
+        }
+        undefs.deinit();
     }
 
-    if (self.requiresThunks()) {
-        const gpa = self.base.comp.gpa;
-        var buffer = std.ArrayList(u8).init(gpa);
-        defer buffer.deinit();
+    var buffer = std.ArrayList(u8).init(gpa);
+    defer buffer.deinit();
+
+    const slice = self.sections.slice();
+    var has_reloc_errors = false;
+    for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
+        if (shdr.sh_type == elf.SHT_NOBITS) continue;
+        if (atom_list.atoms.items.len == 0) continue;
+        atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
+            error.UnsupportedCpuArch => {
+                try self.reportUnsupportedCpuArch();
+                return error.FlushFailure;
+            },
+            error.RelocFailure, error.RelaxFailure => has_reloc_errors = true,
+            else => |e| return e,
+        };
+    }
+
+    try self.reportUndefinedSymbols(&undefs);
+    if (has_reloc_errors) return error.FlushFailure;
 
+    if (self.requiresThunks()) {
         for (self.thunks.items) |th| {
             const thunk_size = th.size(self);
             try buffer.ensureUnusedCapacity(thunk_size);
@@ -4993,7 +5014,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
     return off;
 }
 
-pub fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
+fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
     const gpa = self.base.comp.gpa;
     const max_notes = 4;
 
@@ -5061,7 +5082,7 @@ fn reportMissingLibraryError(
     }
 }
 
-pub fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void {
+fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void {
     var err = try self.base.addErrorWithNotes(0);
     try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{
         @tagName(self.getTarget().cpu.arch),
@@ -5248,9 +5269,8 @@ fn fmtDumpState(
         try writer.print("object({d}) : {}", .{ index, object.fmtPath() });
         if (!object.alive) try writer.writeAll(" : [*]");
         try writer.writeByte('\n');
-        try writer.print("{}{}{}{}{}{}\n", .{
+        try writer.print("{}{}{}{}{}\n", .{
             object.fmtAtoms(self),
-            object.fmtSectionChunks(self),
             object.fmtCies(self),
             object.fmtFdes(self),
             object.fmtSymtab(self),
@@ -5274,6 +5294,14 @@ fn fmtDumpState(
         try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
     }
 
+    const slice = self.sections.slice();
+    {
+        try writer.writeAll("atom lists\n");
+        for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| {
+            try writer.print("shdr({d}) : {s} : {}", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) });
+        }
+    }
+
     if (self.requiresThunks()) {
         try writer.writeAll("thunks\n");
         for (self.thunks.items, 0..) |th, index| {
@@ -5295,7 +5323,7 @@ fn fmtDumpState(
     }
 
     try writer.writeAll("\nOutput shdrs\n");
-    for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| {
+    for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| {
         try writer.print("  shdr({d}) : phdr({?d}) : {}\n", .{
             shndx,
             phndx,
@@ -5549,8 +5577,14 @@ const Section = struct {
     phndx: ?u32 = null,
 
     /// List of atoms contributing to this section.
+    /// TODO currently this is only used for relocations tracking in relocatable mode
+    /// but will be merged with atom_list_2.
     atom_list: std.ArrayListUnmanaged(Ref) = .{},
 
+    /// List of atoms contributing to this section.
+    /// This can be used by sections that require special handling such as init/fini array, etc.
+    atom_list_2: AtomList = .{},
+
     /// Index of the last allocated atom in this section.
     last_atom: Ref = .{ .index = 0, .file = 0 },
 
@@ -5690,6 +5724,7 @@ const Air = @import("../Air.zig");
 const Allocator = std.mem.Allocator;
 const Archive = @import("Elf/Archive.zig");
 pub const Atom = @import("Elf/Atom.zig");
+const AtomList = @import("Elf/AtomList.zig");
 const Cache = std.Build.Cache;
 const Path = Cache.Path;
 const Compilation = @import("../Compilation.zig");