| author | |
| committer | |
| log | 0701646beb8421464346ce6e8993394d8d2c7d5c |
| tree | f65daea499e13e7c0e97a019a404f9490a9f3115 |
| parent | 24126f5382c09f54d8344208e6e38df632d35a44 |
7 files changed, 80 insertions(+), 72 deletions(-)
src/link/Elf.zig+13-28| ... | ... | @@ -208,9 +208,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| 208 | 208 | |
| 209 | 209 | /// List of output merge sections with deduped contents. |
| 210 | 210 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, |
| 211 | /// List of output merge subsections. | |
| 212 | /// Each subsection is akin to Atom but belongs to a MergeSection. | |
| 213 | merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, | |
| 214 | 211 | |
| 215 | 212 | /// Table of last atom index in a section and matching atom free list if any. |
| 216 | 213 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| ... | ... | @@ -497,7 +494,6 @@ pub fn deinit(self: *Elf) void { |
| 497 | 494 | sect.deinit(gpa); |
| 498 | 495 | } |
| 499 | 496 | self.merge_sections.deinit(gpa); |
| 500 | self.merge_subsections.deinit(gpa); | |
| 501 | 497 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 502 | 498 | value.free_list.deinit(gpa); |
| 503 | 499 | } |
| ... | ... | @@ -3288,12 +3284,13 @@ fn checkDuplicates(self: *Elf) !void { |
| 3288 | 3284 | } |
| 3289 | 3285 | |
| 3290 | 3286 | pub fn addCommentString(self: *Elf) !void { |
| 3287 | const gpa = self.base.comp.gpa; | |
| 3291 | 3288 | const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); |
| 3292 | 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 | 3291 | if (res.found_existing) return; |
| 3295 | const msub_index = try self.addMergeSubsection(); | |
| 3296 | const msub = self.mergeSubsection(msub_index); | |
| 3292 | const msub_index = try msec.addMergeSubsection(gpa); | |
| 3293 | const msub = msec.mergeSubsection(msub_index); | |
| 3297 | 3294 | msub.merge_section_index = msec_index; |
| 3298 | 3295 | msub.string_index = res.key.pos; |
| 3299 | 3296 | msub.alignment = .@"1"; |
| ... | ... | @@ -3340,8 +3337,8 @@ pub fn finalizeMergeSections(self: *Elf) !void { |
| 3340 | 3337 | pub fn updateMergeSectionSizes(self: *Elf) !void { |
| 3341 | 3338 | for (self.merge_sections.items) |*msec| { |
| 3342 | 3339 | const shdr = &self.shdrs.items[msec.output_section_index]; |
| 3343 | for (msec.subsections.items) |msub_index| { | |
| 3344 | const msub = self.mergeSubsection(msub_index); | |
| 3340 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3341 | const msub = msec.mergeSubsection(msub_index); | |
| 3345 | 3342 | assert(msub.alive); |
| 3346 | 3343 | const offset = msub.alignment.forward(shdr.sh_size); |
| 3347 | 3344 | const padding = offset - shdr.sh_size; |
| ... | ... | @@ -3357,14 +3354,14 @@ pub fn writeMergeSections(self: *Elf) !void { |
| 3357 | 3354 | var buffer = std.ArrayList(u8).init(gpa); |
| 3358 | 3355 | defer buffer.deinit(); |
| 3359 | 3356 | |
| 3360 | for (self.merge_sections.items) |msec| { | |
| 3357 | for (self.merge_sections.items) |*msec| { | |
| 3361 | 3358 | const shdr = self.shdrs.items[msec.output_section_index]; |
| 3362 | 3359 | const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 3363 | 3360 | try buffer.ensureTotalCapacity(size); |
| 3364 | 3361 | buffer.appendNTimesAssumeCapacity(0, size); |
| 3365 | 3362 | |
| 3366 | for (msec.subsections.items) |msub_index| { | |
| 3367 | const msub = self.mergeSubsection(msub_index); | |
| 3363 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3364 | const msub = msec.mergeSubsection(msub_index); | |
| 3368 | 3365 | assert(msub.alive); |
| 3369 | 3366 | const string = msub.getString(self); |
| 3370 | 3367 | const off = math.cast(usize, msub.value) orelse return error.Overflow; |
| ... | ... | @@ -3384,7 +3381,7 @@ fn initOutputSections(self: *Elf) !void { |
| 3384 | 3381 | |
| 3385 | 3382 | pub fn initMergeSections(self: *Elf) !void { |
| 3386 | 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 | 3385 | const name = msec.name(self); |
| 3389 | 3386 | const shndx = self.sectionByName(name) orelse try self.addSection(.{ |
| 3390 | 3387 | .name = name, |
| ... | ... | @@ -3393,9 +3390,9 @@ pub fn initMergeSections(self: *Elf) !void { |
| 3393 | 3390 | }); |
| 3394 | 3391 | msec.output_section_index = shndx; |
| 3395 | 3392 | |
| 3396 | var entsize = self.mergeSubsection(msec.subsections.items[0]).entsize; | |
| 3397 | for (msec.subsections.items) |index| { | |
| 3398 | const msub = self.mergeSubsection(index); | |
| 3393 | var entsize = msec.mergeSubsection(msec.finalized_subsections.items[0]).entsize; | |
| 3394 | for (msec.finalized_subsections.items) |msub_index| { | |
| 3395 | const msub = msec.mergeSubsection(msub_index); | |
| 3399 | 3396 | entsize = @min(entsize, msub.entsize); |
| 3400 | 3397 | } |
| 3401 | 3398 | const shdr = &self.shdrs.items[shndx]; |
| ... | ... | @@ -5706,18 +5703,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject { |
| 5706 | 5703 | return self.file(index).?.zig_object; |
| 5707 | 5704 | } |
| 5708 | 5705 | |
| 5709 | pub 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 | ||
| 5716 | pub 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 | ||
| 5721 | 5706 | pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index { |
| 5722 | 5707 | const gpa = self.base.comp.gpa; |
| 5723 | 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 | 47 | const global = elf_file.symbol(index); |
| 48 | 48 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { |
| 49 | 49 | global.value = 0; |
| 50 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 50 | global.ref = .{ .index = 0, .file = 0 }; | |
| 51 | 51 | global.file_index = self.index; |
| 52 | 52 | global.esym_index = sym_idx; |
| 53 | 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 | 388 | sym_ptr.esym_index = @as(u32, @intCast(i)); |
| 389 | 389 | sym_ptr.file_index = self.index; |
| 390 | 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 | } |
| 394 | 394 | |
| ... | ... | @@ -575,7 +575,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { |
| 575 | 575 | if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) { |
| 576 | 576 | switch (esym.st_shndx) { |
| 577 | 577 | elf.SHN_ABS, elf.SHN_COMMON => {}, |
| 578 | else => global.atom_ref = .{ | |
| 578 | else => global.ref = .{ | |
| 579 | 579 | .index = self.atoms_indexes.items[esym.st_shndx], |
| 580 | 580 | .file = self.index, |
| 581 | 581 | }, |
| ... | ... | @@ -609,7 +609,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 609 | 609 | }; |
| 610 | 610 | |
| 611 | 611 | global.value = 0; |
| 612 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 612 | global.ref = .{ .index = 0, .file = 0 }; | |
| 613 | 613 | global.esym_index = esym_index; |
| 614 | 614 | global.file_index = self.index; |
| 615 | 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 | 630 | } |
| 631 | 631 | |
| 632 | 632 | global.value = 0; |
| 633 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 633 | global.ref = .{ .index = 0, .file = 0 }; | |
| 634 | 634 | global.esym_index = esym_index; |
| 635 | 635 | global.file_index = self.index; |
| 636 | 636 | } |
| ... | ... | @@ -785,8 +785,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 785 | 785 | const string = imsec.bytes.items[str.pos..][0..str.len]; |
| 786 | 786 | const res = try msec.insert(gpa, string); |
| 787 | 787 | if (!res.found_existing) { |
| 788 | const msub_index = try elf_file.addMergeSubsection(); | |
| 789 | const msub = elf_file.mergeSubsection(msub_index); | |
| 788 | const msub_index = try msec.addMergeSubsection(gpa); | |
| 789 | const msub = msec.mergeSubsection(msub_index); | |
| 790 | 790 | msub.merge_section_index = imsec.merge_section_index; |
| 791 | 791 | msub.string_index = res.key.pos; |
| 792 | 792 | msub.alignment = atom_ptr.alignment; |
| ... | ... | @@ -810,7 +810,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 810 | 810 | const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; |
| 811 | 811 | const imsec = self.inputMergeSection(imsec_index) orelse continue; |
| 812 | 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 | 814 | var err = try elf_file.base.addErrorWithNotes(2); |
| 815 | 815 | try err.addMsg("invalid symbol value: {x}", .{esym.st_value}); |
| 816 | 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 | 818 | return error.MalformedObject; |
| 819 | 819 | }; |
| 820 | 820 | |
| 821 | try sym.addExtra(.{ .subsection = msub_index }, elf_file); | |
| 821 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; | |
| 822 | 822 | sym.flags.merge_subsection = true; |
| 823 | sym.value = offset; | |
| 823 | sym.value = res.offset; | |
| 824 | 824 | } |
| 825 | 825 | |
| 826 | 826 | for (self.atoms_indexes.items) |atom_index| { |
| ... | ... | @@ -835,28 +835,27 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 835 | 835 | const imsec_index = self.input_merge_sections_indexes.items[esym.st_shndx]; |
| 836 | 836 | const imsec = self.inputMergeSection(imsec_index) orelse continue; |
| 837 | 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 | 840 | var err = try elf_file.base.addErrorWithNotes(1); |
| 840 | 841 | try err.addMsg("invalid relocation at offset 0x{x}", .{rel.r_offset}); |
| 841 | 842 | try err.addNote("in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); |
| 842 | 843 | return error.MalformedObject; |
| 843 | 844 | }; |
| 844 | const msub = elf_file.mergeSubsection(msub_index); | |
| 845 | const msec = msub.mergeSection(elf_file); | |
| 846 | 845 | |
| 847 | 846 | const out_sym_idx: u64 = @intCast(self.symbols.items.len); |
| 848 | 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 | 849 | defer gpa.free(name); |
| 851 | 850 | const sym_index = try elf_file.addSymbol(); |
| 852 | 851 | const sym = elf_file.symbol(sym_index); |
| 853 | 852 | sym.* = .{ |
| 854 | .value = @bitCast(@as(i64, @intCast(offset)) - rel.r_addend), | |
| 853 | .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend), | |
| 855 | 854 | .name_offset = try self.addString(gpa, name), |
| 856 | 855 | .esym_index = rel.r_sym(), |
| 857 | 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 | 859 | sym.flags.merge_subsection = true; |
| 861 | 860 | self.symbols.addOneAssumeCapacity().* = sym_index; |
| 862 | 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 | 919 | try self.atoms_indexes.append(gpa, atom_index); |
| 921 | 920 | |
| 922 | 921 | global.value = 0; |
| 923 | global.atom_ref = .{ .index = atom_index, .file = self.index }; | |
| 922 | global.ref = .{ .index = atom_index, .file = self.index }; | |
| 924 | 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 | 232 | const global = elf_file.symbol(index); |
| 233 | 233 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { |
| 234 | 234 | global.value = @intCast(this_sym.st_value); |
| 235 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 235 | global.ref = .{ .index = 0, .file = 0 }; | |
| 236 | 236 | global.esym_index = esym_index; |
| 237 | 237 | global.version_index = self.versyms.items[esym_index]; |
| 238 | 238 | global.file_index = self.index; |
src/link/Elf/Symbol.zig+9-9| ... | ... | @@ -9,9 +9,9 @@ name_offset: u32 = 0, |
| 9 | 9 | /// Index of file where this symbol is defined. |
| 10 | 10 | file_index: File.Index = 0, |
| 11 | 11 | |
| 12 | /// Reference to Atom containing this symbol if any. | |
| 13 | /// Use `atom` to get the pointer to the atom. | |
| 14 | atom_ref: Elf.Ref = .{ .index = 0, .file = 0 }, | |
| 12 | /// Reference to Atom or merge subsection containing this symbol if any. | |
| 13 | /// Use `atom` or `mergeSubsection` to get the pointer to the atom. | |
| 14 | ref: Elf.Ref = .{ .index = 0, .file = 0 }, | |
| 15 | 15 | |
| 16 | 16 | /// Assigned output section index for this symbol. |
| 17 | 17 | output_section_index: u32 = 0, |
| ... | ... | @@ -71,14 +71,15 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 { |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { |
| 74 | const file_ptr = elf_file.file(symbol.atom_ref.file) orelse return null; | |
| 75 | return file_ptr.atom(symbol.atom_ref.index); | |
| 74 | if (symbol.flags.merge_subsection) return null; | |
| 75 | const file_ptr = elf_file.file(symbol.ref.file) orelse return null; | |
| 76 | return file_ptr.atom(symbol.ref.index); | |
| 76 | 77 | } |
| 77 | 78 | |
| 78 | 79 | pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection { |
| 79 | 80 | if (!symbol.flags.merge_subsection) return null; |
| 80 | const extras = symbol.extra(elf_file).?; | |
| 81 | return elf_file.mergeSubsection(extras.subsection); | |
| 81 | const msec = elf_file.mergeSection(symbol.ref.file); | |
| 82 | return msec.mergeSubsection(symbol.ref.index); | |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | 85 | pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| ... | ... | @@ -262,7 +263,6 @@ const AddExtraOpts = struct { |
| 262 | 263 | gottp: ?u32 = null, |
| 263 | 264 | tlsdesc: ?u32 = null, |
| 264 | 265 | zig_got: ?u32 = null, |
| 265 | subsection: ?u32 = null, | |
| 266 | 266 | }; |
| 267 | 267 | |
| 268 | 268 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { |
| ... | ... | @@ -488,7 +488,7 @@ pub const Extra = struct { |
| 488 | 488 | gottp: u32 = 0, |
| 489 | 489 | tlsdesc: u32 = 0, |
| 490 | 490 | zig_got: u32 = 0, |
| 491 | subsection: u32 = 0, | |
| 491 | merge_section: u32 = 0, | |
| 492 | 492 | }; |
| 493 | 493 | |
| 494 | 494 | pub 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 | 291 | |
| 292 | 292 | const symbol_ptr = elf_file.symbol(symbol_index); |
| 293 | 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 }; | |
| 295 | 295 | |
| 296 | 296 | self.local_esyms.items(.shndx)[esym_index] = atom_index; |
| 297 | 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 | 342 | else => unreachable, |
| 343 | 343 | }; |
| 344 | 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 | 346 | global.esym_index = esym_index; |
| 347 | 347 | global.file_index = self.index; |
| 348 | 348 | global.version_index = elf_file.default_sym_version; |
| ... | ... | @@ -371,7 +371,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { |
| 371 | 371 | }; |
| 372 | 372 | |
| 373 | 373 | global.value = 0; |
| 374 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 374 | global.ref = .{ .index = 0, .file = 0 }; | |
| 375 | 375 | global.esym_index = esym_index; |
| 376 | 376 | global.file_index = self.index; |
| 377 | 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 | 392 | } |
| 393 | 393 | |
| 394 | 394 | global.value = 0; |
| 395 | global.atom_ref = .{ .index = 0, .file = 0 }; | |
| 395 | global.ref = .{ .index = 0, .file = 0 }; | |
| 396 | 396 | global.esym_index = esym_index; |
| 397 | 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 | 10 | IndexContext, |
| 11 | 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) = .{}, | |
| 14 | 15 | |
| 15 | 16 | pub fn deinit(msec: *MergeSection, allocator: Allocator) void { |
| 16 | 17 | msec.bytes.deinit(allocator); |
| 17 | 18 | msec.table.deinit(allocator); |
| 18 | 19 | msec.subsections.deinit(allocator); |
| 20 | msec.finalized_subsections.deinit(allocator); | |
| 19 | 21 | } |
| 20 | 22 | |
| 21 | 23 | pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 { |
| ... | ... | @@ -60,23 +62,25 @@ pub const MergeSection = struct { |
| 60 | 62 | /// Sorts all owned subsections. |
| 61 | 63 | pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void { |
| 62 | 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); | |
| 64 | 66 | |
| 65 | 67 | var it = msec.table.iterator(); |
| 66 | 68 | while (it.next()) |entry| { |
| 67 | const msub = elf_file.mergeSubsection(entry.value_ptr.*); | |
| 69 | const msub = msec.mergeSubsection(entry.value_ptr.*); | |
| 68 | 70 | if (!msub.alive) continue; |
| 69 | msec.subsections.appendAssumeCapacity(entry.value_ptr.*); | |
| 71 | msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*); | |
| 70 | 72 | } |
| 71 | 73 | msec.table.clearAndFree(gpa); |
| 72 | 74 | |
| 73 | 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 | 77 | const lhs_msub = ctx.mergeSubsection(lhs); |
| 76 | 78 | const rhs_msub = ctx.mergeSubsection(rhs); |
| 77 | 79 | if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) { |
| 78 | 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 | 85 | return lhs_msub.size < rhs_msub.size; |
| 82 | 86 | } |
| ... | ... | @@ -84,7 +88,19 @@ pub const MergeSection = struct { |
| 84 | 88 | } |
| 85 | 89 | }.sortFn; |
| 86 | 90 | |
| 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 | } |
| 89 | 105 | |
| 90 | 106 | pub const IndexContext = struct { |
| ... | ... | @@ -154,8 +170,8 @@ pub const MergeSection = struct { |
| 154 | 170 | msec.type, |
| 155 | 171 | msec.flags, |
| 156 | 172 | }); |
| 157 | for (msec.subsections.items) |index| { | |
| 158 | try writer.print(" {}\n", .{elf_file.mergeSubsection(index).fmt(elf_file)}); | |
| 173 | for (msec.subsections.items) |msub| { | |
| 174 | try writer.print(" {}\n", .{msub.fmt(elf_file)}); | |
| 159 | 175 | } |
| 160 | 176 | } |
| 161 | 177 | |
| ... | ... | @@ -250,18 +266,26 @@ pub const InputMergeSection = struct { |
| 250 | 266 | // TODO: imsec.strings.clearAndFree(allocator); |
| 251 | 267 | } |
| 252 | 268 | |
| 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 | 275 | // TODO: binary search |
| 255 | 276 | for (imsec.offsets.items, 0..) |off, index| { |
| 256 | 277 | if (offset < off) return .{ |
| 257 | imsec.subsections.items[index - 1], | |
| 258 | offset - imsec.offsets.items[index - 1], | |
| 278 | .msub_index = imsec.subsections.items[index - 1], | |
| 279 | .offset = offset - imsec.offsets.items[index - 1], | |
| 259 | 280 | }; |
| 260 | 281 | } |
| 261 | 282 | const last = imsec.offsets.items.len - 1; |
| 262 | 283 | const last_off = imsec.offsets.items[last]; |
| 263 | 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 | 289 | return null; |
| 266 | 290 | } |
| 267 | 291 |