| ... | @@ -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 | } |
| 280 | | 280 | |
| 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 { |
| 864 | | 864 | |
| 865 | pub const Global = struct { | 865 | pub const Global = struct { |
| 866 | si: Symbol.Index, | 866 | si: Symbol.Index, |
| 867 | lib_name: String.Optional, | 867 | lib_name: ExternLibName, |
| 868 | }; | 868 | }; |
| 869 | | 869 | |
| 870 | pub const WeakExternalStrat = enum(u3) { | 870 | pub 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 | } |
| 2783 | | 2783 | |
| 2784 | const GlobalOptions = struct { | 2784 | const 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 | }; |
| 2790 | | 2792 | |
| | 2793 | const FmtExternLibName = struct { coff: *Coff, lib_name: ExternLibName }; |
| | 2794 | |
| | 2795 | fn fmtExternLibName(coff: *Coff, lib_name: ExternLibName) std.fmt.Alt(FmtExternLibName, formatExternLibName) { |
| | 2796 | return .{ .data = .{ .coff = coff, .lib_name = lib_name } }; |
| | 2797 | } |
| | 2798 | |
| | 2799 | fn 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 | |
| 2791 | fn getOrPutGlobalSymbol( | 2807 | fn 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); |
| 2798 | | 2819 | |
| 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); |
| 2826 | | 2832 | |
| 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 | } |
| 2829 | | 2835 | |
| 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 | } |
| 2839 | | 2845 | |
| 2840 | pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index { | 2846 | pub 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 | } |
| 2844 | | 2878 | |
| ... | @@ -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); | | |
| 3551 | | 3584 | |
| 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 | }); |
| 4545 | | 4582 | |
| 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; |
| 4827 | | 4864 | |
| 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); |
| 6246 | | 6283 | |
| 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); |
| 6285 | | 6322 | |
| 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 | ); | | |
| 6404 | | 6407 | |
| 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), |
| 6409 | | 6412 | member.iai.path(coff).stem(), |
| 6410 | try coff.ensureUnusedStringCapacity(imp_name.len); | 6413 | ), |
| 6411 | break :undecorated coff.getOrPutStringAssumeCapacity(imp_name); | 6414 | }; |
| 6412 | }; | | |
| 6413 | | 6415 | |
| 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 | }; |
| 6419 | | 6459 | |
| 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 | } |
| 6428 | | 6469 | |
| 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 external | 6481 | // 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 | } |
| 6470 | | 6514 | |
| 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 |
| 7660 | fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void { | 7704 | fn 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 | } |
| 7666 | | 7712 | |
| 7667 | fn printNodeName( | 7713 | fn 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 | } |