| ... | ... | @@ -737,7 +737,7 @@ pub const Symbol = struct { |
| 737 | 737 | value: union { |
| 738 | 738 | /// For generated symbols, this is their size |
| 739 | 739 | size: u32, |
| 740 | | /// For globals from input sections, this is the offset within the input section |
| 740 | /// For symbols from input sections, this is the offset within the input section |
| 741 | 741 | input_offset: u32, |
| 742 | 742 | }, |
| 743 | 743 | /// Relocations contained within this symbol |
| ... | ... | @@ -1322,11 +1322,15 @@ pub fn deinit(coff: *Coff) void { |
| 1322 | 1322 | const gpa = coff.base.comp.gpa; |
| 1323 | 1323 | coff.mf.deinit(gpa); |
| 1324 | 1324 | coff.nodes.deinit(gpa); |
| 1325 | coff.pending_members.deinit(gpa); |
| 1326 | coff.lib_string_table.deinit(gpa); |
| 1325 | 1327 | coff.long_names_table.entries.deinit(gpa); |
| 1326 | 1328 | coff.import_table.entries.deinit(gpa); |
| 1327 | 1329 | coff.export_table.entries.deinit(gpa); |
| 1328 | 1330 | coff.symbol_table.strings.deinit(gpa); |
| 1329 | 1331 | coff.symbol_table.pending.deinit(gpa); |
| 1332 | coff.inputs.deinit(gpa); |
| 1333 | coff.input_sections.deinit(gpa); |
| 1330 | 1334 | coff.strings.deinit(gpa); |
| 1331 | 1335 | coff.string_bytes.deinit(gpa); |
| 1332 | 1336 | coff.section_table.deinit(gpa); |
| ... | ... | @@ -2145,6 +2149,13 @@ fn initSymbolAssumeCapacity(coff: *Coff) !Symbol.Index { |
| 2145 | 2149 | return si; |
| 2146 | 2150 | } |
| 2147 | 2151 | |
| 2152 | fn initInputSectionSymbol(coff: *Coff, sym: *Symbol, section_si: Symbol.Index, value: u32) void { |
| 2153 | const section_sym = section_si.get(coff); |
| 2154 | sym.ni = section_sym.ni; |
| 2155 | sym.value = .{ .input_offset = value }; |
| 2156 | sym.section_number = section_sym.section_number; |
| 2157 | } |
| 2158 | |
| 2148 | 2159 | fn getOrPutString(coff: *Coff, string: []const u8) !String { |
| 2149 | 2160 | try coff.ensureUnusedStringCapacity(string.len); |
| 2150 | 2161 | return coff.getOrPutStringAssumeCapacity(string); |
| ... | ... | @@ -2240,7 +2251,12 @@ fn getOrPutGlobalSymbol( |
| 2240 | 2251 | } |
| 2241 | 2252 | |
| 2242 | 2253 | pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index { |
| 2243 | | return (try coff.getOrPutGlobalSymbol(opts)).value_ptr.*; |
| 2254 | const gop = try coff.getOrPutGlobalSymbol(opts); |
| 2255 | if (gop.found_existing) { |
| 2256 | // TODO: Need to know if this is an export or extern, add to opts |
| 2257 | } |
| 2258 | |
| 2259 | return gop.value_ptr.*; |
| 2244 | 2260 | } |
| 2245 | 2261 | |
| 2246 | 2262 | pub fn pendingSymbolTableEntry(coff: *Coff, si: Symbol.Index) !void { |
| ... | ... | @@ -2657,6 +2673,10 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void { |
| 2657 | 2673 | if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size) |
| 2658 | 2674 | return error.EndOfStream; |
| 2659 | 2675 | si.applyLocationRelocs(coff); |
| 2676 | |
| 2677 | // TODO: Problem is that if the sym is first seen as undef, it's si is in the range of the section |
| 2678 | // that wants that symbol. but when the section that contains it is moved, the iteration doesn't see |
| 2679 | // that symbol. |
| 2660 | 2680 | } |
| 2661 | 2681 | |
| 2662 | 2682 | fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !Symbol.Index { |
| ... | ... | @@ -3267,7 +3287,7 @@ fn loadObject( |
| 3267 | 3287 | if (section.header.flags.LNK_REMOVE or |
| 3268 | 3288 | section.header.flags.MEM_DISCARDABLE) |
| 3269 | 3289 | { |
| 3270 | | // TODO: Merge .debug$* sections and output to PDB |
| 3290 | // TODO: Convert .debug$* sections into PDB |
| 3271 | 3291 | continue; |
| 3272 | 3292 | } |
| 3273 | 3293 | |
| ... | ... | @@ -3340,8 +3360,6 @@ fn loadObject( |
| 3340 | 3360 | // This will be necessary if we do the equivalent of /Gy for compiler-rt |
| 3341 | 3361 | return diags.failParse(path, "TODO handle COMDAT sections in input objects", .{}); |
| 3342 | 3362 | |
| 3343 | | log.debug("loadInputSection({s})", .{section.name.toSlice(coff)}); |
| 3344 | | |
| 3345 | 3363 | const parent_osmi = try coff.objectSectionMapIndex( |
| 3346 | 3364 | section.name, |
| 3347 | 3365 | coff.mf.flags.block_size, |
| ... | ... | @@ -3372,6 +3390,7 @@ fn loadObject( |
| 3372 | 3390 | }, |
| 3373 | 3391 | }; |
| 3374 | 3392 | |
| 3393 | log.debug("loadInputSection({s}) = {d}@{d}", .{ section.name.toSlice(coff), section.si, sym.section_number }); |
| 3375 | 3394 | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| 3376 | 3395 | } |
| 3377 | 3396 | |
| ... | ... | @@ -3428,89 +3447,141 @@ fn loadObject( |
| 3428 | 3447 | const name = std.mem.sliceTo(if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: { |
| 3429 | 3448 | const index = std.mem.readInt(u32, symbol.name[4..], target_endian); |
| 3430 | 3449 | if (index >= string_table.len) |
| 3431 | | return diags.failParse(path, "bad string offset for symbol {d}", .{symbol_ix}); |
| 3450 | return diags.failParse(path, "bad string offset for symbol 0x{x}", .{symbol_ix}); |
| 3432 | 3451 | break :name string_table[index..]; |
| 3433 | 3452 | } else &symbol.name, 0); |
| 3434 | 3453 | |
| 3435 | | const si = symbols.addOneAssumeCapacity(); |
| 3436 | | si.* = .null; |
| 3437 | | |
| 3438 | | switch (symbol.section_number) { |
| 3439 | | .UNDEFINED, .ABSOLUTE, .DEBUG => continue, |
| 3440 | | else => switch (symbol.storage_class) { |
| 3441 | | .STATIC => if (symbol.value == 0 and symbol.type == std.coff.SymType{ |
| 3442 | | .complex_type = .NULL, |
| 3443 | | .base_type = .NULL, |
| 3444 | | }) { |
| 3445 | | if (symbol.number_of_aux_symbols != 1) |
| 3446 | | return diags.failParse(path, "invalid number of aux symbols for section {d}: {d}", .{ |
| 3447 | | symbol_ix, |
| 3448 | | symbol.number_of_aux_symbols, |
| 3449 | | }); |
| 3450 | | |
| 3451 | | var section_def: std.coff.SectionDefinition = undefined; |
| 3452 | | @memcpy(std.mem.asBytes(&section_def)[0..symbol_size], try r.peek(symbol_size)); |
| 3453 | | if (target_endian != native_endian) |
| 3454 | | std.mem.byteSwapAllFields(std.coff.SectionDefinition, &section_def); |
| 3455 | | |
| 3456 | | // TODO: Extract the COMDAT section info |
| 3454 | const si_slice = symbols.addManyAsSliceAssumeCapacity(1 + symbol.number_of_aux_symbols); |
| 3455 | @memset(si_slice, .null); |
| 3457 | 3456 | |
| 3458 | | if (section_def.number > sections.len) |
| 3459 | | return diags.failParse( |
| 3460 | | path, |
| 3461 | | "section symbol for '{s}' contained an out of bounds section number: {d}", |
| 3462 | | .{ name, section_def.number }, |
| 3463 | | ); |
| 3464 | | |
| 3465 | | // It's valid for this to not match the symbol's section number (ie. .drectve sets this) |
| 3466 | | if (section_def.number == 0) |
| 3467 | | continue; |
| 3457 | defer log.debug("loadInputSymbol({s}, 0x{x}) = {d}@{d}", .{ |
| 3458 | name, |
| 3459 | symbol.value, |
| 3460 | si_slice[0], |
| 3461 | if (si_slice[0] == .null) .UNDEFINED else si_slice[0].get(coff).section_number, |
| 3462 | }); |
| 3468 | 3463 | |
| 3469 | | const section = &sections[section_def.number - 1]; |
| 3470 | | if (section_def.number_of_relocations != section.header.number_of_relocations) |
| 3471 | | return diags.failParse( |
| 3472 | | path, |
| 3473 | | "section symbol for '{s}' relocation count did not match section header: {d} vs {d}", |
| 3474 | | .{ name, section_def.number_of_relocations, section.header.number_of_relocations }, |
| 3475 | | ); |
| 3464 | if (is_archive) { |
| 3465 | if (symbol.storage_class == .EXTERNAL) |
| 3466 | try coff.ensureMemberSymbol(mi, coff.getOrPutStringAssumeCapacity(name)); |
| 3476 | 3467 | |
| 3477 | | if (section_def.number_of_linenumbers != section.header.number_of_linenumbers) |
| 3478 | | return diags.failParse( |
| 3479 | | path, |
| 3480 | | "section symbol for '{s}' line number count did not match section header: {d} vs {d}", |
| 3481 | | .{ name, section_def.number_of_linenumbers, section.header.number_of_linenumbers }, |
| 3482 | | ); |
| 3468 | continue; |
| 3469 | } |
| 3483 | 3470 | |
| 3484 | | si.* = section.si; |
| 3485 | | continue; |
| 3471 | switch (symbol.storage_class) { |
| 3472 | .STATIC, .LABEL => |storage_class| switch (symbol.section_number) { |
| 3473 | .UNDEFINED, .DEBUG, .ABSOLUTE => { |
| 3474 | // TODO: Do we need to do anything with @feat.00? |
| 3475 | // https://llvm.org/doxygen/namespacellvm_1_1COFF.html#aeffa16735e18df727a173beaf748c392 |
| 3476 | }, |
| 3477 | else => |sn| { |
| 3478 | // Section symbol |
| 3479 | if (storage_class == .STATIC and |
| 3480 | symbol.value == 0 and |
| 3481 | symbol.type == std.coff.SymType{ |
| 3482 | .complex_type = .NULL, |
| 3483 | .base_type = .NULL, |
| 3484 | } and |
| 3485 | symbol.number_of_aux_symbols > 0) |
| 3486 | { |
| 3487 | if (symbol.number_of_aux_symbols > 1) |
| 3488 | return diags.failParse(path, "invalid number of aux symbols for section 0x{x}: {d}", .{ |
| 3489 | symbol_ix, |
| 3490 | symbol.number_of_aux_symbols, |
| 3491 | }); |
| 3492 | |
| 3493 | var section_def: std.coff.SectionDefinition = undefined; |
| 3494 | @memcpy(std.mem.asBytes(&section_def)[0..symbol_size], try r.peek(symbol_size)); |
| 3495 | if (target_endian != native_endian) |
| 3496 | std.mem.byteSwapAllFields(std.coff.SectionDefinition, &section_def); |
| 3497 | |
| 3498 | // TODO: Extract the COMDAT section info |
| 3499 | |
| 3500 | if (section_def.number > sections.len) |
| 3501 | return diags.failParse( |
| 3502 | path, |
| 3503 | "section symbol for '{s}' contained an out of bounds section number: 0x{x}", |
| 3504 | .{ name, section_def.number }, |
| 3505 | ); |
| 3506 | |
| 3507 | // It's valid for this to not match the symbol's section number (ie. .drectve sets this) |
| 3508 | if (section_def.number == 0) |
| 3509 | continue; |
| 3510 | |
| 3511 | const section = &sections[section_def.number - 1]; |
| 3512 | if (section_def.number_of_relocations != section.header.number_of_relocations) |
| 3513 | return diags.failParse( |
| 3514 | path, |
| 3515 | "section symbol for '{s}' relocation count did not match section header: {d} vs {d}", |
| 3516 | .{ name, section_def.number_of_relocations, section.header.number_of_relocations }, |
| 3517 | ); |
| 3518 | |
| 3519 | if (section_def.number_of_linenumbers != section.header.number_of_linenumbers) |
| 3520 | return diags.failParse( |
| 3521 | path, |
| 3522 | "section symbol for '{s}' line number count did not match section header: {d} vs {d}", |
| 3523 | .{ name, section_def.number_of_linenumbers, section.header.number_of_linenumbers }, |
| 3524 | ); |
| 3525 | |
| 3526 | @memset(si_slice, section.si); |
| 3527 | } else { |
| 3528 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 3529 | si_slice[0] = coff.addSymbolAssumeCapacity(); |
| 3530 | const sym = si_slice[0].get(coff); |
| 3531 | coff.initInputSectionSymbol(sym, sections[@intCast(@intFromEnum(sn) - 1)].si, symbol.value); |
| 3532 | } |
| 3486 | 3533 | }, |
| 3487 | | .EXTERNAL => {}, |
| 3488 | | else => continue, |
| 3489 | 3534 | }, |
| 3535 | .EXTERNAL => switch (symbol.section_number) { |
| 3536 | .ABSOLUTE => return diags.failParse( |
| 3537 | path, |
| 3538 | "TODO unhandled external absolute symbol: '{s}'", |
| 3539 | .{name}, |
| 3540 | ), |
| 3541 | .DEBUG => return diags.failParse( |
| 3542 | path, |
| 3543 | "unexpected external symbol in DEBUG section: '{s}'", |
| 3544 | .{name}, |
| 3545 | ), |
| 3546 | else => |sn| { |
| 3547 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name }); |
| 3548 | si_slice[0] = global_gop.value_ptr.*; |
| 3549 | |
| 3550 | const sym = si_slice[0].get(coff); |
| 3551 | if (sn != .UNDEFINED) { |
| 3552 | if (global_gop.found_existing and sym.ni != .none) { |
| 3553 | // TODO: Need corresponding logic later if we try to make a global already defined by an input |
| 3554 | |
| 3555 | var err = try diags.addErrorWithNotes(2); |
| 3556 | try err.addMsg("multiple definitions of '{s}'", .{name}); |
| 3557 | switch (coff.getNode(sym.ni)) { |
| 3558 | .input_section => |isi| { |
| 3559 | const other_ii = isi.input(coff); |
| 3560 | err.addNote("first seen in input '{f}{f}'", .{ |
| 3561 | other_ii.path(coff).fmtEscapeString(), |
| 3562 | fmtArchiveNameString(other_ii.archiveName(coff)), |
| 3563 | }); |
| 3564 | }, |
| 3565 | .nav, .uav => err.addNote("first seen in module '{s}'", .{ |
| 3566 | comp.zcu.?.root_mod.fully_qualified_name, |
| 3567 | }), |
| 3568 | else => unreachable, |
| 3569 | } |
| 3570 | err.addNote("defined again in input '{f}'", .{path}); |
| 3571 | return error.LinkFailure; |
| 3572 | } |
| 3573 | |
| 3574 | // TODO: Here if we *were* undefined we want to associate this symbol now with this section for |
| 3575 | // the flushMoved iteration |
| 3576 | |
| 3577 | coff.initInputSectionSymbol(sym, sections[@intCast(@intFromEnum(sn) - 1)].si, symbol.value); |
| 3578 | } else if (!global_gop.found_existing) { |
| 3579 | sym.value = .{ .size = symbol.value }; |
| 3580 | } |
| 3581 | }, |
| 3582 | }, |
| 3583 | else => {}, |
| 3490 | 3584 | } |
| 3491 | | |
| 3492 | | if (is_archive) { |
| 3493 | | try coff.ensureMemberSymbol(mi, coff.getOrPutStringAssumeCapacity(name)); |
| 3494 | | continue; |
| 3495 | | } |
| 3496 | | |
| 3497 | | // Section numbers are 1-based here |
| 3498 | | if (@intFromEnum(symbol.section_number) <= 0 or @intFromEnum(symbol.section_number) > sections.len) |
| 3499 | | return diags.failParse(path, "bad section number {d} for '{s}'", .{ symbol.section_number, name }); |
| 3500 | | |
| 3501 | | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name }); |
| 3502 | | // TODO: Support weak symbols |
| 3503 | | if (global_gop.found_existing) |
| 3504 | | return diags.failParse(path, "multiple definitions of '{s}'", .{name}); |
| 3505 | | si.* = global_gop.value_ptr.*; |
| 3506 | | |
| 3507 | | const section = sections[@intCast(@intFromEnum(symbol.section_number) - 1)]; |
| 3508 | | const section_sym = section.si.get(coff); |
| 3509 | | |
| 3510 | | const sym = si.get(coff); |
| 3511 | | sym.ni = section_sym.ni; |
| 3512 | | sym.value = .{ .input_offset = symbol.value }; |
| 3513 | | sym.section_number = section_sym.section_number; |
| 3514 | 3585 | } |
| 3515 | 3586 | |
| 3516 | 3587 | if (coff.symbols.items.len > first_si) { |
| ... | ... | @@ -3539,16 +3610,17 @@ fn loadObject( |
| 3539 | 3610 | if (reloc.symbol_table_index >= symbols.items.len) |
| 3540 | 3611 | return diags.failParse( |
| 3541 | 3612 | path, |
| 3542 | | "relocation {d} in section '{s}' targets invalid symbol index {d}", |
| 3613 | "relocation 0x{x} in section '{s}' targets invalid symbol index 0x{x}", |
| 3543 | 3614 | .{ reloc_i, section.name.toSlice(coff), reloc.symbol_table_index }, |
| 3544 | 3615 | ); |
| 3545 | 3616 | |
| 3617 | assert(symbols.items[reloc.symbol_table_index] != .null); |
| 3546 | 3618 | try coff.addReloc( |
| 3547 | 3619 | section.si, |
| 3548 | 3620 | reloc.virtual_address - section.header.virtual_address, |
| 3549 | 3621 | symbols.items[reloc.symbol_table_index], |
| 3550 | 3622 | .pending, |
| 3551 | | @bitCast(reloc.type), // TODO: Checks on this cast? |
| 3623 | @bitCast(reloc.type), |
| 3552 | 3624 | ); |
| 3553 | 3625 | } |
| 3554 | 3626 | } |
| ... | ... | @@ -3602,6 +3674,8 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { |
| 3602 | 3674 | pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { |
| 3603 | 3675 | _ = coff; |
| 3604 | 3676 | _ = prog_node; |
| 3677 | |
| 3678 | log.debug("prelink()", .{}); |
| 3605 | 3679 | } |
| 3606 | 3680 | |
| 3607 | 3681 | pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { |
| ... | ... | @@ -3888,6 +3962,126 @@ fn flushImplib( |
| 3888 | 3962 | try file_writer.interface.flush(); |
| 3889 | 3963 | } |
| 3890 | 3964 | |
| 3965 | fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 3966 | const comp = coff.base.comp; |
| 3967 | const gpa = comp.gpa; |
| 3968 | const max_notes = 4; |
| 3969 | |
| 3970 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; |
| 3971 | for (coff.relocs.items, 0..) |reloc, reloc_i| { |
| 3972 | const target_sym = reloc.target.get(coff); |
| 3973 | switch (target_sym.ni) { |
| 3974 | .none => { |
| 3975 | assert(target_sym.gmi != .none); |
| 3976 | (try undef_indices.addOne(gpa)).* = @intCast(reloc_i); |
| 3977 | }, |
| 3978 | else => continue, |
| 3979 | } |
| 3980 | } |
| 3981 | |
| 3982 | if (undef_indices.items.len == 0) return; |
| 3983 | |
| 3984 | const undefLessThan = struct { |
| 3985 | fn lessThan(ctx: *const Coff, lhs: u32, rhs: u32) bool { |
| 3986 | const reloc_l = &ctx.relocs.items[lhs]; |
| 3987 | const reloc_r = &ctx.relocs.items[rhs]; |
| 3988 | if (reloc_l.target == reloc_r.target) |
| 3989 | return @intFromEnum(reloc_l.loc) < @intFromEnum(reloc_r.loc) |
| 3990 | else |
| 3991 | return @intFromEnum(reloc_l.target) < @intFromEnum(reloc_r.target); |
| 3992 | } |
| 3993 | }.lessThan; |
| 3994 | |
| 3995 | std.mem.sortUnstable(u32, undef_indices.items, coff, undefLessThan); |
| 3996 | |
| 3997 | var start_i: usize = 0; |
| 3998 | var num_unique_references: usize = 1; |
| 3999 | for (undef_indices.items[0..], 0..) |reloc_i, i| { |
| 4000 | const target = coff.relocs.items[undef_indices.items[start_i]].target; |
| 4001 | if (target != coff.relocs.items[reloc_i].target or i == undef_indices.items.len - 1) { |
| 4002 | defer { |
| 4003 | start_i = i; |
| 4004 | num_unique_references = 1; |
| 4005 | } |
| 4006 | |
| 4007 | const num_references = i - start_i; |
| 4008 | const num_notes = |
| 4009 | @min(max_notes, num_unique_references) + |
| 4010 | @intFromBool(num_unique_references > max_notes); |
| 4011 | |
| 4012 | var err = try comp.link_diags.addErrorWithNotes(num_notes); |
| 4013 | const target_sym = target.get(coff); |
| 4014 | try err.addMsg("undefined symbol: {s}", .{target_sym.gmi.globalName(coff).name.toSlice(coff)}); |
| 4015 | |
| 4016 | var prev_loc_si: Symbol.Index = .null; |
| 4017 | for (undef_indices.items[start_i..][0..num_references]) |reference_i| { |
| 4018 | if (err.note_slot == num_notes) break; |
| 4019 | |
| 4020 | const loc_si = coff.relocs.items[reference_i].loc; |
| 4021 | if (loc_si == prev_loc_si) continue; |
| 4022 | defer prev_loc_si = loc_si; |
| 4023 | |
| 4024 | const loc_sym = loc_si.get(coff); |
| 4025 | switch (coff.getNode(loc_sym.ni)) { |
| 4026 | .input_section => |isi| { |
| 4027 | const other_ii = isi.input(coff); |
| 4028 | if (loc_sym.gmi == .none) { |
| 4029 | // TODO: We could report the name here if we interned it in loadObject |
| 4030 | err.addNote("referenced internally by input '{f}{f}'", .{ |
| 4031 | other_ii.path(coff).fmtEscapeString(), |
| 4032 | fmtArchiveNameString(other_ii.archiveName(coff)), |
| 4033 | }); |
| 4034 | } else { |
| 4035 | err.addNote("referenced by input symbol '{s}' from '{f}{f}'", .{ |
| 4036 | loc_sym.gmi.globalName(coff).name.toSlice(coff), |
| 4037 | other_ii.path(coff).fmtEscapeString(), |
| 4038 | fmtArchiveNameString(other_ii.archiveName(coff)), |
| 4039 | }); |
| 4040 | } |
| 4041 | }, |
| 4042 | .global => |gmi| err.addNote("referenced by '{s}' in module '{s}'", .{ |
| 4043 | gmi.globalName(coff).name.toSlice(coff), |
| 4044 | comp.zcu.?.root_mod.fully_qualified_name, |
| 4045 | }), |
| 4046 | inline .nav, |
| 4047 | .uav, |
| 4048 | .lazy_code, |
| 4049 | .lazy_const_data, |
| 4050 | => |val, tag| { |
| 4051 | err.addNote("referenced by '{f}'", .{ |
| 4052 | format: switch (tag) { |
| 4053 | .nav => { |
| 4054 | const ip = &comp.zcu.?.intern_pool; |
| 4055 | break :format ip.getNav(val.navIndex(coff)).fqn.fmt(ip); |
| 4056 | }, |
| 4057 | .uav => Value.fromInterned(val.uavValue(coff)).fmtValue(.{ |
| 4058 | .zcu = coff.base.comp.zcu.?, |
| 4059 | .tid = tid, |
| 4060 | }), |
| 4061 | inline .lazy_code, .lazy_const_data => Type.fromInterned(val.lazySymbol(coff).ty).fmt(.{ |
| 4062 | .zcu = coff.base.comp.zcu.?, |
| 4063 | .tid = tid, |
| 4064 | }), |
| 4065 | else => unreachable, |
| 4066 | }, |
| 4067 | }); |
| 4068 | }, |
| 4069 | else => unreachable, |
| 4070 | } |
| 4071 | } |
| 4072 | |
| 4073 | if (num_unique_references > max_notes) |
| 4074 | err.addNote("referenced {d} more times", .{num_references - max_notes}); |
| 4075 | } else if (i != start_i and |
| 4076 | coff.relocs.items[undef_indices.items[i - 1]].loc != coff.relocs.items[undef_indices.items[i]].loc) |
| 4077 | { |
| 4078 | num_unique_references += 1; |
| 4079 | } |
| 4080 | } |
| 4081 | |
| 4082 | return error.LinkFailure; |
| 4083 | } |
| 4084 | |
| 3891 | 4085 | pub fn flush( |
| 3892 | 4086 | coff: *Coff, |
| 3893 | 4087 | arena: std.mem.Allocator, |
| ... | ... | @@ -3897,6 +4091,7 @@ pub fn flush( |
| 3897 | 4091 | _ = arena; |
| 3898 | 4092 | _ = prog_node; |
| 3899 | 4093 | while (try coff.idle(tid)) {} |
| 4094 | try coff.reportUndefs(tid); |
| 3900 | 4095 | |
| 3901 | 4096 | const comp = coff.base.comp; |
| 3902 | 4097 | |
| ... | ... | @@ -4132,7 +4327,7 @@ fn idleProgNode( |
| 4132 | 4327 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ |
| 4133 | 4328 | ii.path(coff).fmtEscapeString(), |
| 4134 | 4329 | fmtArchiveNameString(ii.archiveName(coff)), |
| 4135 | | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 4330 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), |
| 4136 | 4331 | }) catch &name; |
| 4137 | 4332 | }, |
| 4138 | 4333 | .global => |gmi| gmi.globalName(coff).name.toSlice(coff), |
| ... | ... | @@ -4386,6 +4581,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { |
| 4386 | 4581 | coff.nodes.appendAssumeCapacity(.{ .global = gmi }); |
| 4387 | 4582 | sym.rva = coff.computeNodeRva(sym.ni); |
| 4388 | 4583 | si.applyLocationRelocs(coff); |
| 4584 | } else { |
| 4585 | |
| 4586 | // TODO: If no .ni, report symbol not found - or should it be right when it's added as a global if we don't know about it? |
| 4587 | |
| 4389 | 4588 | } |
| 4390 | 4589 | } |
| 4391 | 4590 | |
| ... | ... | @@ -4505,6 +4704,10 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 4505 | 4704 | const ii = isi.input(coff); |
| 4506 | 4705 | var si = ii.firstSymbol(coff); |
| 4507 | 4706 | const last_si = ii.lastSymbol(coff); |
| 4707 | |
| 4708 | // TODO: This iteration doesn't visit symbols that were added first |
| 4709 | // in the range of another section (as undef). |
| 4710 | |
| 4508 | 4711 | while (@intFromEnum(si) <= @intFromEnum(last_si)) : (si = si.next()) { |
| 4509 | 4712 | if (si.get(coff).ni != ni) continue; |
| 4510 | 4713 | si.flushMoved(coff); |
| ... | ... | @@ -5065,7 +5268,7 @@ pub fn printNode( |
| 5065 | 5268 | try w.print("({f}{f}, {s})", .{ |
| 5066 | 5269 | ii.path(coff).fmtEscapeString(), |
| 5067 | 5270 | fmtArchiveNameString(ii.archiveName(coff)), |
| 5068 | | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 5271 | coff.getNode(isi.symbol(coff).node(coff).parent(&coff.mf)).object_section.name(coff).toSlice(coff), |
| 5069 | 5272 | }); |
| 5070 | 5273 | }, |
| 5071 | 5274 | .import_lookup_table, |