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 {...@@ -912,7 +912,7 @@ pub const Symbol = struct {
912 dll_storage_class: DllStorageClass,912 dll_storage_class: DllStorageClass,
913 // Only defined for .alias_si and .alias_name913 // Only defined for .alias_si and .alias_name
914 weak_external_strat: WeakExternalStrat,914 weak_external_strat: WeakExternalStrat,
915 has_exports: bool,915 has_aliases: bool,
916 _: u7 = 0,916 _: u7 = 0,
917 },917 },
918 /// Relocations contained within this symbol918 /// Relocations contained within this symbol
...@@ -927,9 +927,9 @@ pub const Symbol = struct {...@@ -927,9 +927,9 @@ pub const Symbol = struct {
927 /// Only valid when .ni == .input_section and .value_tag == .node_offset927 /// Only valid when .ni == .input_section and .value_tag == .node_offset
928 /// TODO: This is only used for name lookups, could just be String?928 /// TODO: This is only used for name lookups, could just be String?
929 isli: Node.InputSection.LocalIndex,929 isli: Node.InputSection.LocalIndex,
930 /// Only valid if flags.has_exports is set. The first in a contiguous930 /// Only valid if flags.has_aliases is set. The first in a contiguous
931 /// list of symbols that are exports of this symbol.931 /// list of symbols that are aliases of this symbol.
932 first_export_si: Symbol.Index,932 first_alias_si: Symbol.Index,
933 },933 },
934934
935 pub const DllStorageClass = enum(u2) {935 pub const DllStorageClass = enum(u2) {
...@@ -946,8 +946,8 @@ pub const Symbol = struct {...@@ -946,8 +946,8 @@ pub const Symbol = struct {
946946
947 const ValueTag = enum(u2) {947 const ValueTag = enum(u2) {
948 node_offset,948 node_offset,
949 alias_si,949 weak_alias_si,
950 alias_name,950 weak_alias_name,
951 size,951 size,
952 };952 };
953953
...@@ -957,12 +957,12 @@ pub const Symbol = struct {...@@ -957,12 +957,12 @@ pub const Symbol = struct {
957 node_offset: u32,957 node_offset: u32,
958 /// This is a weak alias that can replace this symbol958 /// This is a weak alias that can replace this symbol
959 /// Globals only.959 /// Globals only.
960 alias_si: Symbol.Index,960 weak_alias_si: Symbol.Index,
961 /// For weak externals that have an alias that is also an undef961 /// For weak externals that have an alias that is also an undef
962 /// external, this is the name of the alias global that should962 /// external, this is the name of the alias global that should
963 /// be generated if this symbol is not resolved.963 /// be generated if this symbol is not resolved.
964 /// Globals only.964 /// Globals only.
965 alias_name: String,965 weak_alias_name: String,
966 /// The symbol size, or 0 if unknown966 /// The symbol size, or 0 if unknown
967 size: u32,967 size: u32,
968 };968 };
...@@ -1069,8 +1069,8 @@ pub const Symbol = struct {...@@ -1069,8 +1069,8 @@ pub const Symbol = struct {
1069 si.applyLocationRelocs(coff);1069 si.applyLocationRelocs(coff);
1070 si.applyTargetRelocs(coff, .none);1070 si.applyTargetRelocs(coff, .none);
10711071
1072 if (sym.flags.has_exports) {1072 if (sym.flags.has_aliases) {
1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_export_si)..]) |*export_sym| {1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_alias_si)..]) |*export_sym| {
1074 if (export_sym.ni != sym.ni) break;1074 if (export_sym.ni != sym.ni) break;
1075 export_sym.rva = sym.rva;1075 export_sym.rva = sym.rva;
1076 const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr);1076 const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr);
...@@ -2203,6 +2203,9 @@ pub fn initBuiltins(coff: *Coff) !void {...@@ -2203,6 +2203,9 @@ pub fn initBuiltins(coff: *Coff) !void {
2203 );2203 );
22042204
2205 const start_sym = start_osmi.symbol(coff).get(coff);2205 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
2206 try start_sym.ni.resize(&coff.mf, gpa, addr_info.size);2209 try start_sym.ni.resize(&coff.mf, gpa, addr_info.size);
2207 const start_slice = start_sym.ni.slice(&coff.mf);2210 const start_slice = start_sym.ni.slice(&coff.mf);
2208 switch (addr_info.magic) {2211 switch (addr_info.magic) {
...@@ -2561,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -2561,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
2561 .type = .unknown,2564 .type = .unknown,
2562 .dll_storage_class = .default,2565 .dll_storage_class = .default,
2563 .weak_external_strat = undefined,2566 .weak_external_strat = undefined,
2564 .has_exports = false,2567 .has_aliases = false,
2565 },2568 },
2566 .loc_relocs = .none,2569 .loc_relocs = .none,
2567 .target_relocs = .none,2570 .target_relocs = .none,
...@@ -4443,10 +4446,10 @@ fn loadObject(...@@ -4443,10 +4446,10 @@ fn loadObject(
4443 .external => {4446 .external => {
4444 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {4447 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
4445 // If the alias itself is an undef external, we need to wait until flushing the weak4448 // 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 input4449 // external global before creating a global for the alias, as another input could
4447 // could still provide the weak external.4450 // still provide the weak external.
4448 const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);4451 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 });
4450 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;4453 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
4451 }4454 }
44524455
...@@ -4476,9 +4479,9 @@ fn loadObject(...@@ -4476,9 +4479,9 @@ fn loadObject(
4476 alias.weak_external_psi = .wrap(@intCast(i));4479 alias.weak_external_psi = .wrap(@intCast(i));
4477 } else {4480 } else {
4478 sym.setValue(if (alias.si.unwrap()) |alias_si| .{4481 sym.setValue(if (alias.si.unwrap()) |alias_si| .{
4479 .alias_si = alias_si,4482 .weak_alias_si = alias_si,
4480 } else .{4483 } else .{
4481 .alias_name = alias.name,4484 .weak_alias_name = alias.name,
4482 });4485 });
4483 sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux;4486 sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux;
4484 }4487 }
...@@ -4521,7 +4524,7 @@ fn loadObject(...@@ -4521,7 +4524,7 @@ fn loadObject(
4521 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {4524 if (symbol.weak_external_psi.unwrap()) |weak_external_i| {
4522 assert(symbol.si != .null);4525 assert(symbol.si != .null);
4523 const weak_sym = pending_symbols.values()[weak_external_i].si.get(coff);4526 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 });
4525 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;4528 weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux;
4526 }4529 }
45274530
...@@ -5985,17 +5988,16 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -5985,17 +5988,16 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
5985 const gpa = comp.gpa;5988 const gpa = comp.gpa;
5986 const gn = gmi.globalName(coff);5989 const gn = gmi.globalName(coff);
5987 const si = gmi.symbol(coff);5990 const si = gmi.symbol(coff);
5988 const sym = si.get(coff);
5989 const is_late = gmi.unwrap().? < coff.global_pending_index;5991 const is_late = gmi.unwrap().? < coff.global_pending_index;
59905992
5991 log.debug(5993 log.debug(
5992 "flushGlobal({s}, {?s}, {}) = n{d} {d}@{d}",5994 "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 },
5994 );5996 );
59955997
5996 if (!coff.isImage()) {5998 if (!coff.isImage()) {
5997 try coff.pendingSymbolTableEntry(si);5999 try coff.pendingSymbolTableEntry(si);
5998 if (coff.isArchive() and sym.ni != .none)6000 if (coff.isArchive() and si.get(coff).ni != .none)
5999 try coff.ensureMemberSymbol(6001 try coff.ensureMemberSymbol(
6000 coff.getNode(Node.known.zcu_member).archive_member,6002 coff.getNode(Node.known.zcu_member).archive_member,
6001 gn.name,6003 gn.name,
...@@ -6004,6 +6006,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6004,6 +6006,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6004 return true;6006 return true;
6005 }6007 }
60066008
6009 if (si.get(coff).ni != .none)
6010 return true;
6011
6007 const Import = struct {6012 const Import = struct {
6008 lib_name: String,6013 lib_name: String,
6009 name: String.Optional,6014 name: String.Optional,
...@@ -6014,7 +6019,8 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6014,7 +6019,8 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6014 },6019 },
6015 };6020 };
60166021
6017 const opt_import: ?Import = if (sym.ni == .none) import: {6022 const import: Import = import: {
6023 const sym = si.get(coff);
6018 const global_name = gn.name.toSlice(coff);6024 const global_name = gn.name.toSlice(coff);
6019 const imp_match = std.mem.startsWith(u8, global_name, imp_prefix);6025 const imp_match = std.mem.startsWith(u8, global_name, imp_prefix);
60206026
...@@ -6030,7 +6036,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6030,7 +6036,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
60306036
6031 const opt_alt_search_name = coff.alternate_names.get(search_name);6037 const opt_alt_search_name = coff.alternate_names.get(search_name);
6032 const search_libs = if (is_late) switch (sym.flags.value_tag) {6038 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) {
6034 .no_library => false,6040 .no_library => false,
6035 .library,6041 .library,
6036 .alias,6042 .alias,
...@@ -6044,7 +6050,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6044,7 +6050,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6044 else => true,6050 else => true,
6045 } else search_libs: {6051 } else search_libs: {
6046 if (switch (sym.flags.value_tag) {6052 if (switch (sym.flags.value_tag) {
6047 .alias_si, .alias_name => true,6053 .weak_alias_si, .weak_alias_name => true,
6048 else => opt_alt_search_name != null,6054 else => opt_alt_search_name != null,
6049 }) {6055 }) {
6050 // We need to wait until all exports are known before resolving these6056 // We need to wait until all exports are known before resolving these
...@@ -6137,16 +6143,18 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6137,16 +6143,18 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6137 }6143 }
61386144
6139 switch (sym.flags.value_tag) {6145 switch (sym.flags.value_tag) {
6140 .alias_si => {6146 .weak_alias_si => {
6141 assert(is_late);6147 assert(is_late);
6142 try coff.aliasGlobal(gmi, sym.value.alias_si);6148 try coff.aliasGlobal(gmi, sym.value.weak_alias_si);
6143 return true;6149 return true;
6144 },6150 },
6145 .alias_name => {6151 .weak_alias_name => {
6146 assert(is_late);6152 assert(is_late);
6147 // Convert an unresolved weak external that itself refers to an undef external6153 // Convert an unresolved weak external that itself refers to an undef external
6148 // into a (possibly new) global, so it can be resolved separately.6154 // 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 });
6150 try coff.aliasGlobal(gmi, alias_gop.value_ptr.*);6158 try coff.aliasGlobal(gmi, alias_gop.value_ptr.*);
6151 return true;6159 return true;
6152 },6160 },
...@@ -6174,216 +6182,216 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6174,216 +6182,216 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6174 };6182 };
6175 }6183 }
61766184
6177 break :import null;6185 return true;
6178 } else null;6186 };
61796187
6180 if (opt_import) |import| {6188 const lib_name = import.lib_name.toSlice(coff);
6181 assert(sym.ni == .none);
6182 const lib_name = import.lib_name.toSlice(coff);
61836189
6184 try coff.nodes.ensureUnusedCapacity(gpa, 4);6190 try coff.nodes.ensureUnusedCapacity(gpa, 4);
6185 try coff.symbols.ensureUnusedCapacity(gpa, 1);6191 try coff.symbols.ensureUnusedCapacity(gpa, 1);
61866192
6187 const target_endian = coff.targetEndian();6193 const sym = si.get(coff);
6188 const addr_info = coff.targetAddrInfo();6194 const target_endian = coff.targetEndian();
6189 const gop = try coff.import_table.entries.getOrPutAdapted(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,
6190 gpa,6206 gpa,
6191 lib_name,6207 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
6192 ImportTable.Adapter{ .coff = coff },
6193 );6208 );
6194 const import_hint_name_align: std.mem.Alignment = .@"2";6209 const import_hint_name_table_len =
6195 if (!gop.found_existing) {6210 import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
6196 errdefer _ = coff.import_table.entries.pop();6211 const idata_section_ni = coff.import_table.ni.parent(&coff.mf);
6197 try coff.import_table.ni.resize(6212 const import_lookup_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6198 &coff.mf,6213 .size = addr_info.size * 2,
6199 gpa,6214 .alignment = addr_info.alignment,
6200 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),6215 .moved = true,
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,
6272 });6216 });
6273 if (!iat_symbol_gop.found_existing) {6217 const import_address_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6274 const import_symbol_index = gop.value_ptr.len;6218 .size = addr_info.size * 2,
6275 iat_symbol_gop.value_ptr.* = import_symbol_index;6219 .alignment = addr_info.alignment,
62766220 .moved = true,
6277 gop.value_ptr.len = import_symbol_index + 1;6221 });
6278 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);6222 const import_address_table_si = coff.addSymbolAssumeCapacity();
62796223 {
6280 try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);6224 const import_address_table_sym = import_address_table_si.get(coff);
6281 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);6225 import_address_table_sym.ni = import_address_table_ni;
6282 try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);6226 assert(import_address_table_sym.loc_relocs == .none);
62836227 import_address_table_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
6284 const opt_name = import.name.toSlice(coff);6228 import_address_table_sym.section_number =
6285 const opt_import_hint_name_index = if (opt_name) |name| blk: {6229 coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
6286 const import_hint_name_index = gop.value_ptr.hint_name_len;6230 }
6287 gop.value_ptr.hint_name_len = @intCast(6231 const import_hint_name_table_ni = try coff.mf.addLastChildNode(gpa, idata_section_ni, .{
6288 import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1),6232 .size = import_hint_name_table_len,
6289 );6233 .alignment = import_hint_name_align,
6290 try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);6234 .moved = true,
6291 break :blk import_hint_name_index;6235 });
6292 } else null;6236 gop.value_ptr.* = .{
62936237 .import_lookup_table_ni = import_lookup_table_ni,
6294 const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: {6238 .import_address_table_si = import_address_table_si,
6295 const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);6239 .import_hint_name_table_ni = import_hint_name_table_ni,
6296 const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2]));6240 .import_address_table_symbols = .empty,
6297 ordinal_hint.* = std.mem.nativeTo(u16, import.ordinal_hint, target_endian);6241 .len = 0,
6298 @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..opt_name.?.len], opt_name.?);6242 .hint_name_len = @intCast(import_hint_name_table_len),
6299 @memset(import_hint_name_slice[import_hint_name_index + 2 + opt_name.?.len ..], 0);6243 };
6300 break :blk coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;6244 const import_hint_name_slice = import_hint_name_table_ni.slice(&coff.mf);
6301 } else 0;6245 @memcpy(import_hint_name_slice[0..lib_name.len], lib_name);
63026246 @memcpy(import_hint_name_slice[lib_name.len..][0..".dll".len], ".dll");
6303 const import_lookup_slice = gop.value_ptr.import_lookup_table_ni.slice(&coff.mf);6247 @memset(import_hint_name_slice[lib_name.len + ".dll".len ..], 0);
6304 const import_address_slice = import_address_table_ni.slice(&coff.mf);6248 coff.nodes.appendAssumeCapacity(.{ .import_lookup_table = @enumFromInt(gop.index) });
6305 switch (addr_info.magic) {6249 coff.nodes.appendAssumeCapacity(.{ .import_address_table = @enumFromInt(gop.index) });
6306 _ => unreachable,6250 coff.nodes.appendAssumeCapacity(.{ .import_hint_name_table = @enumFromInt(gop.index) });
6307 inline .PE32, .@"PE32+" => |ct_magic| {6251
6308 const Entry = ImportTable.TableEntry(ct_magic);6252 const import_directory_entries = coff.importDirectoryTableSlice()[gop.index..][0..2];
6309 const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice));6253 import_directory_entries.* = .{ .{
6310 const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice));6254 .import_lookup_table_rva = coff.computeNodeRva(import_lookup_table_ni),
6311 const import_hint_name_rvas: [2]Entry = .{6255 .time_date_stamp = 0,
6312 .{6256 .forwarder_chain = 0,
6313 .payload = if (import.name == .none)6257 .name_rva = coff.computeNodeRva(import_hint_name_table_ni),
6314 .{ .ordinal = .{ .ordinal = import.ordinal_hint } }6258 .import_address_table_rva = coff.computeNodeRva(import_address_table_ni),
6315 else6259 }, .{
6316 .{ .hint_name_rva = @intCast(import_hint_name_rva) },6260 .import_lookup_table_rva = 0,
6317 .is_ordinal = import.name == .none,6261 .time_date_stamp = 0,
6318 },6262 .forwarder_chain = 0,
6319 @bitCast(@as(@typeInfo(Entry).@"struct".backing_integer.?, 0)),6263 .name_rva = 0,
6320 };6264 .import_address_table_rva = 0,
6321 if (native_endian != target_endian)6265 } };
6322 for (import_hint_name_rvas) |*v| std.mem.byteSwapAllFields(Entry, v);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;6270 log.debug(
6325 import_address_table[import_symbol_index..][0..2].* = import_hint_name_rvas;6271 "flushGlobalImport({s}, {?s}, {d}, {s})",
6326 },6272 .{ gn.name.toSlice(coff), import.name.toSlice(coff), import.ordinal_hint, lib_name },
6327 }6273 );
6328 }
63296274
6330 assert(sym.loc_relocs == .none);6275 const iat_symbol_gop = try coff.import_table.iat_symbol_indices.getOrPut(gpa, .{
6331 const iat_offset: u32 = @intCast(addr_info.size * iat_symbol_gop.value_ptr.*);6276 .iti = @enumFromInt(gop.index),
6332 switch (import.kind) {6277 .name = import.name,
6333 .iat_ptr => {6278 .ordinal_hint = import.ordinal_hint,
6334 const iat_sym = gop.value_ptr.import_address_table_si.get(coff);6279 });
6335 sym.section_number = iat_sym.section_number;6280 if (!iat_symbol_gop.found_existing) {
6336 sym.ni = iat_sym.ni;6281 const import_symbol_index = gop.value_ptr.len;
6337 sym.setValue(.{ .node_offset = iat_offset });6282 iat_symbol_gop.value_ptr.* = import_symbol_index;
6338 si.flushMoved(coff);6283
6339 (try gop.value_ptr.import_address_table_symbols.addOne(gpa)).* = si;6284 gop.value_ptr.len = import_symbol_index + 1;
6340 },6285 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);
6341 .thunk => {6286
6342 sym.section_number = Symbol.Index.text.get(coff).section_number;6287 try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6343 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);6288 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);
6344 switch (coff.targetLoad(&coff.headerPtr().machine)) {6289 try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size);
6345 else => |tag| @panic(@tagName(tag)),6290
6346 .AMD64 => {6291 const opt_name = import.name.toSlice(coff);
6347 const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };6292 const opt_import_hint_name_index = if (opt_name) |name| blk: {
6348 const target = &comp.root_mod.resolved_target.result;6293 const import_hint_name_index = gop.value_ptr.hint_name_len;
6349 const ni = try coff.mf.addLastChildNode(gpa, Symbol.Index.text.node(coff), .{6294 gop.value_ptr.hint_name_len = @intCast(
6350 .alignment = switch (comp.root_mod.optimize_mode) {6295 import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1),
6351 .Debug,6296 );
6352 .ReleaseSafe,6297 try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len);
6353 .ReleaseFast,6298 break :blk import_hint_name_index;
6354 => target_util.defaultFunctionAlignment(target),6299 } else null;
6355 .ReleaseSmall => target_util.minFunctionAlignment(target),6300
6356 }.toStdMem(),6301 const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: {
6357 .size = init.len,6302 const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf);
6358 });6303 const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2]));
6359 @memcpy(ni.slice(&coff.mf)[0..init.len], &init);6304 ordinal_hint.* = std.mem.nativeTo(u16, import.ordinal_hint, target_endian);
6360 sym.ni = ni;6305 @memcpy(import_hint_name_slice[import_hint_name_index + 2 ..][0..opt_name.?.len], opt_name.?);
6361 sym.setValue(.{ .size = init.len });6306 @memset(import_hint_name_slice[import_hint_name_index + 2 + opt_name.?.len ..], 0);
6362 try coff.addReloc(6307 break :blk coff.computeNodeRva(gop.value_ptr.import_hint_name_table_ni) + import_hint_name_index;
6363 si,6308 } else 0;
6364 init.len - 4,6309
6365 gop.value_ptr.import_address_table_si,6310 const import_lookup_slice = gop.value_ptr.import_lookup_table_ni.slice(&coff.mf);
6366 .{ .known = iat_offset },6311 const import_address_slice = import_address_table_ni.slice(&coff.mf);
6367 .{ .AMD64 = .REL32 },6312 switch (addr_info.magic) {
6368 );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,
6369 },6325 },
6370 }6326 @bitCast(@as(@typeInfo(Entry).@"struct".backing_integer.?, 0)),
6371 coff.nodes.appendAssumeCapacity(.{ .import_thunk = gmi });6327 };
6372 sym.rva = coff.computeNodeRva(sym.ni);6328 if (native_endian != target_endian)
6373 si.applyLocationRelocs(coff);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;
6374 },6333 },
6375 }6334 }
6376 }6335 }
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
6378 return true;6384 return true;
6379}6385}
63806386
6381fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {6387fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {
6382 const comp = coff.base.comp;6388 const comp = coff.base.comp;
6389
6390 if (!coff.isImage()) return .none;
6383 const gpa = comp.gpa;6391 const gpa = comp.gpa;
6384 const machine = coff.targetLoad(&coff.headerPtr().machine);6392 const machine = coff.targetLoad(&coff.headerPtr().machine);
6393 const target = &comp.root_mod.resolved_target.result;
63856394
6386 if (!coff.isImage()) return .none;
6387 return next: switch (pending) {6395 return next: switch (pending) {
6388 .entry => {6396 .entry => {
6389 // TODO: Use explicitly specified entry if set, add err if not found6397 // TODO: Use explicitly specified entry if set, add err if not found
...@@ -6402,7 +6410,7 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {...@@ -6402,7 +6410,7 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol {
6402 .{ "wWinMainCRTStartup", "wWinMainCRTStartup" },6410 .{ "wWinMainCRTStartup", "wWinMainCRTStartup" },
6403 }6411 }
6404 else6412 else
6405 &.{.{ null, "_DllMainCRTStartup" }};6413 &.{.{ null, if (target.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup" }};
64066414
6407 const entry_si = for (entries) |entry| {6415 const entry_si = for (entries) |entry| {
6408 if (entry[0]) |required_name|6416 if (entry[0]) |required_name|
...@@ -7073,13 +7081,13 @@ fn updateExportsInner(...@@ -7073,13 +7081,13 @@ fn updateExportsInner(
7073 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),7081 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
7074 ))),7082 ))),
7075 };7083 };
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
7078 const machine = coff.targetLoad(&coff.headerPtr().machine);7086 const machine = coff.targetLoad(&coff.headerPtr().machine);
7079 const exported_ni = exported_si.node(coff);7087 const exported_ni = exported_si.node(coff);
7080 const exported_sym = exported_si.get(coff);7088 const exported_sym = exported_si.get(coff);
7081 exported_sym.extra = .{ .first_export_si = @enumFromInt(coff.symbols.items.len) };7089 exported_sym.extra = .{ .first_alias_si = @enumFromInt(coff.symbols.items.len) };
7082 exported_sym.flags.has_exports = true;7090 exported_sym.flags.has_aliases = true;
70837091
7084 for (export_indices) |export_index| {7092 for (export_indices) |export_index| {
7085 const @"export" = export_index.ptr(zcu);7093 const @"export" = export_index.ptr(zcu);
...@@ -7256,8 +7264,8 @@ fn printSymbol(...@@ -7256,8 +7264,8 @@ fn printSymbol(
7256 else7264 else
7257 0,7265 0,
7258 switch (sym.flags.value_tag) {7266 switch (sym.flags.value_tag) {
7259 .alias_name => "an",7267 .weak_alias_name => "an",
7260 .alias_si => "as",7268 .weak_alias_si => "as",
7261 .node_offset => "no",7269 .node_offset => "no",
7262 .size => "sz",7270 .size => "sz",
7263 },7271 },