diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-04 11:40:56 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-04 13:34:26 +0200 |
| commit | d302a1068effe4edcd36bd01f77ac2e1b1048e16 (patch) | |
| tree | be0f2fc35bb60239b4fbb4e8ebdbe416ddca1f6e /src | |
| parent | 64ad6eff16aac1f6154efa12406818efed57bf73 (diff) | |
| download | zig-d302a1068effe4edcd36bd01f77ac2e1b1048e16.tar.gz zig-d302a1068effe4edcd36bd01f77ac2e1b1048e16.zip | |
elf: rename SectionChunk into AtomList and store as part of Section
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 133 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 276 | ||||
| -rw-r--r-- | src/link/Elf/relocatable.zig | 20 |
3 files changed, 103 insertions, 326 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 12f564edcf..67969b7fb7 100644 --- a/src/link/Elf.zig +++ b/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"); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 0d063927ce..18c7a91c8f 100644 --- a/src/link/Elf/Object.zig +++ b/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; diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 5df6bb9946..5fc0d5790b 100644 --- a/src/link/Elf/relocatable.zig +++ b/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); } } |
