diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-28 10:24:26 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-30 10:00:50 +0200 |
| commit | 0701646beb8421464346ce6e8993394d8d2c7d5c (patch) | |
| tree | f65daea499e13e7c0e97a019a404f9490a9f3115 /src | |
| parent | 24126f5382c09f54d8344208e6e38df632d35a44 (diff) | |
| download | zig-0701646beb8421464346ce6e8993394d8d2c7d5c.tar.gz zig-0701646beb8421464346ce6e8993394d8d2c7d5c.zip | |
elf: move merge subsections ownership into merge sections
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 41 | ||||
| -rw-r--r-- | src/link/Elf/LinkerDefined.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 31 | ||||
| -rw-r--r-- | src/link/Elf/SharedObject.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/Symbol.zig | 18 | ||||
| -rw-r--r-- | src/link/Elf/ZigObject.zig | 8 | ||||
| -rw-r--r-- | src/link/Elf/merge_section.zig | 50 |
7 files changed, 80 insertions, 72 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1ca7ac9eca..4da9ffeb33 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -208,9 +208,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{}, /// List of output merge sections with deduped contents. merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, -/// List of output merge subsections. -/// Each subsection is akin to Atom but belongs to a MergeSection. -merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, /// Table of last atom index in a section and matching atom free list if any. last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, @@ -497,7 +494,6 @@ pub fn deinit(self: *Elf) void { sect.deinit(gpa); } self.merge_sections.deinit(gpa); - self.merge_subsections.deinit(gpa); for (self.last_atom_and_free_list_table.values()) |*value| { value.free_list.deinit(gpa); } @@ -3288,12 +3284,13 @@ fn checkDuplicates(self: *Elf) !void { } pub fn addCommentString(self: *Elf) !void { + const gpa = self.base.comp.gpa; const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); const msec = self.mergeSection(msec_index); - const res = try msec.insertZ(self.base.comp.gpa, "zig " ++ builtin.zig_version_string); + const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string); if (res.found_existing) return; - const msub_index = try self.addMergeSubsection(); - const msub = self.mergeSubsection(msub_index); + const msub_index = try msec.addMergeSubsection(gpa); + const msub = msec.mergeSubsection(msub_index); msub.merge_section_index = msec_index; msub.string_index = res.key.pos; msub.alignment = .@"1"; @@ -3340,8 +3337,8 @@ pub fn finalizeMergeSections(self: *Elf) !void { pub fn updateMergeSectionSizes(self: *Elf) !void { for (self.merge_sections.items) |*msec| { const shdr = &self.shdrs.items[msec.output_section_index]; - for (msec.subsections.items) |msub_index| { - const msub = self.mergeSubsection(msub_index); + for (msec.finalized_subsections.items) |msub_index| { + const msub = msec.mergeSubsection(msub_index); assert(msub.alive); const offset = msub.alignment.forward(shdr.sh_size); const padding = offset - shdr.sh_size; @@ -3357,14 +3354,14 @@ pub fn writeMergeSections(self: *Elf) !void { var buffer = std.ArrayList(u8).init(gpa); defer buffer.deinit(); - for (self.merge_sections.items) |msec| { + for (self.merge_sections.items) |*msec| { const shdr = self.shdrs.items[msec.output_section_index]; const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; try buffer.ensureTotalCapacity(size); buffer.appendNTimesAssumeCapacity(0, size); - for (msec.subsections.items) |msub_index| { - const msub = self.mergeSubsection(msub_index); + for (msec.finalized_subsections.items) |msub_index| { + const msub = msec.mergeSubsection(msub_index); assert(msub.alive); const string = msub.getString(self); const off = math.cast(usize, msub.value) orelse return error.Overflow; @@ -3384,7 +3381,7 @@ fn initOutputSections(self: *Elf) !void { pub fn initMergeSections(self: *Elf) !void { for (self.merge_sections.items) |*msec| { - if (msec.subsections.items.len == 0) continue; + if (msec.finalized_subsections.items.len == 0) continue; const name = msec.name(self); const shndx = self.sectionByName(name) orelse try self.addSection(.{ .name = name, @@ -3393,9 +3390,9 @@ pub fn initMergeSections(self: *Elf) !void { }); msec.output_section_index = shndx; - var entsize = self.mergeSubsection(msec.subsections.items[0]).entsize; - for (msec.subsections.items) |index| { - const msub = self.mergeSubsection(index); + var entsize = msec.mergeSubsection(msec.finalized_subsections.items[0]).entsize; + for (msec.finalized_subsections.items) |msub_index| { + const msub = msec.mergeSubsection(msub_index); entsize = @min(entsize, msub.entsize); } const shdr = &self.shdrs.items[shndx]; @@ -5706,18 +5703,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject { return self.file(index).?.zig_object; } -pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index { - const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len); - const msec = try self.merge_subsections.addOne(self.base.comp.gpa); - msec.* = .{}; - return index; -} - -pub fn mergeSubsection(self: *Elf, index: MergeSubsection.Index) *MergeSubsection { - assert(index < self.merge_subsections.items.len); - return &self.merge_subsections.items[index]; -} - pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index { const gpa = self.base.comp.gpa; const out_name = name: { diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 0e4a7f8f50..6009f446a9 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -47,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { const global = elf_file.symbol(index); if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { global.value = 0; - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.file_index = self.index; global.esym_index = sym_idx; global.version_index = elf_file.default_sym_version; diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index fb8da7dfcc..40c1896282 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -388,7 +388,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void { sym_ptr.esym_index = @as(u32, @intCast(i)); sym_ptr.file_index = self.index; if (sym.st_shndx != elf.SHN_ABS) { - sym_ptr.atom_ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index }; + sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index }; } } @@ -575,7 +575,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) { switch (esym.st_shndx) { elf.SHN_ABS, elf.SHN_COMMON => {}, - else => global.atom_ref = .{ + else => global.ref = .{ .index = self.atoms_indexes.items[esym.st_shndx], .file = self.index, }, @@ -609,7 +609,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { }; global.value = 0; - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.esym_index = esym_index; global.file_index = self.index; global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; @@ -630,7 +630,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { } global.value = 0; - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.esym_index = esym_index; global.file_index = self.index; } @@ -785,8 +785,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { const string = imsec.bytes.items[str.pos..][0..str.len]; const res = try msec.insert(gpa, string); if (!res.found_existing) { - const msub_index = try elf_file.addMergeSubsection(); - const msub = elf_file.mergeSubsection(msub_index); + const msub_index = try msec.addMergeSubsection(gpa); + const msub = msec.mergeSubsection(msub_index); msub.merge_section_index = imsec.merge_section_index; msub.string_index = res.key.pos; msub.alignment = atom_ptr.alignment; @@ -810,7 +810,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; const imsec = self.inputMergeSection(imsec_index) orelse continue; if (imsec.offsets.items.len == 0) continue; - const msub_index, const offset = imsec.findSubsection(@intCast(esym.st_value)) orelse { + const res = imsec.findSubsection(@intCast(esym.st_value)) orelse { var err = try elf_file.base.addErrorWithNotes(2); try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); try err.addNote("for symbol {s}", .{sym.name(elf_file)}); @@ -818,9 +818,9 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { return error.MalformedObject; }; - try sym.addExtra(.{ .subsection = msub_index }, elf_file); + sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; sym.flags.merge_subsection = true; - sym.value = offset; + sym.value = res.offset; } for (self.atoms_indexes.items) |atom_index| { @@ -835,28 +835,27 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; const imsec = self.inputMergeSection(imsec_index) orelse continue; if (imsec.offsets.items.len == 0) continue; - const msub_index, const offset = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { + const msec = elf_file.mergeSection(imsec.merge_section_index); + const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { var err = try elf_file.base.addErrorWithNotes(1); try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); return error.MalformedObject; }; - const msub = elf_file.mergeSubsection(msub_index); - const msec = msub.mergeSection(elf_file); const out_sym_idx: u64 = @intCast(self.symbols.items.len); try self.symbols.ensureUnusedCapacity(gpa, 1); - const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), msub_index }); + const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index }); defer gpa.free(name); const sym_index = try elf_file.addSymbol(); const sym = elf_file.symbol(sym_index); sym.* = .{ - .value = @bitCast(@as(i64, @intCast(offset)) - rel.r_addend), + .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend), .name_offset = try self.addString(gpa, name), .esym_index = rel.r_sym(), .file_index = self.index, }; - try sym.addExtra(.{ .subsection = msub_index }, elf_file); + sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; sym.flags.merge_subsection = true; self.symbols.addOneAssumeCapacity().* = sym_index; rel.r_info = (out_sym_idx << 32) | rel.r_type(); @@ -920,7 +919,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { try self.atoms_indexes.append(gpa, atom_index); global.value = 0; - global.atom_ref = .{ .index = atom_index, .file = self.index }; + global.ref = .{ .index = atom_index, .file = self.index }; global.flags.weak = false; } } diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index ef65f3abaa..461a56ae39 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void { const global = elf_file.symbol(index); if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { global.value = @intCast(this_sym.st_value); - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.esym_index = esym_index; global.version_index = self.versyms.items[esym_index]; global.file_index = self.index; diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 3fcecd5c09..68d23cb74d 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -9,9 +9,9 @@ name_offset: u32 = 0, /// Index of file where this symbol is defined. file_index: File.Index = 0, -/// Reference to Atom containing this symbol if any. -/// Use `atom` to get the pointer to the atom. -atom_ref: Elf.Ref = .{ .index = 0, .file = 0 }, +/// Reference to Atom or merge subsection containing this symbol if any. +/// Use `atom` or `mergeSubsection` to get the pointer to the atom. +ref: Elf.Ref = .{ .index = 0, .file = 0 }, /// Assigned output section index for this symbol. output_section_index: u32 = 0, @@ -71,14 +71,15 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 { } pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { - const file_ptr = elf_file.file(symbol.atom_ref.file) orelse return null; - return file_ptr.atom(symbol.atom_ref.index); + if (symbol.flags.merge_subsection) return null; + const file_ptr = elf_file.file(symbol.ref.file) orelse return null; + return file_ptr.atom(symbol.ref.index); } pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection { if (!symbol.flags.merge_subsection) return null; - const extras = symbol.extra(elf_file).?; - return elf_file.mergeSubsection(extras.subsection); + const msec = elf_file.mergeSection(symbol.ref.file); + return msec.mergeSubsection(symbol.ref.index); } pub fn file(symbol: Symbol, elf_file: *Elf) ?File { @@ -262,7 +263,6 @@ const AddExtraOpts = struct { gottp: ?u32 = null, tlsdesc: ?u32 = null, zig_got: ?u32 = null, - subsection: ?u32 = null, }; pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { @@ -488,7 +488,7 @@ pub const Extra = struct { gottp: u32 = 0, tlsdesc: u32 = 0, zig_got: u32 = 0, - subsection: u32 = 0, + merge_section: u32 = 0, }; pub const Index = u32; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 9c4baa4aff..1771e3cae1 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -291,7 +291,7 @@ pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { const symbol_ptr = elf_file.symbol(symbol_index); symbol_ptr.file_index = self.index; - symbol_ptr.atom_ref = .{ .index = atom_index, .file = self.index }; + symbol_ptr.ref = .{ .index = atom_index, .file = self.index }; self.local_esyms.items(.shndx)[esym_index] = atom_index; self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM; @@ -342,7 +342,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { else => unreachable, }; global.value = @intCast(esym.st_value); - global.atom_ref = .{ .index = atom_index, .file = self.index }; + global.ref = .{ .index = atom_index, .file = self.index }; global.esym_index = esym_index; global.file_index = self.index; global.version_index = elf_file.default_sym_version; @@ -371,7 +371,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { }; global.value = 0; - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.esym_index = esym_index; global.file_index = self.index; global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version; @@ -392,7 +392,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { } global.value = 0; - global.atom_ref = .{ .index = 0, .file = 0 }; + global.ref = .{ .index = 0, .file = 0 }; global.esym_index = esym_index; global.file_index = self.index; } diff --git a/src/link/Elf/merge_section.zig b/src/link/Elf/merge_section.zig index ab716794fc..3dabe8eda3 100644 --- a/src/link/Elf/merge_section.zig +++ b/src/link/Elf/merge_section.zig @@ -10,12 +10,14 @@ pub const MergeSection = struct { IndexContext, std.hash_map.default_max_load_percentage, ) = .{}, - subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{}, + subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, + finalized_subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{}, pub fn deinit(msec: *MergeSection, allocator: Allocator) void { msec.bytes.deinit(allocator); msec.table.deinit(allocator); msec.subsections.deinit(allocator); + msec.finalized_subsections.deinit(allocator); } pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 { @@ -60,23 +62,25 @@ pub const MergeSection = struct { /// Sorts all owned subsections. pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void { const gpa = elf_file.base.comp.gpa; - try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count()); + try msec.finalized_subsections.ensureTotalCapacityPrecise(gpa, msec.subsections.items.len); var it = msec.table.iterator(); while (it.next()) |entry| { - const msub = elf_file.mergeSubsection(entry.value_ptr.*); + const msub = msec.mergeSubsection(entry.value_ptr.*); if (!msub.alive) continue; - msec.subsections.appendAssumeCapacity(entry.value_ptr.*); + msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*); } msec.table.clearAndFree(gpa); const sortFn = struct { - pub fn sortFn(ctx: *Elf, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool { + pub fn sortFn(ctx: *MergeSection, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool { const lhs_msub = ctx.mergeSubsection(lhs); const rhs_msub = ctx.mergeSubsection(rhs); if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) { if (lhs_msub.size == rhs_msub.size) { - return mem.order(u8, lhs_msub.getString(ctx), rhs_msub.getString(ctx)) == .lt; + const lhs_string = ctx.bytes.items[lhs_msub.string_index..][0..lhs_msub.size]; + const rhs_string = ctx.bytes.items[rhs_msub.string_index..][0..rhs_msub.size]; + return mem.order(u8, lhs_string, rhs_string) == .lt; } return lhs_msub.size < rhs_msub.size; } @@ -84,7 +88,19 @@ pub const MergeSection = struct { } }.sortFn; - std.mem.sort(MergeSubsection.Index, msec.subsections.items, elf_file, sortFn); + std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn); + } + + pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { + const index: MergeSubsection.Index = @intCast(msec.subsections.items.len); + const msub = try msec.subsections.addOne(allocator); + msub.* = .{}; + return index; + } + + pub fn mergeSubsection(msec: *MergeSection, index: MergeSubsection.Index) *MergeSubsection { + assert(index < msec.subsections.items.len); + return &msec.subsections.items[index]; } pub const IndexContext = struct { @@ -154,8 +170,8 @@ pub const MergeSection = struct { msec.type, msec.flags, }); - for (msec.subsections.items) |index| { - try writer.print(" {}\n", .{elf_file.mergeSubsection(index).fmt(elf_file)}); + for (msec.subsections.items) |msub| { + try writer.print(" {}\n", .{msub.fmt(elf_file)}); } } @@ -250,18 +266,26 @@ pub const InputMergeSection = struct { // TODO: imsec.strings.clearAndFree(allocator); } - pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?struct { MergeSubsection.Index, u32 } { + const FindSubsectionResult = struct { + msub_index: MergeSubsection.Index, + offset: u32, + }; + + pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?FindSubsectionResult { // TODO: binary search for (imsec.offsets.items, 0..) |off, index| { if (offset < off) return .{ - imsec.subsections.items[index - 1], - offset - imsec.offsets.items[index - 1], + .msub_index = imsec.subsections.items[index - 1], + .offset = offset - imsec.offsets.items[index - 1], }; } const last = imsec.offsets.items.len - 1; const last_off = imsec.offsets.items[last]; const last_len = imsec.strings.items[last].len; - if (offset < last_off + last_len) return .{ imsec.subsections.items[last], offset - last_off }; + if (offset < last_off + last_len) return .{ + .msub_index = imsec.subsections.items[last], + .offset = offset - last_off, + }; return null; } |
