authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:34-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:22:42-04:00
log3ee12f3a2aeab1aff5852466cf0c654222e034cc
treed83bb2a05aeb0e32645e3e182a55cc62cd072675
parentcef6ea05d982589d29bc312b43bde1432ea78623

Coff: linking against archives is now functional

- Fixup not aligning section header start when reading archives - Load archive members on-deman as symbols from them are referenced - Sort symbols by section before building inputs_resolved so that ranges are contiguous

1 files changed, 182 insertions(+), 81 deletions(-)

src/link/Coff.zig+182-81
......@@ -38,13 +38,10 @@ input_archive_symbol_indices: std.AutoArrayHashMapUnmanaged(String, struct {
3838 first: InputArchive.Member.Symbol.Index,
3939 last: InputArchive.Member.Symbol.Index,
4040}),
41pending_input: ?InputArchive.Member.Index,
4142inputs: std.ArrayList(Input),
4243input_resolved: std.ArrayList(Symbol.Index),
43input_sections: std.ArrayList(struct {
44 ii: Node.InputIndex,
45 si: Symbol.Index,
46 file_location: MappedFile.Node.FileLocation,
47}),
44input_sections: std.ArrayList(Node.InputSection),
4845input_section_pending_index: u32,
4946strings: std.HashMapUnmanaged(
5047 u32,
......@@ -203,7 +200,7 @@ pub const Node = union(enum) {
203200
204201 pseudo_section: PseudoSectionMapIndex,
205202 object_section: ObjectSectionMapIndex,
206 input_section: InputSectionIndex,
203 input_section: InputSection.Index,
207204 global: GlobalMapIndex,
208205 nav: NavMapIndex,
209206 uav: UavMapIndex,
......@@ -292,16 +289,16 @@ pub const Node = union(enum) {
292289 return coff.inputs.items[@intFromEnum(ii)].path;
293290 }
294291
295 pub fn archiveName(ii: InputIndex, coff: *const Coff) ?[]const u8 {
296 return coff.inputs.items[@intFromEnum(ii)].archive_name;
292 pub fn memberName(ii: InputIndex, coff: *const Coff) ?[]const u8 {
293 return coff.inputs.items[@intFromEnum(ii)].member_name;
297294 }
298295
299296 pub fn firstSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index {
300297 return coff.inputs.items[@intFromEnum(ii)].first_si;
301298 }
302299
303 pub fn lastSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index {
304 return coff.inputs.items[@intFromEnum(ii)].last_si;
300 pub fn endSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index {
301 return coff.inputs.items[@intFromEnum(ii)].end_si;
305302 }
306303
307304 pub fn firstResolvedGlobal(ii: InputIndex, coff: *const Coff) Input.ResolvedIndex {
......@@ -309,24 +306,39 @@ pub const Node = union(enum) {
309306 }
310307 };
311308
312 pub const InputSectionIndex = enum(u32) {
313 _,
309 const InputSection = struct {
310 ii: Node.InputIndex,
311 si: Symbol.Index,
312 file_location: MappedFile.Node.FileLocation,
313 first_iri: Node.InputSection.ResolvedIndex,
314314
315 pub fn input(isi: InputSectionIndex, coff: *const Coff) InputIndex {
316 return coff.input_sections.items[@intFromEnum(isi)].ii;
317 }
315 pub const Index = enum(u32) {
316 _,
318317
319 pub fn fileLocation(isi: InputSectionIndex, coff: *const Coff) MappedFile.Node.FileLocation {
320 return coff.input_sections.items[@intFromEnum(isi)].file_location;
321 }
318 pub fn inputSection(isi: Index, coff: *const Coff) *InputSection {
319 return &coff.input_sections.items[@intFromEnum(isi)];
320 }
322321
323 pub fn symbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index {
324 return coff.input_sections.items[@intFromEnum(isi)].si;
325 }
322 pub fn input(isi: Index, coff: *const Coff) InputIndex {
323 return coff.input_sections.items[@intFromEnum(isi)].ii;
324 }
326325
327 pub fn lastSymbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index {
328 return coff.input_sections.items[@intFromEnum(isi)].last_si;
329 }
326 pub fn fileLocation(isi: Index, coff: *const Coff) MappedFile.Node.FileLocation {
327 return coff.input_sections.items[@intFromEnum(isi)].file_location;
328 }
329
330 pub fn symbol(isi: Index, coff: *const Coff) Symbol.Index {
331 return coff.input_sections.items[@intFromEnum(isi)].si;
332 }
333
334 pub fn firstResolvedSymbol(isi: Index, coff: *const Coff) ResolvedIndex {
335 return coff.input_sections.items[@intFromEnum(isi)].first_iri;
336 }
337 };
338
339 const ResolvedIndex = enum(u32) {
340 _,
341 };
330342 };
331343
332344 pub const LazyMapRef = struct {
......@@ -398,6 +410,10 @@ pub const InputArchive = struct {
398410
399411 const Index = enum(u32) {
400412 _,
413
414 pub fn path(iai: InputArchive.Index, coff: *Coff) std.Build.Cache.Path {
415 return coff.input_archives.items[@intFromEnum(iai)].path;
416 }
401417 };
402418
403419 pub const Member = struct {
......@@ -405,10 +421,17 @@ pub const InputArchive = struct {
405421 name: String,
406422 // This range includes the member header
407423 file_location: MappedFile.Node.FileLocation,
408 is_import: bool,
409 // TODO: Field indicating we loaded it already (ii)
424 flags: packed struct {
425 is_import: bool,
426 is_loaded: bool,
427 },
428
410429 const Index = enum(u32) {
411430 _,
431
432 pub fn member(iami: InputArchive.Member.Index, coff: *Coff) *InputArchive.Member {
433 return &coff.input_archive_members.items[@intFromEnum(iami)];
434 }
412435 };
413436
414437 pub const Symbol = struct {
......@@ -425,14 +448,9 @@ pub const InputArchive = struct {
425448
426449pub const Input = struct {
427450 path: std.Build.Cache.Path,
428 archive_name: ?[]const u8,
451 member_name: ?[]const u8,
429452 first_si: Symbol.Index,
430 last_si: Symbol.Index,
431 first_iri: ResolvedIndex,
432
433 const ResolvedIndex = enum(u32) {
434 _,
435 };
453 end_si: Symbol.Index,
436454};
437455
438456pub const Member = struct {
......@@ -1336,6 +1354,7 @@ fn create(
13361354 .input_archive_members = .empty,
13371355 .input_archive_symbols = .empty,
13381356 .input_archive_symbol_indices = .empty,
1357 .pending_input = null,
13391358 .inputs = .empty,
13401359 .input_resolved = .empty,
13411360 .input_sections = .empty,
......@@ -2315,6 +2334,8 @@ fn getOrPutGlobalSymbol(
23152334 si.get(coff).gmi = .wrap(@intCast(sym_gop.index));
23162335 sym_gop.value_ptr.* = si;
23172336 coff.synth_prog_node.increaseEstimatedTotalItems(1);
2337
2338 log.debug("globalSymbol({s}, {?s}) = {d}", .{ opts.name, opts.lib_name, si });
23182339 }
23192340
23202341 return sym_gop;
......@@ -2724,7 +2745,28 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void
27242745 log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti });
27252746}
27262747
2727fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void {
2748fn flushInputMember(coff: *Coff, iami: InputArchive.Member.Index) !void {
2749 const member = iami.member(coff);
2750 if (member.file_location.size == 0) return;
2751 assert(!member.flags.is_loaded);
2752 defer member.flags.is_loaded = true;
2753 const comp = coff.base.comp;
2754 const io = comp.io;
2755 const path = member.iai.path(coff);
2756 const file = try path.root_dir.handle.openFile(io, path.sub_path, .{});
2757 defer file.close(io);
2758 var buffer: [4096]u8 = undefined;
2759 var fr = file.reader(io, &buffer);
2760 const offset = member.file_location.offset + @sizeOf(std.coff.ArchiveMemberHeader);
2761 try fr.seekTo(offset);
2762 log.debug("flushInputMember({f}({s}))", .{ path, member.name.toSlice(coff) });
2763 try coff.loadObject(path, member.name.toSlice(coff), &fr, .{
2764 .offset = offset,
2765 .size = member.file_location.size,
2766 });
2767}
2768
2769fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {
27282770 const file_loc = isi.fileLocation(coff);
27292771 if (file_loc.size == 0) return;
27302772 const comp = coff.base.comp;
......@@ -2740,6 +2782,11 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void {
27402782 const si = isi.symbol(coff);
27412783 si.node(coff).writer(&coff.mf, gpa, &nw);
27422784 defer nw.deinit();
2785 log.debug("flushInputSection({f}{f}, {s})", .{
2786 path,
2787 fmtMemberNameString(ii.memberName(coff)),
2788 isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff),
2789 });
27432790 if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)
27442791 return error.EndOfStream;
27452792 si.applyLocationRelocs(coff);
......@@ -3180,12 +3227,12 @@ pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError ||
31803227 }
31813228}
31823229
3183fn fmtArchiveNameString(archiveName: ?[]const u8) std.fmt.Alt(?[]const u8, archiveNameStringEscape) {
3184 return .{ .data = archiveName };
3230fn fmtMemberNameString(memberName: ?[]const u8) std.fmt.Alt(?[]const u8, memberNameStringEscape) {
3231 return .{ .data = memberName };
31853232}
31863233
3187fn archiveNameStringEscape(archiveName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
3188 try w.print("({f})", .{std.zig.fmtString(archiveName orelse return)});
3234fn memberNameStringEscape(memberName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void {
3235 try w.print("({f})", .{std.zig.fmtString(memberName orelse return)});
31893236}
31903237
31913238fn inputSectionHeaderNameSlice(
......@@ -3214,7 +3261,7 @@ fn inputSectionHeaderNameSlice(
32143261fn loadObject(
32153262 coff: *Coff,
32163263 path: std.Build.Cache.Path,
3217 archive_name: ?[]const u8,
3264 member_name: ?[]const u8,
32183265 fr: *Io.File.Reader,
32193266 fl: MappedFile.Node.FileLocation,
32203267) !void {
......@@ -3227,7 +3274,7 @@ fn loadObject(
32273274 const is_archive = coff.isArchive();
32283275 assert(!coff.isObj());
32293276
3230 log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtArchiveNameString(archive_name) });
3277 log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberNameString(member_name) });
32313278
32323279 const header = try r.peekStruct(std.coff.Header, coff.targetEndian());
32333280 if (header.machine != target.toCoffMachine())
......@@ -3271,10 +3318,9 @@ fn loadObject(
32713318 const input = coff.inputs.addOneAssumeCapacity();
32723319 input.* = .{
32733320 .path = path,
3274 .archive_name = if (archive_name) |m| try gpa.dupe(u8, m) else null,
3275 .first_si = .null,
3276 .last_si = .null,
3277 .first_iri = @enumFromInt(coff.input_resolved.items.len),
3321 .member_name = if (member_name) |m| try gpa.dupe(u8, m) else null,
3322 .first_si = @enumFromInt(coff.symbols.items.len),
3323 .end_si = @enumFromInt(coff.symbols.items.len),
32783324 };
32793325
32803326 const string_table = string_table: {
......@@ -3455,6 +3501,7 @@ fn loadObject(
34553501 .offset = fl.offset + section.header.pointer_to_raw_data,
34563502 .size = section.header.size_of_raw_data,
34573503 },
3504 .first_iri = @enumFromInt(coff.input_resolved.items.len),
34583505 };
34593506
34603507 log.debug("loadInputSection({s}) = {d}@{d}", .{ section.name.toSlice(coff), section.si, sym.section_number });
......@@ -3497,8 +3544,11 @@ fn loadObject(
34973544
34983545 var symbols: std.ArrayList(Symbol.Index) = .empty;
34993546 try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols);
3547 var num_resolved: u32 = 0;
3548
3549 input.first_si = @enumFromInt(coff.symbols.items.len);
3550 defer input.end_si = @enumFromInt(coff.symbols.items.len);
35003551
3501 const first_si = coff.symbols.items.len;
35023552 var symbol_i: u32 = 0;
35033553 while (symbol_i < header.number_of_symbols) {
35043554 var symbol: std.coff.Symbol = undefined;
......@@ -3619,6 +3669,7 @@ fn loadObject(
36193669 .{name},
36203670 ),
36213671 else => |sn| {
3672 // TODO: Should this use archive name as lib_name as well?
36223673 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name });
36233674 si_slice[0] = global_gop.value_ptr.*;
36243675 const sym = si_slice[0].get(coff);
......@@ -3631,7 +3682,7 @@ fn loadObject(
36313682 const other_ii = isi.input(coff);
36323683 err.addNote("first seen in input '{f}{f}'", .{
36333684 other_ii.path(coff).fmtEscapeString(),
3634 fmtArchiveNameString(other_ii.archiveName(coff)),
3685 fmtMemberNameString(other_ii.memberName(coff)),
36353686 });
36363687 },
36373688 .nav, .uav => err.addNote("first seen in module '{s}'", .{
......@@ -3643,12 +3694,8 @@ fn loadObject(
36433694 return error.LinkFailure;
36443695 }
36453696
3646 if (global_gop.found_existing) {
3647 // `input_resolved` allows visting this symbol in this input section's flushMoved,
3648 // as the previously undefined global created earlier will not be in our
3649 // contiguous first / last range.
3650 (try coff.input_resolved.addOne(gpa)).* = si_slice[0];
3651 }
3697 if (global_gop.found_existing)
3698 num_resolved += 1;
36523699
36533700 coff.initInputSectionSymbol(sym, sections[@intCast(@intFromEnum(sn) - 1)].si, symbol.value);
36543701 },
......@@ -3657,11 +3704,6 @@ fn loadObject(
36573704 }
36583705 }
36593706
3660 if (coff.symbols.items.len > first_si) {
3661 input.first_si = @enumFromInt(first_si);
3662 input.last_si = @enumFromInt(coff.symbols.items.len - 1);
3663 }
3664
36653707 const relocation_size = std.coff.Relocation.sizeOf();
36663708 for (sections) |section| {
36673709 if (section.si == .null) continue;
......@@ -3697,6 +3739,38 @@ fn loadObject(
36973739 );
36983740 }
36993741 }
3742
3743 const symbolLessThan = struct {
3744 fn lessThan(ctx: *Coff, lhs: Symbol.Index, rhs: Symbol.Index) bool {
3745 const lhs_sn = @intFromEnum(if (lhs == .null) .UNDEFINED else lhs.get(ctx).section_number);
3746 const rhs_sn = @intFromEnum(if (rhs == .null) .UNDEFINED else rhs.get(ctx).section_number);
3747 if (lhs_sn == rhs_sn) return @intFromEnum(lhs) < @intFromEnum(rhs);
3748 return lhs_sn < rhs_sn;
3749 }
3750 }.lessThan;
3751
3752 std.mem.sortUnstable(Symbol.Index, symbols.items, coff, symbolLessThan);
3753
3754 // Any symbols that we resolved (used to be undefined but are now defined) in this pass need to be
3755 // added to contigous ranges in `input_resolved` so they can be visited in `flushMoved`, as they
3756 // are not part of the contiguous ii.first_si / ii.last_si range.
3757 //
3758 // TODO: Should we just use this array for all symbols in this input? More memory but less get().ni misses in flushMoved
3759 try coff.input_resolved.ensureUnusedCapacity(gpa, num_resolved);
3760 var prev_isi: ?Node.InputSection.Index = null;
3761 for (symbols.items) |si| {
3762 if (si == .null or @intFromEnum(si) >= @intFromEnum(input.end_si)) continue;
3763 const ni = si.get(coff).ni;
3764 if (ni == .none) continue;
3765
3766 const isi = coff.getNode(ni).input_section;
3767 if (prev_isi != isi) {
3768 isi.inputSection(coff).first_iri = @enumFromInt(coff.input_resolved.items.len);
3769 prev_isi = isi;
3770 }
3771
3772 coff.input_resolved.addOneAssumeCapacity().* = si;
3773 }
37003774}
37013775
37023776const ArchiveMemberHeader = struct {
......@@ -3813,6 +3887,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
38133887 var pos = fr.logicalPos();
38143888 const size = try fr.getSize();
38153889 while (pos < size) : (pos = fr.logicalPos()) {
3890 if ((pos & 1) != 0) r.toss(1);
38163891 const header = try r.takeStruct(std.coff.ArchiveMemberHeader, target_endian);
38173892 const res = try parseArchiveMemberHeader(diags, path, &header, opt_longnames);
38183893
......@@ -3891,7 +3966,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
38913966 coff.input_archive_members.addOneAssumeCapacity().* = .{
38923967 .iai = iai,
38933968 .name = undefined,
3894 .is_import = undefined,
3969 .flags = undefined,
38953970 .file_location = .{
38963971 .offset = member_offset,
38973972 .size = undefined,
......@@ -3952,7 +4027,10 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
39524027 const member_sig = try r.peek(4);
39534028 const machine = std.mem.readInt(u16, member_sig[0..2], target_endian);
39544029 const sig = std.mem.readInt(u16, member_sig[2..4], target_endian);
3955 member.is_import = machine == @intFromEnum(std.coff.IMAGE.FILE.MACHINE.UNKNOWN) and sig == 0xffff;
4030 member.flags = .{
4031 .is_import = machine == @intFromEnum(std.coff.IMAGE.FILE.MACHINE.UNKNOWN) and sig == 0xffff,
4032 .is_loaded = false,
4033 };
39564034 member.file_location.size = res.size;
39574035
39584036 log.debug("verifyArchiveMember({s}) = 0x{x}+{x}", .{
......@@ -3961,7 +4039,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
39614039 member.file_location.size,
39624040 });
39634041
3964 if (member.is_import) {
4042 if (member.flags.is_import) {
39654043 const import_header = try r.peekStruct(std.coff.ImportHeader, target_endian);
39664044 // TODO: Validate import table header fields
39674045 // TODO: Use this result in flushGlobal
......@@ -4356,13 +4434,13 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
43564434 // TODO: We could report the name here if we interned it in loadObject
43574435 err.addNote("referenced internally by input '{f}{f}'", .{
43584436 other_ii.path(coff).fmtEscapeString(),
4359 fmtArchiveNameString(other_ii.archiveName(coff)),
4437 fmtMemberNameString(other_ii.memberName(coff)),
43604438 });
43614439 } else {
43624440 err.addNote("referenced by input symbol '{s}' from '{f}{f}'", .{
43634441 loc_sym.gmi.globalName(coff).name.toSlice(coff),
43644442 other_ii.path(coff).fmtEscapeString(),
4365 fmtArchiveNameString(other_ii.archiveName(coff)),
4443 fmtMemberNameString(other_ii.memberName(coff)),
43664444 });
43674445 }
43684446 },
......@@ -4478,21 +4556,32 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
44784556 };
44794557 break :task;
44804558 }
4559 if (coff.pending_input) |pending_iami| {
4560 // TODO: Prog node?
4561 coff.flushInputMember(pending_iami) catch |err| switch (err) {
4562 error.OutOfMemory => return error.OutOfMemory,
4563 else => |e| return comp.link_diags.fail(
4564 "linker failed to archive member: {t}",
4565 .{e},
4566 ),
4567 };
4568 coff.pending_input = null;
4569 break :task;
4570 }
44814571 if (coff.global_pending_index < coff.globals.count()) {
44824572 const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index);
4483 coff.global_pending_index += 1;
44844573 const sub_prog_node = coff.synth_prog_node.start(
44854574 gmi.globalName(coff).name.toSlice(coff),
44864575 0,
44874576 );
44884577 defer sub_prog_node.end();
4489 coff.flushGlobal(gmi) catch |err| switch (err) {
4578 if (coff.flushGlobal(gmi) catch |err| switch (err) {
44904579 else => |e| return e,
44914580 error.MappedFileIo => return comp.link_diags.fail(
44924581 "linker failed to lower constant: {t}",
44934582 .{coff.mf.io_err.?},
44944583 ),
4495 };
4584 }) coff.global_pending_index += 1;
44964585 break :task;
44974586 }
44984587 var lazy_it = coff.lazy.iterator();
......@@ -4547,7 +4636,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
45474636 }
45484637 // TODO: Idle task for flushing obj into lib?
45494638 if (coff.input_section_pending_index < coff.input_sections.items.len) {
4550 const isi: Node.InputSectionIndex = @enumFromInt(coff.input_section_pending_index);
4639 const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index);
45514640 coff.input_section_pending_index += 1;
45524641 const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff)));
45534642 defer sub_prog_node.end();
......@@ -4559,7 +4648,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
45594648 .{
45604649 isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff),
45614650 ii.path(coff).fmtEscapeString(),
4562 fmtArchiveNameString(ii.archiveName(coff)),
4651 fmtMemberNameString(ii.memberName(coff)),
45634652 e,
45644653 },
45654654 );
......@@ -4629,9 +4718,10 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
46294718 }
46304719 }
46314720 if (coff.pending_uavs.count() > 0) return true;
4721 if (coff.pending_input != null) return true;
46324722 if (coff.globals.count() > coff.global_pending_index) return true;
4633 if (coff.symbol_table.pending.count() > 0) return true;
46344723 for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;
4724 if (coff.symbol_table.pending.count() > 0) return true;
46354725 if (coff.input_sections.items.len > coff.input_section_pending_index) return true;
46364726 if (coff.mf.updates.items.len > 0) return true;
46374727 if (coff.pending_members.count() > 0) return true;
......@@ -4655,7 +4745,7 @@ fn idleProgNode(
46554745 const ii = isi.input(coff);
46564746 break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{
46574747 ii.path(coff).fmtEscapeString(),
4658 fmtArchiveNameString(ii.archiveName(coff)),
4748 fmtMemberNameString(ii.memberName(coff)),
46594749 coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff),
46604750 }) catch &name;
46614751 },
......@@ -4736,7 +4826,7 @@ fn flushUav(
47364826 si.applyLocationRelocs(coff);
47374827}
47384828
4739fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void {
4829fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
47404830 const comp = coff.base.comp;
47414831 const gpa = comp.gpa;
47424832 const gn = gmi.globalName(coff);
......@@ -4751,7 +4841,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void {
47514841 gn.name,
47524842 );
47534843
4754 return;
4844 return true;
47554845 }
47564846
47574847 if (gn.lib_name.toSlice(coff)) |lib_name| {
......@@ -4911,15 +5001,26 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void {
49115001 sym.rva = coff.computeNodeRva(sym.ni);
49125002 si.applyLocationRelocs(coff);
49135003 } else {
5004 if (coff.input_archive_symbol_indices.get(gn.name)) |index| {
5005 var iter: InputArchive.Member.Symbol.Index = index.first;
5006 while (true) {
5007 const archive_sym = &coff.input_archive_symbols.items[@intFromEnum(iter)];
5008
5009 // TODO: This implies that loading an input failing is not fatal
5010 if (!coff.input_archive_members.items[@intFromEnum(archive_sym.iami)].flags.is_loaded) {
5011 coff.pending_input = archive_sym.iami;
5012 return false;
5013 }
49145014
4915 // TODO: Check if not defined, and if in an input member
4916 // TODO: If so, queue a loadObject for that member
4917 // TODO: Return a value indicating to retry this flushGlobal
4918 // TODO: The loadObject idle task should be before the flushGlobal idle task
4919 //
4920 // TODO: Check if we can get flushGlobal before prelink, that would cause a problem
5015 if (archive_sym.next == iter) break;
5016 iter = archive_sym.next;
5017 }
5018 }
49215019
5020 // TODO: Check if we can get flushGlobal before prelink, that would cause a problem
49225021 }
5022
5023 return true;
49235024}
49245025
49255026fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
......@@ -5040,14 +5141,14 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
50405141
50415142 {
50425143 var si = ii.firstSymbol(coff);
5043 const last_si = ii.lastSymbol(coff);
5044 while (@intFromEnum(si) <= @intFromEnum(last_si)) : (si = si.next()) {
5144 const end_si = ii.endSymbol(coff);
5145 while (@intFromEnum(si) < @intFromEnum(end_si)) : (si = si.next()) {
50455146 if (si.get(coff).ni != ni) continue;
50465147 si.flushMoved(coff);
50475148 }
50485149 }
50495150
5050 for (coff.input_resolved.items[@intFromEnum(ii.firstResolvedGlobal(coff))..]) |si| {
5151 for (coff.input_resolved.items[@intFromEnum(isi.firstResolvedSymbol(coff))..]) |si| {
50515152 if (si.get(coff).ni != ni) break;
50525153 si.flushMoved(coff);
50535154 }
......@@ -5606,7 +5707,7 @@ pub fn printNode(
56065707 const ii = isi.input(coff);
56075708 try w.print("({f}{f}, {s})", .{
56085709 ii.path(coff).fmtEscapeString(),
5609 fmtArchiveNameString(ii.archiveName(coff)),
5710 fmtMemberNameString(ii.memberName(coff)),
56105711 coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff),
56115712 });
56125713 },