| ... | ... | @@ -912,7 +912,7 @@ pub const Symbol = struct { |
| 912 | 912 | dll_storage_class: DllStorageClass, |
| 913 | 913 | // Only defined for .alias_si and .alias_name |
| 914 | 914 | weak_external_strat: WeakExternalStrat, |
| 915 | | has_exports: bool, |
| 915 | has_aliases: bool, |
| 916 | 916 | _: u7 = 0, |
| 917 | 917 | }, |
| 918 | 918 | /// Relocations contained within this symbol |
| ... | ... | @@ -927,9 +927,9 @@ pub const Symbol = struct { |
| 927 | 927 | /// Only valid when .ni == .input_section and .value_tag == .node_offset |
| 928 | 928 | /// TODO: This is only used for name lookups, could just be String? |
| 929 | 929 | 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, |
| 933 | 933 | }, |
| 934 | 934 | |
| 935 | 935 | pub const DllStorageClass = enum(u2) { |
| ... | ... | @@ -946,8 +946,8 @@ pub const Symbol = struct { |
| 946 | 946 | |
| 947 | 947 | const ValueTag = enum(u2) { |
| 948 | 948 | node_offset, |
| 949 | | alias_si, |
| 950 | | alias_name, |
| 949 | weak_alias_si, |
| 950 | weak_alias_name, |
| 951 | 951 | size, |
| 952 | 952 | }; |
| 953 | 953 | |
| ... | ... | @@ -957,12 +957,12 @@ pub const Symbol = struct { |
| 957 | 957 | node_offset: u32, |
| 958 | 958 | /// This is a weak alias that can replace this symbol |
| 959 | 959 | /// Globals only. |
| 960 | | alias_si: Symbol.Index, |
| 960 | weak_alias_si: Symbol.Index, |
| 961 | 961 | /// For weak externals that have an alias that is also an undef |
| 962 | 962 | /// external, this is the name of the alias global that should |
| 963 | 963 | /// be generated if this symbol is not resolved. |
| 964 | 964 | /// Globals only. |
| 965 | | alias_name: String, |
| 965 | weak_alias_name: String, |
| 966 | 966 | /// The symbol size, or 0 if unknown |
| 967 | 967 | size: u32, |
| 968 | 968 | }; |
| ... | ... | @@ -1069,8 +1069,8 @@ pub const Symbol = struct { |
| 1069 | 1069 | si.applyLocationRelocs(coff); |
| 1070 | 1070 | si.applyTargetRelocs(coff, .none); |
| 1071 | 1071 | |
| 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| { |
| 1074 | 1074 | if (export_sym.ni != sym.ni) break; |
| 1075 | 1075 | export_sym.rva = sym.rva; |
| 1076 | 1076 | const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr); |
| ... | ... | @@ -2203,6 +2203,9 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2203 | 2203 | ); |
| 2204 | 2204 | |
| 2205 | 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 | 2209 | try start_sym.ni.resize(&coff.mf, gpa, addr_info.size); |
| 2207 | 2210 | const start_slice = start_sym.ni.slice(&coff.mf); |
| 2208 | 2211 | switch (addr_info.magic) { |
| ... | ... | @@ -2561,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 2561 | 2564 | .type = .unknown, |
| 2562 | 2565 | .dll_storage_class = .default, |
| 2563 | 2566 | .weak_external_strat = undefined, |
| 2564 | | .has_exports = false, |
| 2567 | .has_aliases = false, |
| 2565 | 2568 | }, |
| 2566 | 2569 | .loc_relocs = .none, |
| 2567 | 2570 | .target_relocs = .none, |
| ... | ... | @@ -4443,10 +4446,10 @@ fn loadObject( |
| 4443 | 4446 | .external => { |
| 4444 | 4447 | if (symbol.weak_external_psi.unwrap()) |weak_external_i| { |
| 4445 | 4448 | // 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. |
| 4448 | 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 | 4453 | weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux; |
| 4451 | 4454 | } |
| 4452 | 4455 | |
| ... | ... | @@ -4476,9 +4479,9 @@ fn loadObject( |
| 4476 | 4479 | alias.weak_external_psi = .wrap(@intCast(i)); |
| 4477 | 4480 | } else { |
| 4478 | 4481 | sym.setValue(if (alias.si.unwrap()) |alias_si| .{ |
| 4479 | | .alias_si = alias_si, |
| 4482 | .weak_alias_si = alias_si, |
| 4480 | 4483 | } else .{ |
| 4481 | | .alias_name = alias.name, |
| 4484 | .weak_alias_name = alias.name, |
| 4482 | 4485 | }); |
| 4483 | 4486 | sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux; |
| 4484 | 4487 | } |
| ... | ... | @@ -4521,7 +4524,7 @@ fn loadObject( |
| 4521 | 4524 | if (symbol.weak_external_psi.unwrap()) |weak_external_i| { |
| 4522 | 4525 | assert(symbol.si != .null); |
| 4523 | 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 | 4528 | weak_sym.flags.weak_external_strat = pending_symbols.values()[weak_external_i + 1].value.weak_external_aux; |
| 4526 | 4529 | } |
| 4527 | 4530 | |
| ... | ... | @@ -5985,17 +5988,16 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 5985 | 5988 | const gpa = comp.gpa; |
| 5986 | 5989 | const gn = gmi.globalName(coff); |
| 5987 | 5990 | const si = gmi.symbol(coff); |
| 5988 | | const sym = si.get(coff); |
| 5989 | 5991 | const is_late = gmi.unwrap().? < coff.global_pending_index; |
| 5990 | 5992 | |
| 5991 | 5993 | log.debug( |
| 5992 | 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 | ); |
| 5995 | 5997 | |
| 5996 | 5998 | if (!coff.isImage()) { |
| 5997 | 5999 | try coff.pendingSymbolTableEntry(si); |
| 5998 | | if (coff.isArchive() and sym.ni != .none) |
| 6000 | if (coff.isArchive() and si.get(coff).ni != .none) |
| 5999 | 6001 | try coff.ensureMemberSymbol( |
| 6000 | 6002 | coff.getNode(Node.known.zcu_member).archive_member, |
| 6001 | 6003 | gn.name, |
| ... | ... | @@ -6004,6 +6006,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6004 | 6006 | return true; |
| 6005 | 6007 | } |
| 6006 | 6008 | |
| 6009 | if (si.get(coff).ni != .none) |
| 6010 | return true; |
| 6011 | |
| 6007 | 6012 | const Import = struct { |
| 6008 | 6013 | lib_name: String, |
| 6009 | 6014 | name: String.Optional, |
| ... | ... | @@ -6014,7 +6019,8 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6014 | 6019 | }, |
| 6015 | 6020 | }; |
| 6016 | 6021 | |
| 6017 | | const opt_import: ?Import = if (sym.ni == .none) import: { |
| 6022 | const import: Import = import: { |
| 6023 | const sym = si.get(coff); |
| 6018 | 6024 | const global_name = gn.name.toSlice(coff); |
| 6019 | 6025 | const imp_match = std.mem.startsWith(u8, global_name, imp_prefix); |
| 6020 | 6026 | |
| ... | ... | @@ -6030,7 +6036,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6030 | 6036 | |
| 6031 | 6037 | const opt_alt_search_name = coff.alternate_names.get(search_name); |
| 6032 | 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 | 6040 | .no_library => false, |
| 6035 | 6041 | .library, |
| 6036 | 6042 | .alias, |
| ... | ... | @@ -6044,7 +6050,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6044 | 6050 | else => true, |
| 6045 | 6051 | } else search_libs: { |
| 6046 | 6052 | if (switch (sym.flags.value_tag) { |
| 6047 | | .alias_si, .alias_name => true, |
| 6053 | .weak_alias_si, .weak_alias_name => true, |
| 6048 | 6054 | else => opt_alt_search_name != null, |
| 6049 | 6055 | }) { |
| 6050 | 6056 | // 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 | 6143 | } |
| 6138 | 6144 | |
| 6139 | 6145 | switch (sym.flags.value_tag) { |
| 6140 | | .alias_si => { |
| 6146 | .weak_alias_si => { |
| 6141 | 6147 | assert(is_late); |
| 6142 | | try coff.aliasGlobal(gmi, sym.value.alias_si); |
| 6148 | try coff.aliasGlobal(gmi, sym.value.weak_alias_si); |
| 6143 | 6149 | return true; |
| 6144 | 6150 | }, |
| 6145 | | .alias_name => { |
| 6151 | .weak_alias_name => { |
| 6146 | 6152 | assert(is_late); |
| 6147 | 6153 | // Convert an unresolved weak external that itself refers to an undef external |
| 6148 | 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 | 6158 | try coff.aliasGlobal(gmi, alias_gop.value_ptr.*); |
| 6151 | 6159 | return true; |
| 6152 | 6160 | }, |
| ... | ... | @@ -6174,216 +6182,216 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6174 | 6182 | }; |
| 6175 | 6183 | } |
| 6176 | 6184 | |
| 6177 | | break :import null; |
| 6178 | | } else null; |
| 6185 | return true; |
| 6186 | }; |
| 6179 | 6187 | |
| 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); |
| 6183 | 6189 | |
| 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); |
| 6186 | 6192 | |
| 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, |
| 6190 | 6206 | gpa, |
| 6191 | | lib_name, |
| 6192 | | ImportTable.Adapter{ .coff = coff }, |
| 6207 | @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2), |
| 6193 | 6208 | ); |
| 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, |
| 6272 | 6216 | }); |
| 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 | } |
| 6323 | 6269 | |
| 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 | ); |
| 6329 | 6274 | |
| 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, |
| 6369 | 6325 | }, |
| 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; |
| 6374 | 6333 | }, |
| 6375 | 6334 | } |
| 6376 | 6335 | } |
| 6377 | 6336 | |
| 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 | 6384 | return true; |
| 6379 | 6385 | } |
| 6380 | 6386 | |
| 6381 | 6387 | fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol { |
| 6382 | 6388 | const comp = coff.base.comp; |
| 6389 | |
| 6390 | if (!coff.isImage()) return .none; |
| 6383 | 6391 | const gpa = comp.gpa; |
| 6384 | 6392 | const machine = coff.targetLoad(&coff.headerPtr().machine); |
| 6393 | const target = &comp.root_mod.resolved_target.result; |
| 6385 | 6394 | |
| 6386 | | if (!coff.isImage()) return .none; |
| 6387 | 6395 | return next: switch (pending) { |
| 6388 | 6396 | .entry => { |
| 6389 | 6397 | // TODO: Use explicitly specified entry if set, add err if not found |
| ... | ... | @@ -6402,7 +6410,7 @@ fn flushSpecialSymbol(coff: *Coff, pending: SpecialSymbol) !SpecialSymbol { |
| 6402 | 6410 | .{ "wWinMainCRTStartup", "wWinMainCRTStartup" }, |
| 6403 | 6411 | } |
| 6404 | 6412 | else |
| 6405 | | &.{.{ null, "_DllMainCRTStartup" }}; |
| 6413 | &.{.{ null, if (target.abi.isGnu()) "DllMainCRTStartup" else "_DllMainCRTStartup" }}; |
| 6406 | 6414 | |
| 6407 | 6415 | const entry_si = for (entries) |entry| { |
| 6408 | 6416 | if (entry[0]) |required_name| |
| ... | ... | @@ -7073,13 +7081,13 @@ fn updateExportsInner( |
| 7073 | 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? |
| 7077 | 7085 | |
| 7078 | 7086 | const machine = coff.targetLoad(&coff.headerPtr().machine); |
| 7079 | 7087 | const exported_ni = exported_si.node(coff); |
| 7080 | 7088 | 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; |
| 7083 | 7091 | |
| 7084 | 7092 | for (export_indices) |export_index| { |
| 7085 | 7093 | const @"export" = export_index.ptr(zcu); |
| ... | ... | @@ -7256,8 +7264,8 @@ fn printSymbol( |
| 7256 | 7264 | else |
| 7257 | 7265 | 0, |
| 7258 | 7266 | switch (sym.flags.value_tag) { |
| 7259 | | .alias_name => "an", |
| 7260 | | .alias_si => "as", |
| 7267 | .weak_alias_name => "an", |
| 7268 | .weak_alias_si => "as", |
| 7261 | 7269 | .node_offset => "no", |
| 7262 | 7270 | .size => "sz", |
| 7263 | 7271 | }, |