| ... | @@ -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 | }; |
| ... | @@ -647,15 +647,12 @@ pub const SymbolTable = struct { | ... | @@ -647,15 +647,12 @@ pub const SymbolTable = struct { |
| 647 | }; | 647 | }; |
| 648 | | 648 | |
| 649 | pub const SymbolName = union(enum) { | 649 | pub const SymbolName = union(enum) { |
| 650 | short: []const u8, | 650 | short: [8]u8, |
| 651 | long: StringIndex, | 651 | long: StringIndex, |
| 652 | | 652 | |
| 653 | pub fn store(name: SymbolName, coff: *const Coff, field: *[8]u8) void { | 653 | pub fn store(name: SymbolName, coff: *const Coff, field: *[8]u8) void { |
| 654 | switch (name) { | 654 | switch (name) { |
| 655 | .short => |s| { | 655 | .short => |s| field.* = s, |
| 656 | @memcpy(field[0..s.len], s); | | |
| 657 | @memset(field[s.len..], 0); | | |
| 658 | }, | | |
| 659 | .long => |l| { | 656 | .long => |l| { |
| 660 | @memset(field[0..4], 0); | 657 | @memset(field[0..4], 0); |
| 661 | std.mem.writePackedInt(u32, field[4..], 0, @backingInt(l), coff.targetEndian()); | 658 | std.mem.writePackedInt(u32, field[4..], 0, @backingInt(l), coff.targetEndian()); |
| ... | @@ -864,7 +861,7 @@ pub const Section = struct { | ... | @@ -864,7 +861,7 @@ pub const Section = struct { |
| 864 | | 861 | |
| 865 | pub const Global = struct { | 862 | pub const Global = struct { |
| 866 | si: Symbol.Index, | 863 | si: Symbol.Index, |
| 867 | lib_name: String.Optional, | 864 | lib_name: ExternLibName, |
| 868 | }; | 865 | }; |
| 869 | | 866 | |
| 870 | pub const WeakExternalStrat = enum(u3) { | 867 | pub const WeakExternalStrat = enum(u3) { |
| ... | @@ -2263,6 +2260,11 @@ pub fn initBuiltins(coff: *Coff) !void { | ... | @@ -2263,6 +2260,11 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2263 | } | 2260 | } |
| 2264 | | 2261 | |
| 2265 | defer coff.flushSectionMerges() catch unreachable; | 2262 | defer coff.flushSectionMerges() catch unreachable; |
| | 2263 | if (coff.isImage()) { |
| | 2264 | // In images, the .tls section is a read-only template |
| | 2265 | try coff.section_merges.put(gpa, .@".tls", .@".rdata"); |
| | 2266 | } |
| | 2267 | |
| 2266 | if (coff.isImage() and target.isMinGW() and comp.config.link_libc) { | 2268 | if (coff.isImage() and target.isMinGW() and comp.config.link_libc) { |
| 2267 | try coff.symbols.ensureUnusedCapacity(gpa, 8); | 2269 | try coff.symbols.ensureUnusedCapacity(gpa, 8); |
| 2268 | try coff.globals.ensureUnusedCapacity(gpa, 2); | 2270 | try coff.globals.ensureUnusedCapacity(gpa, 2); |
| ... | @@ -2723,29 +2725,42 @@ fn getString(coff: *Coff, string: []const u8) String.Optional { | ... | @@ -2723,29 +2725,42 @@ fn getString(coff: *Coff, string: []const u8) String.Optional { |
| 2723 | return .none; | 2725 | return .none; |
| 2724 | } | 2726 | } |
| 2725 | | 2727 | |
| 2726 | /// If the name does not fit in the symbol header, adds it to the symbol table string table. | 2728 | /// If the name does not fit within inline storage, adds it to the symbol table string table. |
| 2727 | /// If the caller knows this name already has a String associated with it, they can avoid | 2729 | fn getOrPutSymbolName(coff: *Coff, name: union(enum) { |
| 2728 | /// a redundant call to `getOrPutString` by specifying `opt_string`. | 2730 | slice: []const u8, |
| 2729 | /// The lifetime of the return value matches that of `name`. | 2731 | string: String, |
| 2730 | fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !SymbolTable.SymbolName { | 2732 | }) !SymbolTable.SymbolName { |
| 2731 | assert(!coff.isImage()); | 2733 | assert(!coff.isImage()); |
| 2732 | const gpa = coff.base.comp.gpa; | 2734 | const gpa = coff.base.comp.gpa; |
| | 2735 | const slice = switch (name) { |
| | 2736 | .slice => |s| s, |
| | 2737 | .string => |s| s.toSlice(coff), |
| | 2738 | }; |
| | 2739 | |
| | 2740 | if (slice.len > header_name_max_len) { |
| | 2741 | const string = switch (name) { |
| | 2742 | .slice => |s| try coff.getOrPutString(s), |
| | 2743 | .string => |s| s, |
| | 2744 | }; |
| 2733 | | 2745 | |
| 2734 | return if (name.len > header_name_max_len) name: { | | |
| 2735 | const string = opt_string orelse try coff.getOrPutString(name); | | |
| 2736 | const string_gop = try coff.symbol_table.strings.getOrPut(gpa, string); | 2746 | const string_gop = try coff.symbol_table.strings.getOrPut(gpa, string); |
| 2737 | if (!string_gop.found_existing) { | 2747 | if (!string_gop.found_existing) { |
| 2738 | const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1]; | 2748 | const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1]; |
| 2739 | string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index)); | 2749 | string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index)); |
| 2740 | | 2750 | |
| 2741 | try coff.symbol_table.strings_ni.resizeLeaf(gpa, &coff.mf, string_index + name.len + 1); | 2751 | try coff.symbol_table.strings_ni.resizeLeaf(gpa, &coff.mf, string_index + slice.len + 1); |
| 2742 | const slice = coff.symbol_table.strings_ni.slice(&coff.mf); | 2752 | const storage = coff.symbol_table.strings_ni.slice(&coff.mf); |
| 2743 | @memcpy(slice[@intCast(string_index)..][0..name.len], name); | 2753 | @memcpy(storage[@intCast(string_index)..][0..slice.len], slice); |
| 2744 | slice[@intCast(string_index + name.len)] = 0; | 2754 | storage[@intCast(string_index + slice.len)] = 0; |
| 2745 | } | 2755 | } |
| 2746 | | 2756 | |
| 2747 | break :name .{ .long = string_gop.value_ptr.* }; | 2757 | return .{ .long = string_gop.value_ptr.* }; |
| 2748 | } else .{ .short = name }; | 2758 | } else { |
| | 2759 | var symbol_name: SymbolTable.SymbolName = .{ .short = undefined }; |
| | 2760 | @memcpy(symbol_name.short[0..slice.len], slice); |
| | 2761 | @memset(symbol_name.short[slice.len..], 0); |
| | 2762 | return symbol_name; |
| | 2763 | } |
| 2749 | } | 2764 | } |
| 2750 | | 2765 | |
| 2751 | /// `len` does not include null terminators | 2766 | /// `len` does not include null terminators |
| ... | @@ -2776,37 +2791,43 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String { | ... | @@ -2776,37 +2791,43 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String { |
| 2776 | return @fromBackingInt(@intCast(gop.key_ptr.*)); | 2791 | return @fromBackingInt(@intCast(gop.key_ptr.*)); |
| 2777 | } | 2792 | } |
| 2778 | | 2793 | |
| 2779 | const GlobalOptions = struct { | 2794 | const ExternLibName = union(enum) { |
| 2780 | name: []const u8, | 2795 | // Symbol can be supplied from anywhere |
| 2781 | lib_name: ?[]const u8 = null, | 2796 | any, |
| 2782 | type: Symbol.Type = .unknown, | 2797 | // Symbol can be supplied by any LibC input |
| 2783 | dll_storage_class: Symbol.DllStorageClass = .default, | 2798 | lib_c, |
| | 2799 | // Symbol must be supplied by a specific input |
| | 2800 | explicit: String, |
| 2784 | }; | 2801 | }; |
| 2785 | | 2802 | |
| | 2803 | const FmtExternLibName = struct { coff: *Coff, lib_name: ExternLibName }; |
| | 2804 | |
| | 2805 | fn fmtExternLibName(coff: *Coff, lib_name: ExternLibName) std.fmt.Alt(FmtExternLibName, formatExternLibName) { |
| | 2806 | return .{ .data = .{ .coff = coff, .lib_name = lib_name } }; |
| | 2807 | } |
| | 2808 | |
| | 2809 | fn formatExternLibName(data: FmtExternLibName, w: *Io.Writer) Io.Writer.Error!void { |
| | 2810 | try w.writeAll(switch (data.lib_name) { |
| | 2811 | .any => "*", |
| | 2812 | .lib_c => "c", |
| | 2813 | .explicit => |str| str.toSlice(data.coff), |
| | 2814 | }); |
| | 2815 | } |
| | 2816 | |
| 2786 | fn getOrPutGlobalSymbol( | 2817 | fn getOrPutGlobalSymbol( |
| 2787 | coff: *Coff, | 2818 | coff: *Coff, |
| 2788 | opts: GlobalOptions, | 2819 | opts: struct { |
| | 2820 | name: String, |
| | 2821 | lib_name: ExternLibName = .any, |
| | 2822 | type: Symbol.Type = .unknown, |
| | 2823 | dll_storage_class: Symbol.DllStorageClass = .default, |
| | 2824 | }, |
| 2789 | ) !std.array_hash_map.Auto(String, Global).GetOrPutResult { | 2825 | ) !std.array_hash_map.Auto(String, Global).GetOrPutResult { |
| 2790 | const comp = coff.base.comp; | 2826 | const comp = coff.base.comp; |
| 2791 | const gpa = comp.gpa; | 2827 | const gpa = comp.gpa; |
| 2792 | try coff.symbols.ensureUnusedCapacity(gpa, 1); | 2828 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 2793 | | 2829 | |
| 2794 | const lib_name: String.Optional = if (opts.lib_name) |lib_name| lib_name: { | 2830 | const sym_gop = try coff.globals.getOrPut(gpa, opts.name); |
| 2795 | const is_libc = std.zig.target.isLibCLibName(&comp.root_mod.resolved_target.result, lib_name); | | |
| 2796 | if (is_libc) { | | |
| 2797 | // This is guaranteed by Sema.handleExternLibName | | |
| 2798 | if (!comp.config.link_libc) unreachable; | | |
| 2799 | | | |
| 2800 | // TODO: The user has requested this symbol come from libc, but this logic allows | | |
| 2801 | // it to come from anywhere. We need to know what inputs are libc inputs, | | |
| 2802 | // and set a flag to only search them for this symbol. | | |
| 2803 | break :lib_name .none; | | |
| 2804 | } | | |
| 2805 | | | |
| 2806 | break :lib_name (try coff.getOrPutString(lib_name)).toOptional(); | | |
| 2807 | } else .none; | | |
| 2808 | | | |
| 2809 | const sym_gop = try coff.globals.getOrPut(gpa, try coff.getOrPutString(opts.name)); | | |
| 2810 | if (!sym_gop.found_existing) { | 2831 | if (!sym_gop.found_existing) { |
| 2811 | const si = coff.addSymbolAssumeCapacity(); | 2832 | const si = coff.addSymbolAssumeCapacity(); |
| 2812 | const sym = si.get(coff); | 2833 | const sym = si.get(coff); |
| ... | @@ -2815,11 +2836,11 @@ fn getOrPutGlobalSymbol( | ... | @@ -2815,11 +2836,11 @@ fn getOrPutGlobalSymbol( |
| 2815 | sym.flags.dll_storage_class = opts.dll_storage_class; | 2836 | sym.flags.dll_storage_class = opts.dll_storage_class; |
| 2816 | sym_gop.value_ptr.* = .{ | 2837 | sym_gop.value_ptr.* = .{ |
| 2817 | .si = si, | 2838 | .si = si, |
| 2818 | .lib_name = lib_name, | 2839 | .lib_name = opts.lib_name, |
| 2819 | }; | 2840 | }; |
| 2820 | coff.synth_prog_node.increaseEstimatedTotalItems(1); | 2841 | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| 2821 | | 2842 | |
| 2822 | log.debug("globalSymbol({s}, {?s}) = {d}", .{ opts.name, opts.lib_name, si }); | 2843 | log.debug("globalSymbol({s}, {f}) = {d}", .{ opts.name.toSlice(coff), fmtExternLibName(coff, opts.lib_name), si }); |
| 2823 | } | 2844 | } |
| 2824 | | 2845 | |
| 2825 | return sym_gop; | 2846 | return sym_gop; |
| ... | @@ -2832,8 +2853,36 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index { | ... | @@ -2832,8 +2853,36 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index { |
| 2832 | return .null; | 2853 | return .null; |
| 2833 | } | 2854 | } |
| 2834 | | 2855 | |
| 2835 | pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index { | 2856 | pub fn globalSymbol(coff: *Coff, opts: struct { |
| 2836 | const gop = try coff.getOrPutGlobalSymbol(opts); | 2857 | name: []const u8, |
| | 2858 | lib_name: ?[]const u8 = null, |
| | 2859 | type: Symbol.Type = .unknown, |
| | 2860 | dll_storage_class: Symbol.DllStorageClass = .default, |
| | 2861 | }) !Symbol.Index { |
| | 2862 | const comp = coff.base.comp; |
| | 2863 | const lib_name: ExternLibName = if (opts.lib_name) |lib_name| lib_name: { |
| | 2864 | const is_libc = std.zig.target.isLibCLibName( |
| | 2865 | &comp.root_mod.resolved_target.result, |
| | 2866 | lib_name, |
| | 2867 | ); |
| | 2868 | |
| | 2869 | if (is_libc) { |
| | 2870 | // This is guaranteed by Sema.handleExternLibName |
| | 2871 | if (!comp.config.link_libc) unreachable; |
| | 2872 | break :lib_name .lib_c; |
| | 2873 | } |
| | 2874 | |
| | 2875 | try coff.ensureManyUnusedStringCapacity(2, opts.name.len + lib_name.len + 2); |
| | 2876 | break :lib_name .{ .explicit = coff.getOrPutStringAssumeCapacity(lib_name) }; |
| | 2877 | } else .any; |
| | 2878 | |
| | 2879 | try coff.ensureUnusedStringCapacity(opts.name.len); |
| | 2880 | const gop = try coff.getOrPutGlobalSymbol(.{ |
| | 2881 | .name = coff.getOrPutStringAssumeCapacity(opts.name), |
| | 2882 | .lib_name = lib_name, |
| | 2883 | .type = opts.type, |
| | 2884 | .dll_storage_class = opts.dll_storage_class, |
| | 2885 | }); |
| 2837 | return gop.value_ptr.si; | 2886 | return gop.value_ptr.si; |
| 2838 | } | 2887 | } |
| 2839 | | 2888 | |
| ... | @@ -3107,7 +3156,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { | ... | @@ -3107,7 +3156,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void { |
| 3107 | coff.targetStore(coff.secondLinkerMemberNumSymbolsPtr(), @backingInt(mfli) + 1); | 3156 | coff.targetStore(coff.secondLinkerMemberNumSymbolsPtr(), @backingInt(mfli) + 1); |
| 3108 | if (!needs_sort) { | 3157 | if (!needs_sort) { |
| 3109 | @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]); | 3158 | @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]); |
| 3110 | @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice[0..name_slice.len]); | 3159 | @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice); |
| 3111 | slice[new_header_size + coff.lib_string_len + name_slice.len] = 0; | 3160 | slice[new_header_size + coff.lib_string_len + name_slice.len] = 0; |
| 3112 | } else if (!old_needs_sort) { | 3161 | } else if (!old_needs_sort) { |
| 3113 | // The entire string table is rebuilt in flushMember after sorting | 3162 | // The entire string table is rebuilt in flushMember after sorting |
| ... | @@ -3136,9 +3185,8 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { | ... | @@ -3136,9 +3185,8 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3136 | const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: { | 3185 | const entry = coff.symbolTableEntryPtr(sti.*) orelse entry: { |
| 3137 | const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType = | 3186 | const symbol_name, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType = |
| 3138 | if (sym.gmi != .none) blk: { | 3187 | if (sym.gmi != .none) blk: { |
| 3139 | const name = sym.gmi.name(coff); | | |
| 3140 | break :blk .{ | 3188 | break :blk .{ |
| 3141 | try coff.getOrPutSymbolName(name.toSlice(coff), name), | 3189 | try coff.getOrPutSymbolName(.{ .string = sym.gmi.name(coff) }), |
| 3142 | @intFromBool(sym.flags.weak_external_strat != .none), | 3190 | @intFromBool(sym.flags.weak_external_strat != .none), |
| 3143 | if (Symbol.Index.text.get(coff).section_number == sym.section_number) | 3191 | if (Symbol.Index.text.get(coff).section_number == sym.section_number) |
| 3144 | .FUNCTION | 3192 | .FUNCTION |
| ... | @@ -3147,7 +3195,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { | ... | @@ -3147,7 +3195,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3147 | }; | 3195 | }; |
| 3148 | } else blk: switch (coff.getNode(sym.ni.unwrap().?)) { | 3196 | } else blk: switch (coff.getNode(sym.ni.unwrap().?)) { |
| 3149 | .image_section => .{ | 3197 | .image_section => .{ |
| 3150 | try coff.getOrPutSymbolName(&sym.section_number.header(coff).name, null), | 3198 | try coff.getOrPutSymbolName(.{ .slice = &sym.section_number.header(coff).name }), |
| 3151 | 1, | 3199 | 1, |
| 3152 | .NULL, | 3200 | .NULL, |
| 3153 | }, | 3201 | }, |
| ... | @@ -3156,7 +3204,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { | ... | @@ -3156,7 +3204,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3156 | const ip = &zcu.intern_pool; | 3204 | const ip = &zcu.intern_pool; |
| 3157 | const nav = ip.getNav(nmi.navIndex(coff)); | 3205 | const nav = ip.getNav(nmi.navIndex(coff)); |
| 3158 | break :blk .{ | 3206 | break :blk .{ |
| 3159 | try coff.getOrPutSymbolName(nav.fqn.toSlice(ip), null), | 3207 | try coff.getOrPutSymbolName(.{ .slice = nav.fqn.toSlice(ip) }), |
| 3160 | 0, | 3208 | 0, |
| 3161 | if (ip.isFunctionType(nav.resolved.?.type)) .FUNCTION else .NULL, | 3209 | if (ip.isFunctionType(nav.resolved.?.type)) .FUNCTION else .NULL, |
| 3162 | }; | 3210 | }; |
| ... | @@ -3165,7 +3213,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { | ... | @@ -3165,7 +3213,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3165 | var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined; | 3213 | var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined; |
| 3166 | const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable; | 3214 | const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable; |
| 3167 | break :blk .{ | 3215 | break :blk .{ |
| 3168 | try coff.getOrPutSymbolName(name, null), | 3216 | try coff.getOrPutSymbolName(.{ .slice = name }), |
| 3169 | 0, | 3217 | 0, |
| 3170 | .NULL, | 3218 | .NULL, |
| 3171 | }; | 3219 | }; |
| ... | @@ -3179,9 +3227,8 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { | ... | @@ -3179,9 +3227,8 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void { |
| 3179 | lazy_sym.kind, mi, | 3227 | lazy_sym.kind, mi, |
| 3180 | }) catch unreachable; | 3228 | }) catch unreachable; |
| 3181 | | 3229 | |
| 3182 | const string = try coff.getOrPutString(name); | | |
| 3183 | break :blk .{ | 3230 | break :blk .{ |
| 3184 | try coff.getOrPutSymbolName(string.toSlice(coff), string), | 3231 | try coff.getOrPutSymbolName(.{ .slice = name }), |
| 3185 | 0, | 3232 | 0, |
| 3186 | if (tag == .lazy_code) .FUNCTION else .NULL, | 3233 | if (tag == .lazy_code) .FUNCTION else .NULL, |
| 3187 | }; | 3234 | }; |
| ... | @@ -3412,8 +3459,8 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S | ... | @@ -3412,8 +3459,8 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S |
| 3412 | if (coff.targetEndian() != native_endian) | 3459 | if (coff.targetEndian() != native_endian) |
| 3413 | std.mem.byteSwapAllFields(std.coff.SectionHeader, section); | 3460 | std.mem.byteSwapAllFields(std.coff.SectionHeader, section); |
| 3414 | | 3461 | |
| 3415 | const name_slice = name.toSlice(coff); | | |
| 3416 | if (coff.isImage()) { | 3462 | if (coff.isImage()) { |
| | 3463 | const name_slice = name.toSlice(coff); |
| 3417 | @memcpy(section.name[0..name_slice.len], name_slice); | 3464 | @memcpy(section.name[0..name_slice.len], name_slice); |
| 3418 | @memset(section.name[name_slice.len..], 0); | 3465 | @memset(section.name[name_slice.len..], 0); |
| 3419 | switch (coff.optionalHeaderPtr()) { | 3466 | switch (coff.optionalHeaderPtr()) { |
| ... | @@ -3423,7 +3470,7 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S | ... | @@ -3423,7 +3470,7 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S |
| 3423 | ), | 3470 | ), |
| 3424 | } | 3471 | } |
| 3425 | } else { | 3472 | } else { |
| 3426 | (try coff.getOrPutSymbolName(name_slice, name)).store(coff, &section.name); | 3473 | (try coff.getOrPutSymbolName(.{ .string = name })).store(coff, &section.name); |
| 3427 | try coff.pendingSymbolTableEntry(si); | 3474 | try coff.pendingSymbolTableEntry(si); |
| 3428 | } | 3475 | } |
| 3429 | | 3476 | |
| ... | @@ -3542,21 +3589,26 @@ fn objectSectionMapIndex( | ... | @@ -3542,21 +3589,26 @@ fn objectSectionMapIndex( |
| 3542 | attributes: ObjectSectionAttributes, | 3589 | attributes: ObjectSectionAttributes, |
| 3543 | ) !Node.ObjectSectionMapIndex { | 3590 | ) !Node.ObjectSectionMapIndex { |
| 3544 | const gpa = coff.base.comp.gpa; | 3591 | const gpa = coff.base.comp.gpa; |
| 3545 | const name_slice = name.toSlice(coff); | | |
| 3546 | // TODO: Should this be a section merge instead? | | |
| 3547 | const effective_attributes = if (coff.isImage() and std.mem.startsWith(u8, name_slice, ".tls")) attr: { | | |
| 3548 | // In images, the .tls section is a read-only template | | |
| 3549 | var attr = attributes; | | |
| 3550 | attr.write = false; | | |
| 3551 | break :attr attr; | | |
| 3552 | } else attributes; | | |
| 3553 | | 3592 | |
| 3554 | const object_section_gop = try coff.object_section_table.getOrPut(gpa, name); | 3593 | const object_section_gop = try coff.object_section_table.getOrPut(gpa, name); |
| 3555 | const osmi: Node.ObjectSectionMapIndex = @fromBackingInt(@intCast(object_section_gop.index)); | 3594 | const osmi: Node.ObjectSectionMapIndex = @fromBackingInt(@intCast(object_section_gop.index)); |
| 3556 | const sym = if (!object_section_gop.found_existing) sym: { | 3595 | const sym = if (!object_section_gop.found_existing) sym: { |
| 3557 | try coff.ensureUnusedStringCapacity(name_slice.len); | 3596 | const name_slice, const parent_name = blk: { |
| 3558 | const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice)); | 3597 | var name_slice = name.toSlice(coff); |
| 3559 | const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, effective_attributes)).symbol(coff); | 3598 | const parent_name_slice = coff.objectSectionParentName(name_slice); |
| | 3599 | const parent_name = if (parent_name_slice.len < name_slice.len) parent_name: { |
| | 3600 | try coff.ensureUnusedStringCapacity(parent_name_slice.len); |
| | 3601 | name_slice = name.toSlice(coff); |
| | 3602 | break :parent_name coff.getOrPutStringAssumeCapacity(name_slice[0..parent_name_slice.len]); |
| | 3603 | } else name; |
| | 3604 | |
| | 3605 | break :blk .{ name_slice, parent_name }; |
| | 3606 | }; |
| | 3607 | |
| | 3608 | coff.string_bytes.lockPointers(); |
| | 3609 | defer coff.string_bytes.unlockPointers(); |
| | 3610 | |
| | 3611 | const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, attributes)).symbol(coff); |
| 3560 | try coff.nodes.ensureUnusedCapacity(gpa, 1); | 3612 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 3561 | try coff.symbols.ensureUnusedCapacity(gpa, 1); | 3613 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 3562 | const parent_ni = parent.node(coff); | 3614 | const parent_ni = parent.node(coff); |
| ... | @@ -3608,7 +3660,7 @@ fn objectSectionMapIndex( | ... | @@ -3608,7 +3660,7 @@ fn objectSectionMapIndex( |
| 3608 | name, | 3660 | name, |
| 3609 | .object, | 3661 | .object, |
| 3610 | .fromFlags(sym.section_number.header(coff).flags), | 3662 | .fromFlags(sym.section_number.header(coff).flags), |
| 3611 | effective_attributes, | 3663 | attributes, |
| 3612 | ); | 3664 | ); |
| 3613 | | 3665 | |
| 3614 | return osmi; | 3666 | return osmi; |
| ... | @@ -4542,7 +4594,7 @@ fn loadObject( | ... | @@ -4542,7 +4594,7 @@ fn loadObject( |
| 4542 | }, | 4594 | }, |
| 4543 | .external => { | 4595 | .external => { |
| 4544 | const global_gop = try coff.getOrPutGlobalSymbol(.{ | 4596 | const global_gop = try coff.getOrPutGlobalSymbol(.{ |
| 4545 | .name = symbol.name.toSlice(coff), | 4597 | .name = symbol.name, |
| 4546 | }); | 4598 | }); |
| 4547 | | 4599 | |
| 4548 | // TODO: What if the same symbol is incorrectly defined twice in this obj? | 4600 | // TODO: What if the same symbol is incorrectly defined twice in this obj? |
| ... | @@ -4749,7 +4801,7 @@ fn loadObject( | ... | @@ -4749,7 +4801,7 @@ fn loadObject( |
| 4749 | continue; | 4801 | continue; |
| 4750 | }, | 4802 | }, |
| 4751 | .weak_external => |alias_index| { | 4803 | .weak_external => |alias_index| { |
| 4752 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) }); | 4804 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name }); |
| 4753 | symbol.si = global_gop.value_ptr.si; | 4805 | symbol.si = global_gop.value_ptr.si; |
| 4754 | if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) { | 4806 | if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) { |
| 4755 | const sym = symbol.si.get(coff); | 4807 | const sym = symbol.si.get(coff); |
| ... | @@ -4788,7 +4840,7 @@ fn loadObject( | ... | @@ -4788,7 +4840,7 @@ fn loadObject( |
| 4788 | break :sym value; | 4840 | break :sym value; |
| 4789 | }, | 4841 | }, |
| 4790 | .external => |value| { | 4842 | .external => |value| { |
| 4791 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) }); | 4843 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name }); |
| 4792 | symbol.si = global_gop.value_ptr.si; | 4844 | symbol.si = global_gop.value_ptr.si; |
| 4793 | if (global_gop.found_existing) | 4845 | if (global_gop.found_existing) |
| 4794 | return coff.failMultipleDefinitions( | 4846 | return coff.failMultipleDefinitions( |
| ... | @@ -4824,7 +4876,7 @@ fn loadObject( | ... | @@ -4824,7 +4876,7 @@ fn loadObject( |
| 4824 | }, | 4876 | }, |
| 4825 | .external => { | 4877 | .external => { |
| 4826 | assert(index != section.comdat_psi.unwrap()); | 4878 | assert(index != section.comdat_psi.unwrap()); |
| 4827 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) }); | 4879 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name }); |
| 4828 | symbol.si = global_gop.value_ptr.si; | 4880 | symbol.si = global_gop.value_ptr.si; |
| 4829 | | 4881 | |
| 4830 | const sym = symbol.si.get(coff); | 4882 | const sym = symbol.si.get(coff); |
| ... | @@ -4908,7 +4960,7 @@ fn loadObject( | ... | @@ -4908,7 +4960,7 @@ fn loadObject( |
| 4908 | assert(symbol.section_number == .UNDEFINED); | 4960 | assert(symbol.section_number == .UNDEFINED); |
| 4909 | switch (symbol.value) { | 4961 | switch (symbol.value) { |
| 4910 | .external => |size| { | 4962 | .external => |size| { |
| 4911 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) }); | 4963 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name }); |
| 4912 | symbol.si = global_gop.value_ptr.si; | 4964 | symbol.si = global_gop.value_ptr.si; |
| 4913 | if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) { | 4965 | if (!global_gop.found_existing or symbol.si.get(coff).ni == .none) { |
| 4914 | const sym = symbol.si.get(coff); | 4966 | const sym = symbol.si.get(coff); |
| ... | @@ -5963,12 +6015,12 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5963,12 +6015,12 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5963 | break :task; | 6015 | break :task; |
| 5964 | } | 6016 | } |
| 5965 | if (coff.pending_input) |pending_iami| { | 6017 | if (coff.pending_input) |pending_iami| { |
| 5966 | const name_slice = pending_iami.member(coff).name.toSlice(coff); | | |
| 5967 | const sub_prog_node = coff.input_prog_node.start( | 6018 | const sub_prog_node = coff.input_prog_node.start( |
| 5968 | name_slice, | 6019 | pending_iami.member(coff).name.toSlice(coff), |
| 5969 | 0, | 6020 | 0, |
| 5970 | ); | 6021 | ); |
| 5971 | defer sub_prog_node.end(); | 6022 | defer sub_prog_node.end(); |
| | 6023 | |
| 5972 | coff.pending_input = null; | 6024 | coff.pending_input = null; |
| 5973 | coff.flushInputMember(pending_iami) catch |err| switch (err) { | 6025 | coff.flushInputMember(pending_iami) catch |err| switch (err) { |
| 5974 | error.OutOfMemory => return error.OutOfMemory, | 6026 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -5976,7 +6028,7 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5976,7 +6028,7 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5976 | "linker failed to load archive member '{f}{f}': {t}", | 6028 | "linker failed to load archive member '{f}{f}': {t}", |
| 5977 | .{ | 6029 | .{ |
| 5978 | pending_iami.member(coff).iai.path(coff), | 6030 | pending_iami.member(coff).iai.path(coff), |
| 5979 | fmtMemberNameString(name_slice), | 6031 | fmtMemberNameString(pending_iami.member(coff).name.toSlice(coff)), |
| 5980 | e, | 6032 | e, |
| 5981 | }, | 6033 | }, |
| 5982 | ), | 6034 | ), |
| ... | @@ -6246,9 +6298,9 @@ fn aliasGlobal(coff: *Coff, gmi: Node.GlobalMapIndex, alias_si: Symbol.Index) !v | ... | @@ -6246,9 +6298,9 @@ fn aliasGlobal(coff: *Coff, gmi: Node.GlobalMapIndex, alias_si: Symbol.Index) !v |
| 6246 | assert(sym.section_number == .UNDEFINED); | 6298 | assert(sym.section_number == .UNDEFINED); |
| 6247 | assert(sym.loc_relocs == .none); | 6299 | assert(sym.loc_relocs == .none); |
| 6248 | | 6300 | |
| 6249 | log.debug("aliasGlobal({s}, {?s}) {d}->{d} ({?s})", .{ | 6301 | log.debug("aliasGlobal({s}, {f}) {d}->{d} ({?s})", .{ |
| 6250 | gmi.name(coff).toSlice(coff), | 6302 | gmi.name(coff).toSlice(coff), |
| 6251 | gmi.libName(coff).toSlice(coff), | 6303 | fmtExternLibName(coff, gmi.libName(coff)), |
| 6252 | si, | 6304 | si, |
| 6253 | alias_si, | 6305 | alias_si, |
| 6254 | if (alias_sym.gmi != .none) alias_sym.gmi.name(coff).toSlice(coff) else null, | 6306 | if (alias_sym.gmi != .none) alias_sym.gmi.name(coff).toSlice(coff) else null, |
| ... | @@ -6286,10 +6338,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6286,10 +6338,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6286 | const si = gmi.symbol(coff); | 6338 | const si = gmi.symbol(coff); |
| 6287 | | 6339 | |
| 6288 | log.debug( | 6340 | log.debug( |
| 6289 | "flushGlobal({s}, {?s}) = n{d} {d}@{d}", | 6341 | "flushGlobal({s}, {f}) = n{d} {d}@{d}", |
| 6290 | .{ | 6342 | .{ |
| 6291 | name.toSlice(coff), | 6343 | name.toSlice(coff), |
| 6292 | gmi.libName(coff).toSlice(coff), | 6344 | fmtExternLibName(coff, gmi.libName(coff)), |
| 6293 | si.get(coff).ni, | 6345 | si.get(coff).ni, |
| 6294 | si, | 6346 | si, |
| 6295 | si.get(coff).section_number, | 6347 | si.get(coff).section_number, |
| ... | @@ -6322,16 +6374,18 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6322,16 +6374,18 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6322 | | 6374 | |
| 6323 | const import: Import = import: { | 6375 | const import: Import = import: { |
| 6324 | const sym = si.get(coff); | 6376 | const sym = si.get(coff); |
| 6325 | const name_slice = name.toSlice(coff); | 6377 | const imp_match, const name_len = blk: { |
| 6326 | const imp_match = std.mem.startsWith(u8, name_slice, imp_prefix); | 6378 | const name_slice = name.toSlice(coff); |
| | 6379 | break :blk .{ std.mem.startsWith(u8, name_slice, imp_prefix), name_slice.len }; |
| | 6380 | }; |
| 6327 | | 6381 | |
| 6328 | // Globals may have the __imp_ prefix already if they are undef externals from another input. | 6382 | // Globals may have the __imp_ prefix already if they are undef externals from another input. |
| 6329 | assert(sym.flags.dll_storage_class != .dllexport); | 6383 | assert(sym.flags.dll_storage_class != .dllexport); |
| 6330 | const search_name, const is_imp = if (imp_match or sym.flags.dll_storage_class != .dllimport) | 6384 | const search_name, const is_imp = if (imp_match or sym.flags.dll_storage_class != .dllimport) |
| 6331 | .{ name, imp_match } | 6385 | .{ name, imp_match } |
| 6332 | else name: { | 6386 | else name: { |
| 6333 | try coff.ensureUnusedStringCapacity(imp_prefix.len + name_slice.len); | 6387 | try coff.ensureUnusedStringCapacity(imp_prefix.len + name_len); |
| 6334 | const imp_name = try gpa.print(imp_prefix ++ "{s}", .{name_slice}); | 6388 | const imp_name = try gpa.print(imp_prefix ++ "{s}", .{name.toSlice(coff)}); |
| 6335 | defer gpa.free(imp_name); | 6389 | defer gpa.free(imp_name); |
| 6336 | break :name .{ coff.getOrPutStringAssumeCapacity(imp_name), true }; | 6390 | break :name .{ coff.getOrPutStringAssumeCapacity(imp_name), true }; |
| 6337 | }; | 6391 | }; |
| ... | @@ -6364,68 +6418,73 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6364,68 +6418,73 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6364 | while (true) { | 6418 | while (true) { |
| 6365 | const archive_sym = &coff.input_archive_symbols.items[@backingInt(iter)]; | 6419 | const archive_sym = &coff.input_archive_symbols.items[@backingInt(iter)]; |
| 6366 | const member = &coff.input_archive_members.items[@backingInt(archive_sym.iami)]; | 6420 | const member = &coff.input_archive_members.items[@backingInt(archive_sym.iami)]; |
| 6367 | member: switch (member.content) { | 6421 | const lib_name_matches = match: switch (gmi.libName(coff)) { |
| 6368 | .object => if (!member.flags.is_loaded) { | 6422 | .any => true, |
| 6369 | if (gmi.libName(coff).unwrap()) |lib_name| | 6423 | .lib_c => { |
| 6370 | if (!std.ascii.eqlIgnoreCase( | 6424 | // TODO: Need a flag to indicate if this member is from a libc archive |
| 6371 | lib_name.toSlice(coff), | 6425 | const is_libc_archive = true; |
| 6372 | member.iai.path(coff).stem(), | | |
| 6373 | )) break :member; | | |
| 6374 | | | |
| 6375 | // Try loading the input member and then retry. | | |
| 6376 | // This could still be a member containing imports | | |
| 6377 | // that use the older non-IMPORT_HEADER method. | | |
| 6378 | coff.pending_input = archive_sym.iami; | | |
| 6379 | return false; | | |
| 6380 | }, | | |
| 6381 | .import => |import| { | | |
| 6382 | if (gmi.libName(coff).unwrap()) |lib_name| | | |
| 6383 | if (!std.ascii.eqlIgnoreCase( | | |
| 6384 | import.lib_name.toSlice(coff), | | |
| 6385 | lib_name.toSlice(coff), | | |
| 6386 | )) break :member; | | |
| 6387 | | | |
| 6388 | const imp_name: String.Optional = name: switch (import.name_type) { | | |
| 6389 | .NAME, | | |
| 6390 | .NAME_NOPREFIX, | | |
| 6391 | .NAME_UNDECORATE, | | |
| 6392 | => |tag| { | | |
| 6393 | const symbol_name: []const u8 = import.symbol_name.toSlice(coff); | | |
| 6394 | const end_match = std.mem.endsWith(u8, name_slice, symbol_name); | | |
| 6395 | const len_delta = name_slice.len -% symbol_name.len; | | |
| 6396 | if (!end_match or | | |
| 6397 | (!imp_match and len_delta != 0) or | | |
| 6398 | (imp_match and len_delta != imp_prefix.len)) | | |
| 6399 | return comp.link_diags.fail( | | |
| 6400 | "global '{s}' has mismatched symbol name in import header: '{s}'", | | |
| 6401 | .{ | | |
| 6402 | name.toSlice(coff), | | |
| 6403 | import.symbol_name.toSlice(coff), | | |
| 6404 | }, | | |
| 6405 | ); | | |
| 6406 | | | |
| 6407 | const imp_name = if (tag == .NAME) import.symbol_name else undecorated: { | | |
| 6408 | var imp_name = std.mem.trimStart(u8, symbol_name, "?@_"); | | |
| 6409 | if (tag == .NAME_UNDECORATE) | | |
| 6410 | imp_name = std.mem.sliceTo(imp_name, '@'); | | |
| 6411 | | 6426 | |
| 6412 | try coff.ensureUnusedStringCapacity(imp_name.len); | 6427 | break :match is_libc_archive; |
| 6413 | break :undecorated coff.getOrPutStringAssumeCapacity(imp_name); | 6428 | }, |
| 6414 | }; | 6429 | .explicit => |lib_name| std.ascii.eqlIgnoreCase( |
| | 6430 | lib_name.toSlice(coff), |
| | 6431 | member.iai.path(coff).stem(), |
| | 6432 | ), |
| | 6433 | }; |
| 6415 | | 6434 | |
| 6416 | break :name imp_name.toOptional(); | 6435 | if (lib_name_matches) { |
| 6417 | }, | 6436 | switch (member.content) { |
| 6418 | .ORDINAL => break :name .none, | 6437 | .object => if (!member.flags.is_loaded) { |
| 6419 | else => |t| return comp.link_diags.fail("TODO handle name_type {t}", .{t}), | 6438 | // Try loading the input member and then retry. |
| 6420 | }; | 6439 | // This could still be a member containing imports |
| | 6440 | // that use the older non-IMPORT_HEADER method. |
| | 6441 | coff.pending_input = archive_sym.iami; |
| | 6442 | return false; |
| | 6443 | }, |
| | 6444 | .import => |import| { |
| | 6445 | const imp_name: String.Optional = name: switch (import.name_type) { |
| | 6446 | .NAME, |
| | 6447 | .NAME_NOPREFIX, |
| | 6448 | .NAME_UNDECORATE, |
| | 6449 | => |tag| { |
| | 6450 | const symbol_name: []const u8 = import.symbol_name.toSlice(coff); |
| | 6451 | const name_slice = name.toSlice(coff); |
| | 6452 | const end_match = std.mem.endsWith(u8, name_slice, symbol_name); |
| | 6453 | const len_delta = name_slice.len -% symbol_name.len; |
| | 6454 | if (!end_match or |
| | 6455 | (!imp_match and len_delta != 0) or |
| | 6456 | (imp_match and len_delta != imp_prefix.len)) |
| | 6457 | return comp.link_diags.fail( |
| | 6458 | "global '{s}' has mismatched symbol name in import header: '{s}'", |
| | 6459 | .{ |
| | 6460 | name.toSlice(coff), |
| | 6461 | import.symbol_name.toSlice(coff), |
| | 6462 | }, |
| | 6463 | ); |
| | 6464 | |
| | 6465 | const imp_name = if (tag == .NAME) import.symbol_name else undecorated: { |
| | 6466 | var imp_name = std.mem.trimStart(u8, symbol_name, "?@_"); |
| | 6467 | if (tag == .NAME_UNDECORATE) |
| | 6468 | imp_name = std.mem.sliceTo(imp_name, '@'); |
| | 6469 | |
| | 6470 | try coff.ensureUnusedStringCapacity(imp_name.len); |
| | 6471 | break :undecorated coff.getOrPutStringAssumeCapacity(imp_name); |
| | 6472 | }; |
| | 6473 | |
| | 6474 | break :name imp_name.toOptional(); |
| | 6475 | }, |
| | 6476 | .ORDINAL => break :name .none, |
| | 6477 | else => |t| return comp.link_diags.fail("TODO handle name_type {t}", .{t}), |
| | 6478 | }; |
| 6421 | | 6479 | |
| 6422 | break :import .{ | 6480 | break :import .{ |
| 6423 | .lib_name = import.lib_name, | 6481 | .lib_name = import.lib_name, |
| 6424 | .name = imp_name, | 6482 | .name = imp_name, |
| 6425 | .ordinal_hint = import.import_ordinal_hint, | 6483 | .ordinal_hint = import.import_ordinal_hint, |
| 6426 | .kind = if (import.type == .CODE and !is_imp) .thunk else .iat_ptr, | 6484 | .kind = if (import.type == .CODE and !is_imp) .thunk else .iat_ptr, |
| 6427 | }; | 6485 | }; |
| 6428 | }, | 6486 | }, |
| | 6487 | } |
| 6429 | } | 6488 | } |
| 6430 | | 6489 | |
| 6431 | if (archive_sym.next == iter) break; | 6490 | if (archive_sym.next == iter) break; |
| ... | @@ -6442,7 +6501,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6442,7 +6501,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6442 | // Convert an unresolved weak external that itself refers to an undef external | 6501 | // Convert an unresolved weak external that itself refers to an undef external |
| 6443 | // into a (possibly new) global, so it can be resolved separately. | 6502 | // into a (possibly new) global, so it can be resolved separately. |
| 6444 | const alias_gop = try coff.getOrPutGlobalSymbol(.{ | 6503 | const alias_gop = try coff.getOrPutGlobalSymbol(.{ |
| 6445 | .name = sym.value.weak_alias_name.toSlice(coff), | 6504 | .name = sym.value.weak_alias_name, |
| 6446 | }); | 6505 | }); |
| 6447 | try coff.aliasGlobal(gmi, alias_gop.value_ptr.si); | 6506 | try coff.aliasGlobal(gmi, alias_gop.value_ptr.si); |
| 6448 | return true; | 6507 | return true; |
| ... | @@ -6462,12 +6521,15 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6462,12 +6521,15 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6462 | // This is necessary for certain ntdll symbols, such as LdrRegisterDllNotification, | 6521 | // This is necessary for certain ntdll symbols, such as LdrRegisterDllNotification, |
| 6463 | // which are not in the implib. | 6522 | // which are not in the implib. |
| 6464 | if (sym.flags.type != .unknown) { | 6523 | if (sym.flags.type != .unknown) { |
| 6465 | if (gmi.libName(coff).unwrap()) |lib_name| break :import .{ | 6524 | switch (gmi.libName(coff)) { |
| 6466 | .lib_name = lib_name, | 6525 | .explicit => |lib_name| break :import .{ |
| 6467 | .name = name.toOptional(), | 6526 | .lib_name = lib_name, |
| 6468 | .ordinal_hint = 0, | 6527 | .name = name.toOptional(), |
| 6469 | .kind = if (sym.flags.type == .code) .thunk else .iat_ptr, | 6528 | .ordinal_hint = 0, |
| 6470 | }; | 6529 | .kind = if (sym.flags.type == .code) .thunk else .iat_ptr, |
| | 6530 | }, |
| | 6531 | else => {}, |
| | 6532 | } |
| 6471 | } | 6533 | } |
| 6472 | | 6534 | |
| 6473 | return true; | 6535 | return true; |
| ... | @@ -6478,10 +6540,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6478,10 +6540,10 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6478 | | 6540 | |
| 6479 | const target_endian = coff.targetEndian(); | 6541 | const target_endian = coff.targetEndian(); |
| 6480 | const addr_info = coff.targetAddrInfo(); | 6542 | const addr_info = coff.targetAddrInfo(); |
| 6481 | const lib_name = import.lib_name.toSlice(coff); | 6543 | const lib_name_slice = import.lib_name.toSlice(coff); |
| 6482 | const gop = try coff.import_table.entries.getOrPutAdapted( | 6544 | const gop = try coff.import_table.entries.getOrPutAdapted( |
| 6483 | gpa, | 6545 | gpa, |
| 6484 | lib_name, | 6546 | lib_name_slice, |
| 6485 | ImportTable.Adapter{ .coff = coff }, | 6547 | ImportTable.Adapter{ .coff = coff }, |
| 6486 | ); | 6548 | ); |
| 6487 | const import_hint_name_align: Alignment = .@"2"; | 6549 | const import_hint_name_align: Alignment = .@"2"; |
| ... | @@ -6493,7 +6555,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6493,7 +6555,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6493 | @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2), | 6555 | @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2), |
| 6494 | ); | 6556 | ); |
| 6495 | const import_hint_name_table_len = | 6557 | const import_hint_name_table_len = |
| 6496 | import_hint_name_align.forward(lib_name.len + ".dll".len + 1); | 6558 | import_hint_name_align.forward(lib_name_slice.len + ".dll".len + 1); |
| 6497 | const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?; | 6559 | const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?; |
| 6498 | const import_lookup_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{ | 6560 | const import_lookup_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{ |
| 6499 | .size = addr_info.size * 2, | 6561 | .size = addr_info.size * 2, |
| ... | @@ -6528,9 +6590,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6528,9 +6590,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6528 | .hint_name_len = @intCast(import_hint_name_table_len), | 6590 | .hint_name_len = @intCast(import_hint_name_table_len), |
| 6529 | }; | 6591 | }; |
| 6530 | const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf); | 6592 | const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf); |
| 6531 | @memcpy(import_hint_name_slice[0..lib_name.len], lib_name); | 6593 | @memcpy(import_hint_name_slice[0..lib_name_slice.len], lib_name_slice); |
| 6532 | @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll"); | 6594 | @memcpy(import_hint_name_slice[lib_name_slice.len..][0..".dll".len], ".dll"); |
| 6533 | @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0); | 6595 | @memset(import_hint_name_slice[lib_name_slice.len + ".dll".len ..], 0); |
| 6534 | coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @fromBackingInt(@intCast(gop.index)) }); | 6596 | coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @fromBackingInt(@intCast(gop.index)) }); |
| 6535 | coff.nodes.appendAssumeCapacity(.{ .import_address_table = @fromBackingInt(@intCast(gop.index)) }); | 6597 | coff.nodes.appendAssumeCapacity(.{ .import_address_table = @fromBackingInt(@intCast(gop.index)) }); |
| 6536 | coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @fromBackingInt(@intCast(gop.index)) }); | 6598 | coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @fromBackingInt(@intCast(gop.index)) }); |
| ... | @@ -6555,7 +6617,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6555,7 +6617,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6555 | | 6617 | |
| 6556 | log.debug( | 6618 | log.debug( |
| 6557 | "flushGlobalImport({s}, {?s}, {d}, {s})", | 6619 | "flushGlobalImport({s}, {?s}, {d}, {s})", |
| 6558 | .{ name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name }, | 6620 | .{ name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name_slice }, |
| 6559 | ); | 6621 | ); |
| 6560 | | 6622 | |
| 6561 | const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{ | 6623 | const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{ |
| ... | @@ -7662,8 +7724,10 @@ fn fmtGlobalName(coff: *Coff, gmi: Node.GlobalMapIndex) std.fmt.Alt(FmtGlobalNam | ... | @@ -7662,8 +7724,10 @@ fn fmtGlobalName(coff: *Coff, gmi: Node.GlobalMapIndex) std.fmt.Alt(FmtGlobalNam |
| 7662 | fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void { | 7724 | fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!void { |
| 7663 | if (data.gmi == .none) return; | 7725 | if (data.gmi == .none) return; |
| 7664 | try w.writeAll(data.gmi.name(data.coff).toSlice(data.coff)); | 7726 | try w.writeAll(data.gmi.name(data.coff).toSlice(data.coff)); |
| 7665 | if (data.gmi.libName(data.coff).unwrap()) |lib_name| | 7727 | switch (data.gmi.libName(data.coff)) { |
| 7666 | try w.print("({s})", .{lib_name.toSlice(data.coff)}); | 7728 | .explicit => |lib_name| try w.print(" ({s}.dll)", .{lib_name.toSlice(data.coff)}), |
| | 7729 | else => {}, |
| | 7730 | } |
| 7667 | } | 7731 | } |
| 7668 | | 7732 | |
| 7669 | fn printNodeName( | 7733 | fn printNodeName( |
| ... | @@ -7705,12 +7769,7 @@ fn printNodeName( | ... | @@ -7705,12 +7769,7 @@ fn printNodeName( |
| 7705 | inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{ | 7769 | inline .pseudo_section, .object_section => |smi| try w.print("({s})", .{ |
| 7706 | smi.name(coff).toSlice(coff), | 7770 | smi.name(coff).toSlice(coff), |
| 7707 | }), | 7771 | }), |
| 7708 | .import_thunk, | 7772 | .import_thunk => |gmi| try w.print("({f})", .{fmtGlobalName(coff, gmi)}), |
| 7709 | => |gmi| { | | |
| 7710 | try w.writeByte('('); | | |
| 7711 | if (gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name}); | | |
| 7712 | try w.print("{s})", .{gmi.name(coff).toSlice(coff)}); | | |
| 7713 | }, | | |
| 7714 | .nav => |nmi| { | 7773 | .nav => |nmi| { |
| 7715 | const zcu = coff.base.comp.zcu.?; | 7774 | const zcu = coff.base.comp.zcu.?; |
| 7716 | const ip = &zcu.intern_pool; | 7775 | const ip = &zcu.intern_pool; |
| ... | @@ -7736,11 +7795,7 @@ fn printNodeName( | ... | @@ -7736,11 +7795,7 @@ fn printNodeName( |
| 7736 | }), | 7795 | }), |
| 7737 | .builtin => |si| { | 7796 | .builtin => |si| { |
| 7738 | const sym = si.get(coff); | 7797 | const sym = si.get(coff); |
| 7739 | if (sym.gmi != .none) { | 7798 | if (sym.gmi != .none) try w.print("({f})", .{fmtGlobalName(coff, sym.gmi)}); |
| 7740 | try w.writeByte('('); | | |
| 7741 | if (sym.gmi.libName(coff).toSlice(coff)) |lib_name| try w.print("{s}.dll, ", .{lib_name}); | | |
| 7742 | try w.print("{s})", .{sym.gmi.name(coff).toSlice(coff)}); | | |
| 7743 | } | | |
| 7744 | }, | 7799 | }, |
| 7745 | } | 7800 | } |
| 7746 | } | 7801 | } |