authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-28 10:24:26+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-30 10:00:50+02:00
log0701646beb8421464346ce6e8993394d8d2c7d5c
treef65daea499e13e7c0e97a019a404f9490a9f3115
parent24126f5382c09f54d8344208e6e38df632d35a44

elf: move merge subsections ownership into merge sections


7 files changed, 80 insertions(+), 72 deletions(-)

src/link/Elf.zig+13-28
...@@ -208,9 +208,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{},...@@ -208,9 +208,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{},
208208
209/// List of output merge sections with deduped contents.209/// List of output merge sections with deduped contents.
210merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},210merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
211/// List of output merge subsections.
212/// Each subsection is akin to Atom but belongs to a MergeSection.
213merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{},
214211
215/// Table of last atom index in a section and matching atom free list if any.212/// Table of last atom index in a section and matching atom free list if any.
216last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},213last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
...@@ -497,7 +494,6 @@ pub fn deinit(self: *Elf) void {...@@ -497,7 +494,6 @@ pub fn deinit(self: *Elf) void {
497 sect.deinit(gpa);494 sect.deinit(gpa);
498 }495 }
499 self.merge_sections.deinit(gpa);496 self.merge_sections.deinit(gpa);
500 self.merge_subsections.deinit(gpa);
501 for (self.last_atom_and_free_list_table.values()) |*value| {497 for (self.last_atom_and_free_list_table.values()) |*value| {
502 value.free_list.deinit(gpa);498 value.free_list.deinit(gpa);
503 }499 }
...@@ -3288,12 +3284,13 @@ fn checkDuplicates(self: *Elf) !void {...@@ -3288,12 +3284,13 @@ fn checkDuplicates(self: *Elf) !void {
3288}3284}
32893285
3290pub fn addCommentString(self: *Elf) !void {3286pub fn addCommentString(self: *Elf) !void {
3287 const gpa = self.base.comp.gpa;
3291 const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS);3288 const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS);
3292 const msec = self.mergeSection(msec_index);3289 const msec = self.mergeSection(msec_index);
3293 const res = try msec.insertZ(self.base.comp.gpa, "zig " ++ builtin.zig_version_string);3290 const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string);
3294 if (res.found_existing) return;3291 if (res.found_existing) return;
3295 const msub_index = try self.addMergeSubsection();3292 const msub_index = try msec.addMergeSubsection(gpa);
3296 const msub = self.mergeSubsection(msub_index);3293 const msub = msec.mergeSubsection(msub_index);
3297 msub.merge_section_index = msec_index;3294 msub.merge_section_index = msec_index;
3298 msub.string_index = res.key.pos;3295 msub.string_index = res.key.pos;
3299 msub.alignment = .@"1";3296 msub.alignment = .@"1";
...@@ -3340,8 +3337,8 @@ pub fn finalizeMergeSections(self: *Elf) !void {...@@ -3340,8 +3337,8 @@ pub fn finalizeMergeSections(self: *Elf) !void {
3340pub fn updateMergeSectionSizes(self: *Elf) !void {3337pub fn updateMergeSectionSizes(self: *Elf) !void {
3341 for (self.merge_sections.items) |*msec| {3338 for (self.merge_sections.items) |*msec| {
3342 const shdr = &self.shdrs.items[msec.output_section_index];3339 const shdr = &self.shdrs.items[msec.output_section_index];
3343 for (msec.subsections.items) |msub_index| {3340 for (msec.finalized_subsections.items) |msub_index| {
3344 const msub = self.mergeSubsection(msub_index);3341 const msub = msec.mergeSubsection(msub_index);
3345 assert(msub.alive);3342 assert(msub.alive);
3346 const offset = msub.alignment.forward(shdr.sh_size);3343 const offset = msub.alignment.forward(shdr.sh_size);
3347 const padding = offset - shdr.sh_size;3344 const padding = offset - shdr.sh_size;
...@@ -3357,14 +3354,14 @@ pub fn writeMergeSections(self: *Elf) !void {...@@ -3357,14 +3354,14 @@ pub fn writeMergeSections(self: *Elf) !void {
3357 var buffer = std.ArrayList(u8).init(gpa);3354 var buffer = std.ArrayList(u8).init(gpa);
3358 defer buffer.deinit();3355 defer buffer.deinit();
33593356
3360 for (self.merge_sections.items) |msec| {3357 for (self.merge_sections.items) |*msec| {
3361 const shdr = self.shdrs.items[msec.output_section_index];3358 const shdr = self.shdrs.items[msec.output_section_index];
3362 const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;3359 const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
3363 try buffer.ensureTotalCapacity(size);3360 try buffer.ensureTotalCapacity(size);
3364 buffer.appendNTimesAssumeCapacity(0, size);3361 buffer.appendNTimesAssumeCapacity(0, size);
33653362
3366 for (msec.subsections.items) |msub_index| {3363 for (msec.finalized_subsections.items) |msub_index| {
3367 const msub = self.mergeSubsection(msub_index);3364 const msub = msec.mergeSubsection(msub_index);
3368 assert(msub.alive);3365 assert(msub.alive);
3369 const string = msub.getString(self);3366 const string = msub.getString(self);
3370 const off = math.cast(usize, msub.value) orelse return error.Overflow;3367 const off = math.cast(usize, msub.value) orelse return error.Overflow;
...@@ -3384,7 +3381,7 @@ fn initOutputSections(self: *Elf) !void {...@@ -3384,7 +3381,7 @@ fn initOutputSections(self: *Elf) !void {
33843381
3385pub fn initMergeSections(self: *Elf) !void {3382pub fn initMergeSections(self: *Elf) !void {
3386 for (self.merge_sections.items) |*msec| {3383 for (self.merge_sections.items) |*msec| {
3387 if (msec.subsections.items.len == 0) continue;3384 if (msec.finalized_subsections.items.len == 0) continue;
3388 const name = msec.name(self);3385 const name = msec.name(self);
3389 const shndx = self.sectionByName(name) orelse try self.addSection(.{3386 const shndx = self.sectionByName(name) orelse try self.addSection(.{
3390 .name = name,3387 .name = name,
...@@ -3393,9 +3390,9 @@ pub fn initMergeSections(self: *Elf) !void {...@@ -3393,9 +3390,9 @@ pub fn initMergeSections(self: *Elf) !void {
3393 });3390 });
3394 msec.output_section_index = shndx;3391 msec.output_section_index = shndx;
33953392
3396 var entsize = self.mergeSubsection(msec.subsections.items[0]).entsize;3393 var entsize = msec.mergeSubsection(msec.finalized_subsections.items[0]).entsize;
3397 for (msec.subsections.items) |index| {3394 for (msec.finalized_subsections.items) |msub_index| {
3398 const msub = self.mergeSubsection(index);3395 const msub = msec.mergeSubsection(msub_index);
3399 entsize = @min(entsize, msub.entsize);3396 entsize = @min(entsize, msub.entsize);
3400 }3397 }
3401 const shdr = &self.shdrs.items[shndx];3398 const shdr = &self.shdrs.items[shndx];
...@@ -5706,18 +5703,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject {...@@ -5706,18 +5703,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject {
5706 return self.file(index).?.zig_object;5703 return self.file(index).?.zig_object;
5707}5704}
57085705
5709pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index {
5710 const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len);
5711 const msec = try self.merge_subsections.addOne(self.base.comp.gpa);
5712 msec.* = .{};
5713 return index;
5714}
5715
5716pub fn mergeSubsection(self: *Elf, index: MergeSubsection.Index) *MergeSubsection {
5717 assert(index < self.merge_subsections.items.len);
5718 return &self.merge_subsections.items[index];
5719}
5720
5721pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index {5706pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index {
5722 const gpa = self.base.comp.gpa;5707 const gpa = self.base.comp.gpa;
5723 const out_name = name: {5708 const out_name = name: {
src/link/Elf/LinkerDefined.zig+1-1
...@@ -47,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -47,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
47 const global = elf_file.symbol(index);47 const global = elf_file.symbol(index);
48 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {48 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
49 global.value = 0;49 global.value = 0;
50 global.atom_ref = .{ .index = 0, .file = 0 };50 global.ref = .{ .index = 0, .file = 0 };
51 global.file_index = self.index;51 global.file_index = self.index;
52 global.esym_index = sym_idx;52 global.esym_index = sym_idx;
53 global.version_index = elf_file.default_sym_version;53 global.version_index = elf_file.default_sym_version;
src/link/Elf/Object.zig+15-16
...@@ -388,7 +388,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {...@@ -388,7 +388,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
388 sym_ptr.esym_index = @as(u32, @intCast(i));388 sym_ptr.esym_index = @as(u32, @intCast(i));
389 sym_ptr.file_index = self.index;389 sym_ptr.file_index = self.index;
390 if (sym.st_shndx != elf.SHN_ABS) {390 if (sym.st_shndx != elf.SHN_ABS) {
391 sym_ptr.atom_ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };391 sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
392 }392 }
393 }393 }
394394
...@@ -575,7 +575,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {...@@ -575,7 +575,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
575 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {575 if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {
576 switch (esym.st_shndx) {576 switch (esym.st_shndx) {
577 elf.SHN_ABS, elf.SHN_COMMON => {},577 elf.SHN_ABS, elf.SHN_COMMON => {},
578 else => global.atom_ref = .{578 else => global.ref = .{
579 .index = self.atoms_indexes.items[esym.st_shndx],579 .index = self.atoms_indexes.items[esym.st_shndx],
580 .file = self.index,580 .file = self.index,
581 },581 },
...@@ -609,7 +609,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {...@@ -609,7 +609,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
609 };609 };
610610
611 global.value = 0;611 global.value = 0;
612 global.atom_ref = .{ .index = 0, .file = 0 };612 global.ref = .{ .index = 0, .file = 0 };
613 global.esym_index = esym_index;613 global.esym_index = esym_index;
614 global.file_index = self.index;614 global.file_index = self.index;
615 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;615 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 {...@@ -630,7 +630,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
630 }630 }
631631
632 global.value = 0;632 global.value = 0;
633 global.atom_ref = .{ .index = 0, .file = 0 };633 global.ref = .{ .index = 0, .file = 0 };
634 global.esym_index = esym_index;634 global.esym_index = esym_index;
635 global.file_index = self.index;635 global.file_index = self.index;
636 }636 }
...@@ -785,8 +785,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -785,8 +785,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
785 const string = imsec.bytes.items[str.pos..][0..str.len];785 const string = imsec.bytes.items[str.pos..][0..str.len];
786 const res = try msec.insert(gpa, string);786 const res = try msec.insert(gpa, string);
787 if (!res.found_existing) {787 if (!res.found_existing) {
788 const msub_index = try elf_file.addMergeSubsection();788 const msub_index = try msec.addMergeSubsection(gpa);
789 const msub = elf_file.mergeSubsection(msub_index);789 const msub = msec.mergeSubsection(msub_index);
790 msub.merge_section_index = imsec.merge_section_index;790 msub.merge_section_index = imsec.merge_section_index;
791 msub.string_index = res.key.pos;791 msub.string_index = res.key.pos;
792 msub.alignment = atom_ptr.alignment;792 msub.alignment = atom_ptr.alignment;
...@@ -810,7 +810,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -810,7 +810,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
810 const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx];810 const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx];
811 const imsec = self.inputMergeSection(imsec_index) orelse continue;811 const imsec = self.inputMergeSection(imsec_index) orelse continue;
812 if (imsec.offsets.items.len == 0) continue;812 if (imsec.offsets.items.len == 0) continue;
813 const msub_index, const offset = imsec.findSubsection(@intCast(esym.st_value)) orelse {813 const res = imsec.findSubsection(@intCast(esym.st_value)) orelse {
814 var err = try elf_file.base.addErrorWithNotes(2);814 var err = try elf_file.base.addErrorWithNotes(2);
815 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});815 try err.addMsg("invalid symbol value: {x}", .{esym.st_value});
816 try err.addNote("for symbol {s}", .{sym.name(elf_file)});816 try err.addNote("for symbol {s}", .{sym.name(elf_file)});
...@@ -818,9 +818,9 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -818,9 +818,9 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
818 return error.MalformedObject;818 return error.MalformedObject;
819 };819 };
820820
821 try sym.addExtra(.{ .subsection = msub_index }, elf_file);821 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
822 sym.flags.merge_subsection = true;822 sym.flags.merge_subsection = true;
823 sym.value = offset;823 sym.value = res.offset;
824 }824 }
825825
826 for (self.atoms_indexes.items) |atom_index| {826 for (self.atoms_indexes.items) |atom_index| {
...@@ -835,28 +835,27 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {...@@ -835,28 +835,27 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
835 const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx];835 const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx];
836 const imsec = self.inputMergeSection(imsec_index) orelse continue;836 const imsec = self.inputMergeSection(imsec_index) orelse continue;
837 if (imsec.offsets.items.len == 0) continue;837 if (imsec.offsets.items.len == 0) continue;
838 const msub_index, const offset = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {838 const msec = elf_file.mergeSection(imsec.merge_section_index);
839 const res = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse {
839 var err = try elf_file.base.addErrorWithNotes(1);840 var err = try elf_file.base.addErrorWithNotes(1);
840 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});841 try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset});
841 try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });842 try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
842 return error.MalformedObject;843 return error.MalformedObject;
843 };844 };
844 const msub = elf_file.mergeSubsection(msub_index);
845 const msec = msub.mergeSection(elf_file);
846845
847 const out_sym_idx: u64 = @intCast(self.symbols.items.len);846 const out_sym_idx: u64 = @intCast(self.symbols.items.len);
848 try self.symbols.ensureUnusedCapacity(gpa, 1);847 try self.symbols.ensureUnusedCapacity(gpa, 1);
849 const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), msub_index });848 const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index });
850 defer gpa.free(name);849 defer gpa.free(name);
851 const sym_index = try elf_file.addSymbol();850 const sym_index = try elf_file.addSymbol();
852 const sym = elf_file.symbol(sym_index);851 const sym = elf_file.symbol(sym_index);
853 sym.* = .{852 sym.* = .{
854 .value = @bitCast(@as(i64, @intCast(offset)) - rel.r_addend),853 .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend),
855 .name_offset = try self.addString(gpa, name),854 .name_offset = try self.addString(gpa, name),
856 .esym_index = rel.r_sym(),855 .esym_index = rel.r_sym(),
857 .file_index = self.index,856 .file_index = self.index,
858 };857 };
859 try sym.addExtra(.{ .subsection = msub_index }, elf_file);858 sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index };
860 sym.flags.merge_subsection = true;859 sym.flags.merge_subsection = true;
861 self.symbols.addOneAssumeCapacity().* = sym_index;860 self.symbols.addOneAssumeCapacity().* = sym_index;
862 rel.r_info = (out_sym_idx << 32) | rel.r_type();861 rel.r_info = (out_sym_idx << 32) | rel.r_type();
...@@ -920,7 +919,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -920,7 +919,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
920 try self.atoms_indexes.append(gpa, atom_index);919 try self.atoms_indexes.append(gpa, atom_index);
921920
922 global.value = 0;921 global.value = 0;
923 global.atom_ref = .{ .index = atom_index, .file = self.index };922 global.ref = .{ .index = atom_index, .file = self.index };
924 global.flags.weak = false;923 global.flags.weak = false;
925 }924 }
926}925}
src/link/Elf/SharedObject.zig+1-1
...@@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {...@@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {
232 const global = elf_file.symbol(index);232 const global = elf_file.symbol(index);
233 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {233 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
234 global.value = @intCast(this_sym.st_value);234 global.value = @intCast(this_sym.st_value);
235 global.atom_ref = .{ .index = 0, .file = 0 };235 global.ref = .{ .index = 0, .file = 0 };
236 global.esym_index = esym_index;236 global.esym_index = esym_index;
237 global.version_index = self.versyms.items[esym_index];237 global.version_index = self.versyms.items[esym_index];
238 global.file_index = self.index;238 global.file_index = self.index;
src/link/Elf/Symbol.zig+9-9
...@@ -9,9 +9,9 @@ name_offset: u32 = 0,...@@ -9,9 +9,9 @@ name_offset: u32 = 0,
9/// Index of file where this symbol is defined.9/// Index of file where this symbol is defined.
10file_index: File.Index = 0,10file_index: File.Index = 0,
1111
12/// Reference to Atom containing this symbol if any.12/// Reference to Atom or merge subsection containing this symbol if any.
13/// Use `atom` to get the pointer to the atom.13/// Use `atom` or `mergeSubsection` to get the pointer to the atom.
14atom_ref: Elf.Ref = .{ .index = 0, .file = 0 },14ref: Elf.Ref = .{ .index = 0, .file = 0 },
1515
16/// Assigned output section index for this symbol.16/// Assigned output section index for this symbol.
17output_section_index: u32 = 0,17output_section_index: u32 = 0,
...@@ -71,14 +71,15 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {...@@ -71,14 +71,15 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
71}71}
7272
73pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {73pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
74 const file_ptr = elf_file.file(symbol.atom_ref.file) orelse return null;74 if (symbol.flags.merge_subsection) return null;
75 return file_ptr.atom(symbol.atom_ref.index);75 const file_ptr = elf_file.file(symbol.ref.file) orelse return null;
76 return file_ptr.atom(symbol.ref.index);
76}77}
7778
78pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {79pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {
79 if (!symbol.flags.merge_subsection) return null;80 if (!symbol.flags.merge_subsection) return null;
80 const extras = symbol.extra(elf_file).?;81 const msec = elf_file.mergeSection(symbol.ref.file);
81 return elf_file.mergeSubsection(extras.subsection);82 return msec.mergeSubsection(symbol.ref.index);
82}83}
8384
84pub fn file(symbol: Symbol, elf_file: *Elf) ?File {85pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
...@@ -262,7 +263,6 @@ const AddExtraOpts = struct {...@@ -262,7 +263,6 @@ const AddExtraOpts = struct {
262 gottp: ?u32 = null,263 gottp: ?u32 = null,
263 tlsdesc: ?u32 = null,264 tlsdesc: ?u32 = null,
264 zig_got: ?u32 = null,265 zig_got: ?u32 = null,
265 subsection: ?u32 = null,
266};266};
267267
268pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {268pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
...@@ -488,7 +488,7 @@ pub const Extra = struct {...@@ -488,7 +488,7 @@ pub const Extra = struct {
488 gottp: u32 = 0,488 gottp: u32 = 0,
489 tlsdesc: u32 = 0,489 tlsdesc: u32 = 0,
490 zig_got: u32 = 0,490 zig_got: u32 = 0,
491 subsection: u32 = 0,491 merge_section: u32 = 0,
492};492};
493493
494pub const Index = u32;494pub const Index = u32;
src/link/Elf/ZigObject.zig+4-4
...@@ -291,7 +291,7 @@ pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {...@@ -291,7 +291,7 @@ pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
291291
292 const symbol_ptr = elf_file.symbol(symbol_index);292 const symbol_ptr = elf_file.symbol(symbol_index);
293 symbol_ptr.file_index = self.index;293 symbol_ptr.file_index = self.index;
294 symbol_ptr.atom_ref = .{ .index = atom_index, .file = self.index };294 symbol_ptr.ref = .{ .index = atom_index, .file = self.index };
295295
296 self.local_esyms.items(.shndx)[esym_index] = atom_index;296 self.local_esyms.items(.shndx)[esym_index] = atom_index;
297 self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;297 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 {...@@ -342,7 +342,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
342 else => unreachable,342 else => unreachable,
343 };343 };
344 global.value = @intCast(esym.st_value);344 global.value = @intCast(esym.st_value);
345 global.atom_ref = .{ .index = atom_index, .file = self.index };345 global.ref = .{ .index = atom_index, .file = self.index };
346 global.esym_index = esym_index;346 global.esym_index = esym_index;
347 global.file_index = self.index;347 global.file_index = self.index;
348 global.version_index = elf_file.default_sym_version;348 global.version_index = elf_file.default_sym_version;
...@@ -371,7 +371,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {...@@ -371,7 +371,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
371 };371 };
372372
373 global.value = 0;373 global.value = 0;
374 global.atom_ref = .{ .index = 0, .file = 0 };374 global.ref = .{ .index = 0, .file = 0 };
375 global.esym_index = esym_index;375 global.esym_index = esym_index;
376 global.file_index = self.index;376 global.file_index = self.index;
377 global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;377 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 {...@@ -392,7 +392,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
392 }392 }
393393
394 global.value = 0;394 global.value = 0;
395 global.atom_ref = .{ .index = 0, .file = 0 };395 global.ref = .{ .index = 0, .file = 0 };
396 global.esym_index = esym_index;396 global.esym_index = esym_index;
397 global.file_index = self.index;397 global.file_index = self.index;
398 }398 }
src/link/Elf/merge_section.zig+37-13
...@@ -10,12 +10,14 @@ pub const MergeSection = struct {...@@ -10,12 +10,14 @@ pub const MergeSection = struct {
10 IndexContext,10 IndexContext,
11 std.hash_map.default_max_load_percentage,11 std.hash_map.default_max_load_percentage,
12 ) = .{},12 ) = .{},
13 subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{},13 subsections: std.ArrayListUnmanaged(MergeSubsection) = .{},
14 finalized_subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .{},
1415
15 pub fn deinit(msec: *MergeSection, allocator: Allocator) void {16 pub fn deinit(msec: *MergeSection, allocator: Allocator) void {
16 msec.bytes.deinit(allocator);17 msec.bytes.deinit(allocator);
17 msec.table.deinit(allocator);18 msec.table.deinit(allocator);
18 msec.subsections.deinit(allocator);19 msec.subsections.deinit(allocator);
20 msec.finalized_subsections.deinit(allocator);
19 }21 }
2022
21 pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 {23 pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 {
...@@ -60,23 +62,25 @@ pub const MergeSection = struct {...@@ -60,23 +62,25 @@ pub const MergeSection = struct {
60 /// Sorts all owned subsections.62 /// Sorts all owned subsections.
61 pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void {63 pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void {
62 const gpa = elf_file.base.comp.gpa;64 const gpa = elf_file.base.comp.gpa;
63 try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count());65 try msec.finalized_subsections.ensureTotalCapacityPrecise(gpa, msec.subsections.items.len);
6466
65 var it = msec.table.iterator();67 var it = msec.table.iterator();
66 while (it.next()) |entry| {68 while (it.next()) |entry| {
67 const msub = elf_file.mergeSubsection(entry.value_ptr.*);69 const msub = msec.mergeSubsection(entry.value_ptr.*);
68 if (!msub.alive) continue;70 if (!msub.alive) continue;
69 msec.subsections.appendAssumeCapacity(entry.value_ptr.*);71 msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*);
70 }72 }
71 msec.table.clearAndFree(gpa);73 msec.table.clearAndFree(gpa);
7274
73 const sortFn = struct {75 const sortFn = struct {
74 pub fn sortFn(ctx: *Elf, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool {76 pub fn sortFn(ctx: *MergeSection, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool {
75 const lhs_msub = ctx.mergeSubsection(lhs);77 const lhs_msub = ctx.mergeSubsection(lhs);
76 const rhs_msub = ctx.mergeSubsection(rhs);78 const rhs_msub = ctx.mergeSubsection(rhs);
77 if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) {79 if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) {
78 if (lhs_msub.size == rhs_msub.size) {80 if (lhs_msub.size == rhs_msub.size) {
79 return mem.order(u8, lhs_msub.getString(ctx), rhs_msub.getString(ctx)) == .lt;81 const lhs_string = ctx.bytes.items[lhs_msub.string_index..][0..lhs_msub.size];
82 const rhs_string = ctx.bytes.items[rhs_msub.string_index..][0..rhs_msub.size];
83 return mem.order(u8, lhs_string, rhs_string) == .lt;
80 }84 }
81 return lhs_msub.size < rhs_msub.size;85 return lhs_msub.size < rhs_msub.size;
82 }86 }
...@@ -84,7 +88,19 @@ pub const MergeSection = struct {...@@ -84,7 +88,19 @@ pub const MergeSection = struct {
84 }88 }
85 }.sortFn;89 }.sortFn;
8690
87 std.mem.sort(MergeSubsection.Index, msec.subsections.items, elf_file, sortFn);91 std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn);
92 }
93
94 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {
95 const index: MergeSubsection.Index = @intCast(msec.subsections.items.len);
96 const msub = try msec.subsections.addOne(allocator);
97 msub.* = .{};
98 return index;
99 }
100
101 pub fn mergeSubsection(msec: *MergeSection, index: MergeSubsection.Index) *MergeSubsection {
102 assert(index < msec.subsections.items.len);
103 return &msec.subsections.items[index];
88 }104 }
89105
90 pub const IndexContext = struct {106 pub const IndexContext = struct {
...@@ -154,8 +170,8 @@ pub const MergeSection = struct {...@@ -154,8 +170,8 @@ pub const MergeSection = struct {
154 msec.type,170 msec.type,
155 msec.flags,171 msec.flags,
156 });172 });
157 for (msec.subsections.items) |index| {173 for (msec.subsections.items) |msub| {
158 try writer.print(" {}\n", .{elf_file.mergeSubsection(index).fmt(elf_file)});174 try writer.print(" {}\n", .{msub.fmt(elf_file)});
159 }175 }
160 }176 }
161177
...@@ -250,18 +266,26 @@ pub const InputMergeSection = struct {...@@ -250,18 +266,26 @@ pub const InputMergeSection = struct {
250 // TODO: imsec.strings.clearAndFree(allocator);266 // TODO: imsec.strings.clearAndFree(allocator);
251 }267 }
252268
253 pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?struct { MergeSubsection.Index, u32 } {269 const FindSubsectionResult = struct {
270 msub_index: MergeSubsection.Index,
271 offset: u32,
272 };
273
274 pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?FindSubsectionResult {
254 // TODO: binary search275 // TODO: binary search
255 for (imsec.offsets.items, 0..) |off, index| {276 for (imsec.offsets.items, 0..) |off, index| {
256 if (offset < off) return .{277 if (offset < off) return .{
257 imsec.subsections.items[index - 1],278 .msub_index = imsec.subsections.items[index - 1],
258 offset - imsec.offsets.items[index - 1],279 .offset = offset - imsec.offsets.items[index - 1],
259 };280 };
260 }281 }
261 const last = imsec.offsets.items.len - 1;282 const last = imsec.offsets.items.len - 1;
262 const last_off = imsec.offsets.items[last];283 const last_off = imsec.offsets.items[last];
263 const last_len = imsec.strings.items[last].len;284 const last_len = imsec.strings.items[last].len;
264 if (offset < last_off + last_len) return .{ imsec.subsections.items[last], offset - last_off };285 if (offset < last_off + last_len) return .{
286 .msub_index = imsec.subsections.items[last],
287 .offset = offset - last_off,
288 };
265 return null;289 return null;
266 }290 }
267291