authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-09-19 13:25:56-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-09-19 13:25:56-04:00
log96c654941c98017e9e59fe38e06d9a334fb6c80c
tree20ba7df157bc8a6618a85f62e84c4dd8e1523152
parent5a4fda7e36e9862d6c0fd8fe15d7bd5cefa2f6e9

Coff: rework global creation to avoid invalidating strings that were themselves used as arguments


1 files changed, 156 insertions(+), 119 deletions(-)

src/link/Coff.zig+156-119
...@@ -278,7 +278,7 @@ pub const Node = union(enum) {...@@ -278,7 +278,7 @@ pub const Node = union(enum) {
278 return coff.globals.values()[gmi.unwrap().?].si;278 return coff.globals.values()[gmi.unwrap().?].si;
279 }279 }
280280
281 pub fn libName(gmi: GlobalMapIndex, coff: *const Coff) String.Optional {281 pub fn libName(gmi: GlobalMapIndex, coff: *const Coff) ExternLibName {
282 return coff.globals.values()[gmi.unwrap().?].lib_name;282 return coff.globals.values()[gmi.unwrap().?].lib_name;
283 }283 }
284 };284 };
...@@ -864,7 +864,7 @@ pub const Section = struct {...@@ -864,7 +864,7 @@ pub const Section = struct {
864864
865pub const Global = struct {865pub const Global = struct {
866 si: Symbol.Index,866 si: Symbol.Index,
867 lib_name: String.Optional,867 lib_name: ExternLibName,
868};868};
869869
870pub const WeakExternalStrat = enum(u3) {870pub const WeakExternalStrat = enum(u3) {
...@@ -2781,37 +2781,43 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {...@@ -2781,37 +2781,43 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {
2781 return @fromBackingInt(@intCast(gop.key_ptr.*));2781 return @fromBackingInt(@intCast(gop.key_ptr.*));
2782}2782}
27832783
2784const GlobalOptions = struct {2784const ExternLibName = union(enum) {
2785 name: []const u8,2785 // Symbol can be supplied from anywhere
2786 lib_name: ?[]const u8 = null,2786 any,
2787 type: Symbol.Type = .unknown,2787 // Symbol can be supplied by any LibC input
2788 dll_storage_class: Symbol.DllStorageClass = .default,2788 lib_c,
2789 // Symbol must be supplied by a specific input
2790 explicit: String,
2789};2791};
27902792
2793const FmtExternLibName = struct { coff: *Coff, lib_name: ExternLibName };
2794
2795fn fmtExternLibName(coff: *Coff, lib_name: ExternLibName) std.fmt.Alt(FmtExternLibName, formatExternLibName) {
2796 return .{ .data = .{ .coff = coff, .lib_name = lib_name } };
2797}
2798
2799fn formatExternLibName(data: FmtExternLibName, w: *Io.Writer) Io.Writer.Error!void {
2800 try w.writeAll(switch (data.lib_name) {
2801 .any => "*",
2802 .lib_c => "c",
2803 .explicit => |str| str.toSlice(data.coff),
2804 });
2805}
2806
2791fn getOrPutGlobalSymbol(2807fn getOrPutGlobalSymbol(
2792 coff: *Coff,2808 coff: *Coff,
2793 opts: GlobalOptions,2809 opts: struct {
2810 name: String,
2811 lib_name: ExternLibName = .any,
2812 type: Symbol.Type = .unknown,
2813 dll_storage_class: Symbol.DllStorageClass = .default,
2814 },
2794) !std.array_hash_map.Auto(String, Global).GetOrPutResult {2815) !std.array_hash_map.Auto(String, Global).GetOrPutResult {
2795 const comp = coff.base.comp;2816 const comp = coff.base.comp;
2796 const gpa = comp.gpa;2817 const gpa = comp.gpa;
2797 try coff.symbols.ensureUnusedCapacity(gpa, 1);2818 try coff.symbols.ensureUnusedCapacity(gpa, 1);
27982819
2799 const lib_name: String.Optional = if (opts.lib_name) |lib_name| lib_name: {2820 const sym_gop = try coff.globals.getOrPut(gpa, opts.name);
2800 const is_libc = std.zig.target.isLibCLibName(&comp.root_mod.resolved_target.result, lib_name);
2801 if (is_libc) {
2802 // This is guaranteed by Sema.handleExternLibName
2803 if (!comp.config.link_libc) unreachable;
2804
2805 // TODO: The user has requested this symbol come from libc, but this logic allows
2806 // it to come from anywhere. We need to know what inputs are libc inputs,
2807 // and set a flag to only search them for this symbol.
2808 break :lib_name .none;
2809 }
2810
2811 break :lib_name (try coff.getOrPutString(lib_name)).toOptional();
2812 } else .none;
2813
2814 const sym_gop = try coff.globals.getOrPut(gpa, try coff.getOrPutString(opts.name));
2815 if (!sym_gop.found_existing) {2821 if (!sym_gop.found_existing) {
2816 const si = coff.addSymbolAssumeCapacity();2822 const si = coff.addSymbolAssumeCapacity();
2817 const sym = si.get(coff);2823 const sym = si.get(coff);
...@@ -2820,11 +2826,11 @@ fn getOrPutGlobalSymbol(...@@ -2820,11 +2826,11 @@ fn getOrPutGlobalSymbol(
2820 sym.flags.dll_storage_class = opts.dll_storage_class;2826 sym.flags.dll_storage_class = opts.dll_storage_class;
2821 sym_gop.value_ptr.* = .{2827 sym_gop.value_ptr.* = .{
2822 .si = si,2828 .si = si,
2823 .lib_name = lib_name,2829 .lib_name = opts.lib_name,
2824 };2830 };
2825 coff.synth_prog_node.increaseEstimatedTotalItems(1);2831 coff.synth_prog_node.increaseEstimatedTotalItems(1);
28262832
2827 log.debug("globalSymbol({s}, {?s}) = {d}", .{ opts.name, opts.lib_name, si });2833 log.debug("globalSymbol({s}, {f}) = {d}", .{ opts.name.toSlice(coff), fmtExternLibName(coff, opts.lib_name), si });
2828 }2834 }
28292835
2830 return sym_gop;2836 return sym_gop;
...@@ -2837,8 +2843,36 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index {...@@ -2837,8 +2843,36 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index {
2837 return .null;2843 return .null;
2838}2844}
28392845
2840pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {2846pub fn globalSymbol(coff: *Coff, opts: struct {
2841 const gop = try coff.getOrPutGlobalSymbol(opts);2847 name: []const u8,
2848 lib_name: ?[]const u8 = null,
2849 type: Symbol.Type = .unknown,
2850 dll_storage_class: Symbol.DllStorageClass = .default,
2851}) !Symbol.Index {
2852 const comp = coff.base.comp;
2853 const lib_name: ExternLibName = if (opts.lib_name) |lib_name| lib_name: {
2854 const is_libc = std.zig.target.isLibCLibName(
2855 &comp.root_mod.resolved_target.result,
2856 lib_name,
2857 );
2858
2859 if (is_libc) {
2860 // This is guaranteed by Sema.handleExternLibName
2861 if (!comp.config.link_libc) unreachable;
2862 break :lib_name .lib_c;
2863 }
2864
2865 try coff.ensureManyUnusedStringCapacity(2, opts.name.len + lib_name.len);
2866 break :lib_name .{ .explicit = coff.getOrPutStringAssumeCapacity(lib_name) };
2867 } else .any;
2868
2869 try coff.ensureUnusedStringCapacity(opts.name.len);
2870 const gop = try coff.getOrPutGlobalSymbol(.{
2871 .name = coff.getOrPutStringAssumeCapacity(opts.name),
2872 .lib_name = lib_name,
2873 .type = opts.type,
2874 .dll_storage_class = opts.dll_storage_class,
2875 });
2842 return gop.value_ptr.si;2876 return gop.value_ptr.si;
2843}2877}
28442878
...@@ -3547,13 +3581,16 @@ fn objectSectionMapIndex(...@@ -3547,13 +3581,16 @@ fn objectSectionMapIndex(
3547 attributes: ObjectSectionAttributes,3581 attributes: ObjectSectionAttributes,
3548) !Node.ObjectSectionMapIndex {3582) !Node.ObjectSectionMapIndex {
3549 const gpa = coff.base.comp.gpa;3583 const gpa = coff.base.comp.gpa;
3550 const name_slice = name.toSlice(coff);
35513584
3552 const object_section_gop = try coff.object_section_table.getOrPut(gpa, name);3585 const object_section_gop = try coff.object_section_table.getOrPut(gpa, name);
3553 const osmi: Node.ObjectSectionMapIndex = @fromBackingInt(@intCast(object_section_gop.index));3586 const osmi: Node.ObjectSectionMapIndex = @fromBackingInt(@intCast(object_section_gop.index));
3554 const sym = if (!object_section_gop.found_existing) sym: {3587 const sym = if (!object_section_gop.found_existing) sym: {
3555 try coff.ensureUnusedStringCapacity(name_slice.len);3588 const name_slice = name.toSlice(coff);
3556 const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice));3589 const parent_name_slice = coff.objectSectionParentName(name_slice);
3590 const parent_name = if (parent_name_slice.len < name_slice.len) parent_name: {
3591 try coff.ensureUnusedStringCapacity(parent_name_slice.len);
3592 break :parent_name coff.getOrPutStringAssumeCapacity(name.toSlice(coff)[0..parent_name_slice.len]);
3593 } else name;
3557 const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, attributes)).symbol(coff);3594 const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, attributes)).symbol(coff);
3558 try coff.nodes.ensureUnusedCapacity(gpa, 1);3595 try coff.nodes.ensureUnusedCapacity(gpa, 1);
3559 try coff.symbols.ensureUnusedCapacity(gpa, 1);3596 try coff.symbols.ensureUnusedCapacity(gpa, 1);
...@@ -4540,7 +4577,7 @@ fn loadObject(...@@ -4540,7 +4577,7 @@ fn loadObject(
4540 },4577 },
4541 .external => {4578 .external => {
4542 const global_gop = try coff.getOrPutGlobalSymbol(.{4579 const global_gop = try coff.getOrPutGlobalSymbol(.{
4543 .name = symbol.name.toSlice(coff),4580 .name = symbol.name,
4544 });4581 });
45454582
4546 // TODO: What if the same symbol is incorrectly defined twice in this obj?4583 // TODO: What if the same symbol is incorrectly defined twice in this obj?
...@@ -4747,7 +4784,7 @@ fn loadObject(...@@ -4747,7 +4784,7 @@ fn loadObject(
4747 continue;4784 continue;
4748 },4785 },
4749 .weak_external => |alias_index| {4786 .weak_external => |alias_index| {
4750 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });4787 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name });
4751 symbol.si = global_gop.value_ptr.si;4788 symbol.si = global_gop.value_ptr.si;
4752 if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {4789 if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {
4753 const sym = symbol.si.get(coff);4790 const sym = symbol.si.get(coff);
...@@ -4786,7 +4823,7 @@ fn loadObject(...@@ -4786,7 +4823,7 @@ fn loadObject(
4786 break :sym value;4823 break :sym value;
4787 },4824 },
4788 .external => |value| {4825 .external => |value| {
4789 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });4826 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name });
4790 symbol.si = global_gop.value_ptr.si;4827 symbol.si = global_gop.value_ptr.si;
4791 if (global_gop.found_existing)4828 if (global_gop.found_existing)
4792 return coff.failMultipleDefinitions(4829 return coff.failMultipleDefinitions(
...@@ -4822,7 +4859,7 @@ fn loadObject(...@@ -4822,7 +4859,7 @@ fn loadObject(
4822 },4859 },
4823 .external => {4860 .external => {
4824 assert(index != section.comdat_psi.unwrap());4861 assert(index != section.comdat_psi.unwrap());
4825 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });4862 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name });
4826 symbol.si = global_gop.value_ptr.si;4863 symbol.si = global_gop.value_ptr.si;
48274864
4828 const sym = symbol.si.get(coff);4865 const sym = symbol.si.get(coff);
...@@ -4906,7 +4943,7 @@ fn loadObject(...@@ -4906,7 +4943,7 @@ fn loadObject(
4906 assert(symbol.section_number == .UNDEFINED);4943 assert(symbol.section_number == .UNDEFINED);
4907 switch (symbol.value) {4944 switch (symbol.value) {
4908 .external => |size| {4945 .external => |size| {
4909 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });4946 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name });
4910 symbol.si = global_gop.value_ptr.si;4947 symbol.si = global_gop.value_ptr.si;
4911 if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {4948 if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) {
4912 const sym = symbol.si.get(coff);4949 const sym = symbol.si.get(coff);
...@@ -6244,9 +6281,9 @@ fn aliasGlobal(coff: *Coff, gmi: Node.GlobalMapIndex, alias_si: Symbol.Index) !v...@@ -6244,9 +6281,9 @@ fn aliasGlobal(coff: *Coff, gmi: Node.GlobalMapIndex, alias_si: Symbol.Index) !v
6244 assert(sym.section_number == .UNDEFINED);6281 assert(sym.section_number == .UNDEFINED);
6245 assert(sym.loc_relocs == .none);6282 assert(sym.loc_relocs == .none);
62466283
6247 log.debug("aliasGlobal({s}, {?s}) {d}->{d} ({?s})", .{6284 log.debug("aliasGlobal({s}, {f}) {d}->{d} ({?s})", .{
6248 gmi.name(coff).toSlice(coff),6285 gmi.name(coff).toSlice(coff),
6249 gmi.libName(coff).toSlice(coff),6286 fmtExternLibName(coff, gmi.libName(coff)),
6250 si,6287 si,
6251 alias_si,6288 alias_si,
6252 if (alias_sym.gmi != .none) alias_sym.gmi.name(coff).toSlice(coff) else null,6289 if (alias_sym.gmi != .none) alias_sym.gmi.name(coff).toSlice(coff) else null,
...@@ -6284,10 +6321,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6284,10 +6321,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6284 const si = gmi.symbol(coff);6321 const si = gmi.symbol(coff);
62856322
6286 log.debug(6323 log.debug(
6287 "flushGlobal({s}, {?s}) = n{d} {d}@{d}",6324 "flushGlobal({s}, {f}) = n{d} {d}@{d}",
6288 .{6325 .{
6289 name.toSlice(coff),6326 name.toSlice(coff),
6290 gmi.libName(coff).toSlice(coff),6327 fmtExternLibName(coff, gmi.libName(coff)),
6291 si.get(coff).ni,6328 si.get(coff).ni,
6292 si,6329 si,
6293 si.get(coff).section_number,6330 si.get(coff).section_number,
...@@ -6362,68 +6399,72 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6362,68 +6399,72 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6362 while (true) {6399 while (true) {
6363 const archive_sym = &coff.input_archive_symbols.items[@backingInt(iter)];6400 const archive_sym = &coff.input_archive_symbols.items[@backingInt(iter)];
6364 const member = &coff.input_archive_members.items[@backingInt(archive_sym.iami)];6401 const member = &coff.input_archive_members.items[@backingInt(archive_sym.iami)];
6365 member: switch (member.content) {6402 const lib_name_matches = match: switch (gmi.libName(coff)) {
6366 .object => if (!member.flags.is_loaded) {6403 .any => true,
6367 if (gmi.libName(coff).unwrap()) |lib_name|6404 .lib_c => {
6368 if (!std.ascii.eqlIgnoreCase(6405 // TODO: Need a flag to indicate if this member is from a libc archive
6369 lib_name.toSlice(coff),6406 const is_libc_archive = true;
6370 member.iai.path(coff).stem(),
6371 )) break :member;
6372
6373 // Try loading the input member and then retry.
6374 // This could still be a member containing imports
6375 // that use the older non-IMPORT_HEADER method.
6376 coff.pending_input = archive_sym.iami;
6377 return false;
6378 },
6379 .import => |import| {
6380 if (gmi.libName(coff).unwrap()) |lib_name|
6381 if (!std.ascii.eqlIgnoreCase(
6382 import.lib_name.toSlice(coff),
6383 lib_name.toSlice(coff),
6384 )) break :member;
6385
6386 const imp_name: String.Optional = name: switch (import.name_type) {
6387 .NAME,
6388 .NAME_NOPREFIX,
6389 .NAME_UNDECORATE,
6390 => |tag| {
6391 const symbol_name: []const u8 = import.symbol_name.toSlice(coff);
6392 const end_match = std.mem.endsWith(u8, name_slice, symbol_name);
6393 const len_delta = name_slice.len -% symbol_name.len;
6394 if (!end_match or
6395 (!imp_match and len_delta != 0) or
6396 (imp_match and len_delta != imp_prefix.len))
6397 return comp.link_diags.fail(
6398 "global '{s}' has mismatched symbol name in import header: '{s}'",
6399 .{
6400 name.toSlice(coff),
6401 import.symbol_name.toSlice(coff),
6402 },
6403 );
64046407
6405 const imp_name = if (tag == .NAME) import.symbol_name else undecorated: {6408 break :match is_libc_archive;
6406 var imp_name = std.mem.trimStart(u8, symbol_name, "?@_");6409 },
6407 if (tag == .NAME_UNDECORATE)6410 .explicit => |lib_name| std.ascii.eqlIgnoreCase(
6408 imp_name = std.mem.sliceTo(imp_name, '@');6411 lib_name.toSlice(coff),
64096412 member.iai.path(coff).stem(),
6410 try coff.ensureUnusedStringCapacity(imp_name.len);6413 ),
6411 break :undecorated coff.getOrPutStringAssumeCapacity(imp_name);6414 };
6412 };
64136415
6414 break :name imp_name.toOptional();6416 if (lib_name_matches) {
6415 },6417 switch (member.content) {
6416 .ORDINAL => break :name .none,6418 .object => if (!member.flags.is_loaded) {
6417 else => |t| return comp.link_diags.fail("TODO handle name_type {t}", .{t}),6419 // Try loading the input member and then retry.
6418 };6420 // This could still be a member containing imports
6421 // that use the older non-IMPORT_HEADER method.
6422 coff.pending_input = archive_sym.iami;
6423 return false;
6424 },
6425 .import => |import| {
6426 const imp_name: String.Optional = name: switch (import.name_type) {
6427 .NAME,
6428 .NAME_NOPREFIX,
6429 .NAME_UNDECORATE,
6430 => |tag| {
6431 const symbol_name: []const u8 = import.symbol_name.toSlice(coff);
6432 const end_match = std.mem.endsWith(u8, name_slice, symbol_name);
6433 const len_delta = name_slice.len -% symbol_name.len;
6434 if (!end_match or
6435 (!imp_match and len_delta != 0) or
6436 (imp_match and len_delta != imp_prefix.len))
6437 return comp.link_diags.fail(
6438 "global '{s}' has mismatched symbol name in import header: '{s}'",
6439 .{
6440 name.toSlice(coff),
6441 import.symbol_name.toSlice(coff),
6442 },
6443 );
6444
6445 const imp_name = if (tag == .NAME) import.symbol_name else undecorated: {
6446 var imp_name = std.mem.trimStart(u8, symbol_name, "?@_");
6447 if (tag == .NAME_UNDECORATE)
6448 imp_name = std.mem.sliceTo(imp_name, '@');
6449
6450 try coff.ensureUnusedStringCapacity(imp_name.len);
6451 break :undecorated coff.getOrPutStringAssumeCapacity(imp_name);
6452 };
6453
6454 break :name imp_name.toOptional();
6455 },
6456 .ORDINAL => break :name .none,
6457 else => |t| return comp.link_diags.fail("TODO handle name_type {t}", .{t}),
6458 };
64196459
6420 break :import .{6460 break :import .{
6421 .lib_name = import.lib_name,6461 .lib_name = import.lib_name,
6422 .name = imp_name,6462 .name = imp_name,
6423 .ordinal_hint = import.import_ordinal_hint,6463 .ordinal_hint = import.import_ordinal_hint,
6424 .kind = if (import.type == .CODE and !is_imp) .thunk else .iat_ptr,6464 .kind = if (import.type == .CODE and !is_imp) .thunk else .iat_ptr,
6425 };6465 };
6426 },6466 },
6467 }
6427 }6468 }
64286469
6429 if (archive_sym.next == iter) break;6470 if (archive_sym.next == iter) break;
...@@ -6440,7 +6481,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6440,7 +6481,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6440 // Convert an unresolved weak external that itself refers to an undef external6481 // Convert an unresolved weak external that itself refers to an undef external
6441 // into a (possibly new) global, so it can be resolved separately.6482 // into a (possibly new) global, so it can be resolved separately.
6442 const alias_gop = try coff.getOrPutGlobalSymbol(.{6483 const alias_gop = try coff.getOrPutGlobalSymbol(.{
6443 .name = sym.value.weak_alias_name.toSlice(coff),6484 .name = sym.value.weak_alias_name,
6444 });6485 });
6445 try coff.aliasGlobal(gmi, alias_gop.value_ptr.si);6486 try coff.aliasGlobal(gmi, alias_gop.value_ptr.si);
6446 return true;6487 return true;
...@@ -6460,12 +6501,15 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6460,12 +6501,15 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6460 // This is necessary for certain ntdll symbols, such as LdrRegisterDllNotification,6501 // This is necessary for certain ntdll symbols, such as LdrRegisterDllNotification,
6461 // which are not in the implib.6502 // which are not in the implib.
6462 if (sym.flags.type != .unknown) {6503 if (sym.flags.type != .unknown) {
6463 if (gmi.libName(coff).unwrap()) |lib_name| break :import .{6504 switch (gmi.libName(coff)) {
6464 .lib_name = lib_name,6505 .explicit => |lib_name| break :import .{
6465 .name = name.toOptional(),6506 .lib_name = lib_name,
6466 .ordinal_hint = 0,6507 .name = name.toOptional(),
6467 .kind = if (sym.flags.type == .code) .thunk else .iat_ptr,6508 .ordinal_hint = 0,
6468 };6509 .kind = if (sym.flags.type == .code) .thunk else .iat_ptr,
6510 },
6511 else => {},
6512 }
6469 }6513 }
64706514
6471 return true;6515 return true;
...@@ -7660,8 +7704,10 @@ fn fmtGlobalName(coff: *Coff, gmi: Node.GlobalMapIndex) std.fmt.Alt(FmtGlobalNam...@@ -7660,8 +7704,10 @@ fn fmtGlobalName(coff: *Coff, gmi: Node.GlobalMapIndex) std.fmt.Alt(FmtGlobalNam
7660fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void {7704fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void {
7661 if (data.gmi == .none) return;7705 if (data.gmi == .none) return;
7662 try w.writeAll(data.gmi.name(data.coff).toSlice(data.coff));7706 try w.writeAll(data.gmi.name(data.coff).toSlice(data.coff));
7663 if (data.gmi.libName(data.coff).unwrap()) |lib_name|7707 switch (data.gmi.libName(data.coff)) {
7664 try w.print("({s})", .{lib_name.toSlice(data.coff)});7708 .explicit => |lib_name| try w.print(" ({s}.dll)", .{lib_name.toSlice(data.coff)}),
7709 else => {},
7710 }
7665}7711}
76667712
7667fn printNodeName(7713fn printNodeName(
...@@ -7703,12 +7749,7 @@ fn printNodeName(...@@ -7703,12 +7749,7 @@ fn printNodeName(
7703 inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{7749 inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{
7704 smi.name(coff).toSlice(coff),7750 smi.name(coff).toSlice(coff),
7705 }),7751 }),
7706 .import_thunk,7752 .import_thunk => |gmi| try w.print("({f})", .{fmtGlobalName(coff, gmi)}),
7707 => |gmi| {
7708 try w.writeByte('(');
7709 if (gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name});
7710 try w.print("{s})", .{gmi.name(coff).toSlice(coff)});
7711 },
7712 .nav => |nmi| {7753 .nav => |nmi| {
7713 const zcu = coff.base.comp.zcu.?;7754 const zcu = coff.base.comp.zcu.?;
7714 const ip = &zcu.intern_pool;7755 const ip = &zcu.intern_pool;
...@@ -7734,11 +7775,7 @@ fn printNodeName(...@@ -7734,11 +7775,7 @@ fn printNodeName(
7734 }),7775 }),
7735 .builtin => |si| {7776 .builtin => |si| {
7736 const sym = si.get(coff);7777 const sym = si.get(coff);
7737 if (sym.gmi != .none) {7778 if (sym.gmi != .none) try w.print("({f})", .{fmtGlobalName(coff, sym.gmi)});
7738 try w.writeByte('(');
7739 if (sym.gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name});
7740 try w.print("{s})", .{sym.gmi.name(coff).toSlice(coff)});
7741 }
7742 },7779 },
7743 }7780 }
7744}7781}