authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:35-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:26:56-04:00
log8a1376f5d001d79cb92dd67547c6a20661fe6bb4
tree0678af7e74acdd49cba488a6b5af5af2ab006818
parent8781abd79b5d8c8ce155b065c874d09076491e26

Coff: fixes for .gnu

- has_exports -> has_aliases, and use this for __(CTOR|DTOR)_LIST__ symbols, which weren't being updated properly - fix stale usage of sym ptr in flushGlobal

1 files changed, 230 insertions(+), 222 deletions(-)

src/link/Coff.zig+230-222
......@@ -912,7 +912,7 @@ pub const Symbol = struct {
912912 dll_storage_class: DllStorageClass,
913913 // Only defined for .alias_si and .alias_name
914914 weak_external_strat: WeakExternalStrat,
915 has_exports: bool,
915 has_aliases: bool,
916916 _: u7 = 0,
917917 },
918918 /// Relocations contained within this symbol
......@@ -927,9 +927,9 @@ pub const Symbol = struct {
927927 /// Only valid when .ni == .input_section and .value_tag == .node_offset
928928 /// TODO: This is only used for name lookups, could just be String?
929929 isli: Node.InputSection.LocalIndex,
930 /// Only valid if flags.has_exports is set. The first in a contiguous
931 /// list of symbols that are exports of this symbol.
932 first_export_si: Symbol.Index,
930 /// Only valid if flags.has_aliases is set. The first in a contiguous
931 /// list of symbols that are aliases of this symbol.
932 first_alias_si: Symbol.Index,
933933 },
934934
935935 pub const DllStorageClass = enum(u2) {
......@@ -946,8 +946,8 @@ pub const Symbol = struct {
946946
947947 const ValueTag = enum(u2) {
948948 node_offset,
949 alias_si,
950 alias_name,
949 weak_alias_si,
950 weak_alias_name,
951951 size,
952952 };
953953
......@@ -957,12 +957,12 @@ pub const Symbol = struct {
957957 node_offset: u32,
958958 /// This is a weak alias that can replace this symbol
959959 /// Globals only.
960 alias_si: Symbol.Index,
960 weak_alias_si: Symbol.Index,
961961 /// For weak externals that have an alias that is also an undef
962962 /// external, this is the name of the alias global that should
963963 /// be generated if this symbol is not resolved.
964964 /// Globals only.
965 alias_name: String,
965 weak_alias_name: String,
966966 /// The symbol size, or 0 if unknown
967967 size: u32,
968968 };
......@@ -1069,8 +1069,8 @@ pub const Symbol = struct {
10691069 si.applyLocationRelocs(coff);
10701070 si.applyTargetRelocs(coff, .none);
10711071
1072 if (sym.flags.has_exports) {
1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_export_si)..]) |*export_sym| {
1072 if (sym.flags.has_aliases) {
1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_alias_si)..]) |*export_sym| {
10741074 if (export_sym.ni != sym.ni) break;
10751075 export_sym.rva = sym.rva;
10761076 const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr);
......@@ -2203,6 +2203,9 @@ pub fn initBuiltins(coff: *Coff) !void {
22032203 );
22042204
22052205 const start_sym = start_osmi.symbol(coff).get(coff);
2206 start_sym.extra = .{ .first_alias_si = @enumFromInt(coff.symbols.items.len) };
2207 start_sym.flags.has_aliases = true;
2208
22062209 try start_sym.ni.resize(&coff.mf, gpa, addr_info.size);
22072210 const start_slice = start_sym.ni.slice(&coff.mf);
22082211 switch (addr_info.magic) {
......@@ -2561,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
25612564 .type = .unknown,
25622565 .dll_storage_class = .default,
25632566 .weak_external_strat = undefined,
2564 .has_exports = false,
2567 .has_aliases = false,
25652568 },
25662569 .loc_relocs = .none,
25672570 .target_relocs = .none,
......@@ -4443,10 +4446,10 @@ fn loadObject(
44434446 .external => {
44444447 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
44454448 // If the alias itself is an undef external, we need to wait until flushing the weak
4446 // external global before creating a global for the alias, as another input
4447 // could still provide the weak external.
4449 // external global before creating a global for the alias, as another input could
4450 // still provide the weak external.
44484451 const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);
4449 weak_sym.setValue(.{ .alias_name = symbol.name });
4452 weak_sym.setValue(.{ .weak_alias_name = symbol.name });
44504453 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
44514454 }
44524455
......@@ -4476,9 +4479,9 @@ fn loadObject(
44764479 alias.weak_external_psi = .wrap(@intCast(i));
44774480 } else {
44784481 sym.setValue(if (alias.si.unwrap()) |alias_si| .{
4479 .alias_si = alias_si,
4482 .weak_alias_si = alias_si,
44804483 } else .{
4481 .alias_name = alias.name,
4484 .weak_alias_name = alias.name,
44824485 });
44834486 sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux;
44844487 }
......@@ -4521,7 +4524,7 @@ fn loadObject(
45214524 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
45224525 assert(symbol.si != .null);
45234526 const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);
4524 weak_sym.setValue(.{ .alias_si = symbol.si });
4527 weak_sym.setValue(.{ .weak_alias_si = symbol.si });
45254528 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
45264529 }
45274530
......@@ -5985,17 +5988,16 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
59855988 const gpa = comp.gpa;
59865989 const gn = gmi.globalName(coff);
59875990 const si = gmi.symbol(coff);
5988 const sym = si.get(coff);
59895991 const is_late = gmi.unwrap().? < coff.global_pending_index;
59905992
59915993 log.debug(
59925994 "flushGlobal({s}, {?s}, {}) = n{d} {d}@{d}",
5993 .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), is_late, sym.ni, si, sym.section_number },
5995 .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), is_late, si.get(coff).ni, si, si.get(coff).section_number },
59945996 );
59955997
59965998 if (!coff.isImage()) {
59975999 try coff.pendingSymbolTableEntry(si);
5998 if (coff.isArchive() and sym.ni != .none)
6000 if (coff.isArchive() and si.get(coff).ni != .none)
59996001 try coff.ensureMemberSymbol(
60006002 coff.getNode(Node.known.zcu_member).archive_member,
60016003 gn.name,
......@@ -6004,6 +6006,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
60046006 return true;
60056007 }
60066008
6009 if (si.get(coff).ni != .none)
6010 return true;
6011
60076012 const Import = struct {
60086013 lib_name: String,
60096014 name: String.Optional,
......@@ -6014,7 +6019,8 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
60146019 },
60156020 };
60166021
6017 const opt_import: ?Import = if (sym.ni == .none) import: {
6022 const import: Import = import: {
6023 const sym = si.get(coff);
60186024 const global_name = gn.name.toSlice(coff);
60196025 const imp_match = std.mem.startsWith(u8, global_name, imp_prefix);
60206026
......@@ -6030,7 +6036,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
60306036
60316037 const opt_alt_search_name = coff.alternate_names.get(search_name);
60326038 const search_libs = if (is_late) switch (sym.flags.value_tag) {
6033 .alias_si, .alias_name => switch (sym.flags.weak_external_strat) {
6039 .weak_alias_si, .weak_alias_name => switch (sym.flags.weak_external_strat) {
60346040 .no_library => false,
60356041 .library,
60366042 .alias,
......@@ -6044,7 +6050,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
60446050 else => true,
60456051 } else search_libs: {
60466052 if (switch (sym.flags.value_tag) {
6047 .alias_si, .alias_name => true,
6053 .weak_alias_si, .weak_alias_name => true,
60486054 else => opt_alt_search_name != null,
60496055 }) {
60506056 // We need to wait until all exports are known before resolving these
......@@ -6137,16 +6143,18 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
61376143 }
61386144
61396145 switch (sym.flags.value_tag) {
6140 .alias_si => {
6146 .weak_alias_si => {
61416147 assert(is_late);
6142 try coff.aliasGlobal(gmi, sym.value.alias_si);
6148 try coff.aliasGlobal(gmi, sym.value.weak_alias_si);
61436149 return true;
61446150 },
6145 .alias_name => {
6151 .weak_alias_name => {
61466152 assert(is_late);
61476153 // Convert an unresolved weak external that itself refers to an undef external
61486154 // into a (possibly new) global, so it can be resolved separately.
6149 const alias_gop = try coff.getOrPutGlobalSymbol(.{ .name = sym.value.alias_name.toSlice(coff) });
6155 const alias_gop = try coff.getOrPutGlobalSymbol(.{
6156 .name = sym.value.weak_alias_name.toSlice(coff),
6157 });
61506158 try coff.aliasGlobal(gmi, alias_gop.value_ptr.*);
61516159 return true;
61526160 },
......@@ -6174,216 +6182,216 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
61746182 };
61756183 }
61766184
6177 break :import null;
6178 } else null;
6185 return true;
6186 };
61796187
6180 if (opt_import) |import| {
6181 assert(sym.ni == .none);
6182 const lib_name = import.lib_name.toSlice(coff);
6188 const lib_name = import.lib_name.toSlice(coff);
61836189
6184 try coff.nodes.ensureUnusedCapacity(gpa, 4);
6185 try coff.symbols.ensureUnusedCapacity(gpa, 1);
6190 try coff.nodes.ensureUnusedCapacity(gpa, 4);
6191 try coff.symbols.ensureUnusedCapacity(gpa, 1);
61866192
6187 const target_endian = coff.targetEndian();
6188 const addr_info = coff.targetAddrInfo();
6189 const gop = try coff.import_table.entries.getOrPutAdapted(
6193 const sym = si.get(coff);
6194 const target_endian = coff.targetEndian();
6195 const addr_info = coff.targetAddrInfo();
6196 const gop = try coff.import_table.entries.getOrPutAdapted(
6197 gpa,
6198 lib_name,
6199 ImportTable.Adapter{ .coff = coff },
6200 );
6201 const import_hint_name_align: std.mem.Alignment = .@"2";
6202 if (!gop.found_existing) {
6203 errdefer _ = coff.import_table.entries.pop();
6204 try coff.import_table.ni.resize(
6205 &coff.mf,
61906206 gpa,
6191 lib_name,
6192 ImportTable.Adapter{ .coff = coff },
6207 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
61936208 );
6194 const import_hint_name_align: std.mem.Alignment = .@"2";
6195 if (!gop.found_existing) {
6196 errdefer _ = coff.import_table.entries.pop();
6197 try coff.import_table.ni.resize(
6198 &coff.mf,
6199 gpa,
6200 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
6201 );
6202 const import_hint_name_table_len =
6203 import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
6204 const idata_section_ni = coff.import_table.ni.parent(&coff.mf);
6205 const import_lookup_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6206 .size = addr_info.size * 2,
6207 .alignment = addr_info.alignment,
6208 .moved = true,
6209 });
6210 const import_address_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6211 .size = addr_info.size * 2,
6212 .alignment = addr_info.alignment,
6213 .moved = true,
6214 });
6215 const import_address_table_si = coff.addSymbolAssumeCapacity();
6216 {
6217 const import_address_table_sym = import_address_table_si.get(coff);
6218 import_address_table_sym.ni = import_address_table_ni;
6219 assert(import_address_table_sym.loc_relocs == .none);
6220 import_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
6221 import_address_table_sym.section_number =
6222 coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
6223 }
6224 const import_hint_name_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6225 .size = import_hint_name_table_len,
6226 .alignment = import_hint_name_align,
6227 .moved = true,
6228 });
6229 gop.value_ptr.* = .{
6230 .import_lookup_table_ni = import_lookup_table_ni,
6231 .import_address_table_si = import_address_table_si,
6232 .import_hint_name_table_ni = import_hint_name_table_ni,
6233 .import_address_table_symbols = .empty,
6234 .len = 0,
6235 .hint_name_len = @intCast(import_hint_name_table_len),
6236 };
6237 const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf);
6238 @memcpy(import_hint_name_slice[0..lib_name.len], lib_name);
6239 @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll");
6240 @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0);
6241 coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @enumFromInt(gop.index) });
6242 coff.nodes.appendAssumeCapacity(.{ .import_address_table = @enumFromInt(gop.index) });
6243 coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @enumFromInt(gop.index) });
6244
6245 const import_directory_entries = coff.importDirectoryTableSlice()[gop.index..][0..2];
6246 import_directory_entries.* = .{ .{
6247 .import_lookup_table_rva = coff.computeNodeRva(import_lookup_table_ni),
6248 .time_date_stamp = 0,
6249 .forwarder_chain = 0,
6250 .name_rva = coff.computeNodeRva(import_hint_name_table_ni),
6251 .import_address_table_rva = coff.computeNodeRva(import_address_table_ni),
6252 }, .{
6253 .import_lookup_table_rva = 0,
6254 .time_date_stamp = 0,
6255 .forwarder_chain = 0,
6256 .name_rva = 0,
6257 .import_address_table_rva = 0,
6258 } };
6259 if (target_endian != native_endian)
6260 std.mem.byteSwapAllFields([2]std.coff.ImportDirectoryEntry, import_directory_entries);
6261 }
6262
6263 log.debug(
6264 "flushGlobalImport({s}, {?s}, {d}, {s})",
6265 .{ gn.name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name },
6266 );
6267
6268 const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{
6269 .iti = @enumFromInt(gop.index),
6270 .name = import.name,
6271 .ordinal_hint = import.ordinal_hint,
6209 const import_hint_name_table_len =
6210 import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
6211 const idata_section_ni = coff.import_table.ni.parent(&coff.mf);
6212 const import_lookup_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6213 .size = addr_info.size * 2,
6214 .alignment = addr_info.alignment,
6215 .moved = true,
62726216 });
6273 if (!iat_symbol_gop.found_existing) {
6274 const import_symbol_index = gop.value_ptr.len;
6275 iat_symbol_gop.value_ptr.* = import_symbol_index;
6276
6277 gop.value_ptr.len = import_symbol_index + 1;
6278 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);
6279
6280 try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6281 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);
6282 try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6283
6284 const opt_name = import.name.toSlice(coff);
6285 const opt_import_hint_name_index = if (opt_name) |name| blk: {
6286 const import_hint_name_index = gop.value_ptr.hint_name_len;
6287 gop.value_ptr.hint_name_len = @intCast(
6288 import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1),
6289 );
6290 try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);
6291 break :blk import_hint_name_index;
6292 } else null;
6293
6294 const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: {
6295 const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);
6296 const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2]));
6297 ordinal_hint.* = std.mem.nativeTo(u16, import.ordinal_hint, target_endian);
6298 @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..opt_name.?.len], opt_name.?);
6299 @memset(import_hint_name_slice[import_hint_name_index + 2 + opt_name.?.len ..], 0);
6300 break :blk coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;
6301 } else 0;
6302
6303 const import_lookup_slice = gop.value_ptr.import_lookup_table_ni.slice(&coff.mf);
6304 const import_address_slice = import_address_table_ni.slice(&coff.mf);
6305 switch (addr_info.magic) {
6306 _ => unreachable,
6307 inline .PE32, .@"PE32+" => |ct_magic| {
6308 const Entry = ImportTable.TableEntry(ct_magic);
6309 const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice));
6310 const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice));
6311 const import_hint_name_rvas: [2]Entry = .{
6312 .{
6313 .payload = if (import.name == .none)
6314 .{ .ordinal = .{ .ordinal = import.ordinal_hint } }
6315 else
6316 .{ .hint_name_rva = @intCast(import_hint_name_rva) },
6317 .is_ordinal = import.name == .none,
6318 },
6319 @bitCast(@as(@typeInfo(Entry).@"struct".backing_integer.?, 0)),
6320 };
6321 if (native_endian != target_endian)
6322 for (import_hint_name_rvas) |*v| std.mem.byteSwapAllFields(Entry, v);
6217 const import_address_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6218 .size = addr_info.size * 2,
6219 .alignment = addr_info.alignment,
6220 .moved = true,
6221 });
6222 const import_address_table_si = coff.addSymbolAssumeCapacity();
6223 {
6224 const import_address_table_sym = import_address_table_si.get(coff);
6225 import_address_table_sym.ni = import_address_table_ni;
6226 assert(import_address_table_sym.loc_relocs == .none);
6227 import_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
6228 import_address_table_sym.section_number =
6229 coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
6230 }
6231 const import_hint_name_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6232 .size = import_hint_name_table_len,
6233 .alignment = import_hint_name_align,
6234 .moved = true,
6235 });
6236 gop.value_ptr.* = .{
6237 .import_lookup_table_ni = import_lookup_table_ni,
6238 .import_address_table_si = import_address_table_si,
6239 .import_hint_name_table_ni = import_hint_name_table_ni,
6240 .import_address_table_symbols = .empty,
6241 .len = 0,
6242 .hint_name_len = @intCast(import_hint_name_table_len),
6243 };
6244 const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf);
6245 @memcpy(import_hint_name_slice[0..lib_name.len], lib_name);
6246 @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll");
6247 @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0);
6248 coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @enumFromInt(gop.index) });
6249 coff.nodes.appendAssumeCapacity(.{ .import_address_table = @enumFromInt(gop.index) });
6250 coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @enumFromInt(gop.index) });
6251
6252 const import_directory_entries = coff.importDirectoryTableSlice()[gop.index..][0..2];
6253 import_directory_entries.* = .{ .{
6254 .import_lookup_table_rva = coff.computeNodeRva(import_lookup_table_ni),
6255 .time_date_stamp = 0,
6256 .forwarder_chain = 0,
6257 .name_rva = coff.computeNodeRva(import_hint_name_table_ni),
6258 .import_address_table_rva = coff.computeNodeRva(import_address_table_ni),
6259 }, .{
6260 .import_lookup_table_rva = 0,
6261 .time_date_stamp = 0,
6262 .forwarder_chain = 0,
6263 .name_rva = 0,
6264 .import_address_table_rva = 0,
6265 } };
6266 if (target_endian != native_endian)
6267 std.mem.byteSwapAllFields([2]std.coff.ImportDirectoryEntry, import_directory_entries);
6268 }
63236269
6324 import_lookup_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
6325 import_address_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
6326 },
6327 }
6328 }
6270 log.debug(
6271 "flushGlobalImport({s}, {?s}, {d}, {s})",
6272 .{ gn.name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name },
6273 );
63296274
6330 assert(sym.loc_relocs == .none);
6331 const iat_offset: u32 = @intCast(addr_info.size * iat_symbol_gop.value_ptr.*);
6332 switch (import.kind) {
6333 .iat_ptr => {
6334 const iat_sym = gop.value_ptr.import_address_table_si.get(coff);
6335 sym.section_number = iat_sym.section_number;
6336 sym.ni = iat_sym.ni;
6337 sym.setValue(.{ .node_offset = iat_offset });
6338 si.flushMoved(coff);
6339 (try gop.value_ptr.import_address_table_symbols.addOne(gpa)).* = si;
6340 },
6341 .thunk => {
6342 sym.section_number = Symbol.Index.text.get(coff).section_number;
6343 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
6344 switch (coff.targetLoad(&coff.headerPtr().machine)) {
6345 else => |tag| @panic(@tagName(tag)),
6346 .AMD64 => {
6347 const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };
6348 const target = &comp.root_mod.resolved_target.result;
6349 const ni = try coff.mf.addLastChildNode(gpa, Symbol.Index.text.node(coff), .{
6350 .alignment = switch (comp.root_mod.optimize_mode) {
6351 .Debug,
6352 .ReleaseSafe,
6353 .ReleaseFast,
6354 => target_util.defaultFunctionAlignment(target),
6355 .ReleaseSmall => target_util.minFunctionAlignment(target),
6356 }.toStdMem(),
6357 .size = init.len,
6358 });
6359 @memcpy(ni.slice(&coff.mf)[0..init.len], &init);
6360 sym.ni = ni;
6361 sym.setValue(.{ .size = init.len });
6362 try coff.addReloc(
6363 si,
6364 init.len - 4,
6365 gop.value_ptr.import_address_table_si,
6366 .{ .known = iat_offset },
6367 .{ .AMD64 = .REL32 },
6368 );
6275 const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{
6276 .iti = @enumFromInt(gop.index),
6277 .name = import.name,
6278 .ordinal_hint = import.ordinal_hint,
6279 });
6280 if (!iat_symbol_gop.found_existing) {
6281 const import_symbol_index = gop.value_ptr.len;
6282 iat_symbol_gop.value_ptr.* = import_symbol_index;
6283
6284 gop.value_ptr.len = import_symbol_index + 1;
6285 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);
6286
6287 try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6288 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);
6289 try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6290
6291 const opt_name = import.name.toSlice(coff);
6292 const opt_import_hint_name_index = if (opt_name) |name| blk: {
6293 const import_hint_name_index = gop.value_ptr.hint_name_len;
6294 gop.value_ptr.hint_name_len = @intCast(
6295 import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1),
6296 );
6297 try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);
6298 break :blk import_hint_name_index;
6299 } else null;
6300
6301 const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: {
6302 const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);
6303 const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2]));
6304 ordinal_hint.* = std.mem.nativeTo(u16, import.ordinal_hint, target_endian);
6305 @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..opt_name.?.len], opt_name.?);
6306 @memset(import_hint_name_slice[import_hint_name_index + 2 + opt_name.?.len ..], 0);
6307 break :blk coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;
6308 } else 0;
6309
6310 const import_lookup_slice = gop.value_ptr.import_lookup_table_ni.slice(&coff.mf);
6311 const import_address_slice = import_address_table_ni.slice(&coff.mf);
6312 switch (addr_info.magic) {
6313 _ => unreachable,
6314 inline .PE32, .@"PE32+" => |ct_magic| {
6315 const Entry = ImportTable.TableEntry(ct_magic);
6316 const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice));
6317 const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice));
6318 const import_hint_name_rvas: [2]Entry = .{
6319 .{
6320 .payload = if (import.name == .none)
6321 .{ .ordinal = .{ .ordinal = import.ordinal_hint } }
6322 else
6323 .{ .hint_name_rva = @intCast(import_hint_name_rva) },
6324 .is_ordinal = import.name == .none,
63696325 },
6370 }
6371 coff.nodes.appendAssumeCapacity(.{ .import_thunk = gmi });
6372 sym.rva = coff.computeNodeRva(sym.ni);
6373 si.applyLocationRelocs(coff);
6326 @bitCast(@as(@typeInfo(Entry).@"struct".backing_integer.?, 0)),
6327 };
6328 if (native_endian != target_endian)
6329 for (import_hint_name_rvas) |*v| std.mem.byteSwapAllFields(Entry, v);
6330
6331 import_lookup_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
6332 import_address_table[import_symbol_index..][0..2].* = import_hint_name_rvas;
63746333 },
63756334 }
63766335 }
63776336
6337 assert(sym.loc_relocs == .none);
6338 const iat_offset: u32 = @intCast(addr_info.size * iat_symbol_gop.value_ptr.*);
6339 switch (import.kind) {
6340 .iat_ptr => {
6341 const iat_sym = gop.value_ptr.import_address_table_si.get(coff);
6342 sym.section_number = iat_sym.section_number;
6343 sym.ni = iat_sym.ni;
6344 sym.setValue(.{ .node_offset = iat_offset });
6345 si.flushMoved(coff);
6346 (try gop.value_ptr.import_address_table_symbols.addOne(gpa)).* = si;
6347 },
6348 .thunk => {
6349 sym.section_number = Symbol.Index.text.get(coff).section_number;
6350 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
6351 switch (coff.targetLoad(&coff.headerPtr().machine)) {
6352 else => |tag| @panic(@tagName(tag)),
6353 .AMD64 => {
6354 const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };
6355 const target = &comp.root_mod.resolved_target.result;
6356 const ni = try coff.mf.addLastChildNode(gpa, Symbol.Index.text.node(coff), .{
6357 .alignment = switch (comp.root_mod.optimize_mode) {
6358 .Debug,
6359 .ReleaseSafe,
6360 .ReleaseFast,
6361 => target_util.defaultFunctionAlignment(target),
6362 .ReleaseSmall => target_util.minFunctionAlignment(target),
6363 }.toStdMem(),
6364 .size = init.len,
6365 });
6366 @memcpy(ni.slice(&coff.mf)[0..init.len], &init);
6367 sym.ni = ni;
6368 sym.setValue(.{ .size = init.len });
6369 try coff.addReloc(
6370 si,
6371 init.len - 4,
6372 gop.value_ptr.import_address_table_si,
6373 .{ .known = iat_offset },
6374 .{ .AMD64 = .REL32 },
6375 );
6376 },
6377 }
6378 coff.nodes.appendAssumeCapacity(.{ .import_thunk = gmi });
6379 sym.rva = coff.computeNodeRva(sym.ni);
6380 si.applyLocationRelocs(coff);
6381 },
6382 }
6383
63786384 return true;
63796385}
63806386
63816387fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {
63826388 const comp = coff.base.comp;
6389
6390 if (!coff.isImage()) return .none;
63836391 const gpa = comp.gpa;
63846392 const machine = coff.targetLoad(&coff.headerPtr().machine);
6393 const target = &comp.root_mod.resolved_target.result;
63856394
6386 if (!coff.isImage()) return .none;
63876395 return next: switch (pending) {
63886396 .entry => {
63896397 // TODO: Use explicitly specified entry if set, add err if not found
......@@ -6402,7 +6410,7 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {
64026410 .{ "wWinMainCRTStartup", "wWinMainCRTStartup" },
64036411 }
64046412 else
6405 &.{.{ null, "_DllMainCRTStartup" }};
6413 &.{.{ null, if (target.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup" }};
64066414
64076415 const entry_si = for (entries) |entry| {
64086416 if (entry[0]) |required_name|
......@@ -7073,13 +7081,13 @@ fn updateExportsInner(
70737081 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
70747082 ))),
70757083 };
7076 while (try coff.idle(pt.tid)) {}
7084 while (try coff.idle(pt.tid)) {} // TODO: Is this necessary now that we handle exports moving via has_aliases?
70777085
70787086 const machine = coff.targetLoad(&coff.headerPtr().machine);
70797087 const exported_ni = exported_si.node(coff);
70807088 const exported_sym = exported_si.get(coff);
7081 exported_sym.extra = .{ .first_export_si = @enumFromInt(coff.symbols.items.len) };
7082 exported_sym.flags.has_exports = true;
7089 exported_sym.extra = .{ .first_alias_si = @enumFromInt(coff.symbols.items.len) };
7090 exported_sym.flags.has_aliases = true;
70837091
70847092 for (export_indices) |export_index| {
70857093 const @"export" = export_index.ptr(zcu);
......@@ -7256,8 +7264,8 @@ fn printSymbol(
72567264 else
72577265 0,
72587266 switch (sym.flags.value_tag) {
7259 .alias_name => "an",
7260 .alias_si => "as",
7267 .weak_alias_name => "an",
7268 .weak_alias_si => "as",
72617269 .node_offset => "no",
72627270 .size => "sz",
72637271 },