| ... | @@ -49,6 +49,7 @@ input_sections: std.ArrayList(Node.InputSection), | ... | @@ -49,6 +49,7 @@ input_sections: std.ArrayList(Node.InputSection), |
| 49 | input_section_pending_index: u32, | 49 | input_section_pending_index: u32, |
| 50 | inputs_complete: bool, | 50 | inputs_complete: bool, |
| 51 | exports_complete: bool, | 51 | exports_complete: bool, |
| | 52 | special_symbols_complete: bool, |
| 52 | strings: std.HashMapUnmanaged( | 53 | strings: std.HashMapUnmanaged( |
| 53 | u32, | 54 | u32, |
| 54 | void, | 55 | void, |
| ... | @@ -74,7 +75,6 @@ pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct { | ... | @@ -74,7 +75,6 @@ pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct { |
| 74 | alignment: InternPool.Alignment, | 75 | alignment: InternPool.Alignment, |
| 75 | }), | 76 | }), |
| 76 | relocs: std.ArrayList(Reloc), | 77 | relocs: std.ArrayList(Reloc), |
| 77 | entry: Node.GlobalMapIndex, | | |
| 78 | const_prog_node: std.Progress.Node, | 78 | const_prog_node: std.Progress.Node, |
| 79 | synth_prog_node: std.Progress.Node, | 79 | synth_prog_node: std.Progress.Node, |
| 80 | symbol_prog_node: std.Progress.Node, | 80 | symbol_prog_node: std.Progress.Node, |
| ... | @@ -896,8 +896,7 @@ pub const Symbol = struct { | ... | @@ -896,8 +896,7 @@ pub const Symbol = struct { |
| 896 | dll_storage_class: DllStorageClass, | 896 | dll_storage_class: DllStorageClass, |
| 897 | // Only defined for .alias_si and .alias_name | 897 | // Only defined for .alias_si and .alias_name |
| 898 | weak_external_strat: WeakExternalStrat, | 898 | weak_external_strat: WeakExternalStrat, |
| 899 | is_entry: bool, | 899 | _: u8 = 0, |
| 900 | _: u7 = 0, | | |
| 901 | }, | 900 | }, |
| 902 | /// Relocations contained within this symbol | 901 | /// Relocations contained within this symbol |
| 903 | loc_relocs: Reloc.Index, | 902 | loc_relocs: Reloc.Index, |
| ... | @@ -1017,6 +1016,11 @@ pub const Symbol = struct { | ... | @@ -1017,6 +1016,11 @@ pub const Symbol = struct { |
| 1017 | return &coff.symbols.items[@intFromEnum(si)]; | 1016 | return &coff.symbols.items[@intFromEnum(si)]; |
| 1018 | } | 1017 | } |
| 1019 | | 1018 | |
| | 1019 | pub fn unwrap(si: Symbol.Index) ?Symbol.Index { |
| | 1020 | if (si == .null) return null; |
| | 1021 | return si; |
| | 1022 | } |
| | 1023 | |
| 1020 | pub fn node(si: Symbol.Index, coff: *Coff) MappedFile.Node.Index { | 1024 | pub fn node(si: Symbol.Index, coff: *Coff) MappedFile.Node.Index { |
| 1021 | const ni = si.get(coff).ni; | 1025 | const ni = si.get(coff).ni; |
| 1022 | assert(ni != .none); | 1026 | assert(ni != .none); |
| ... | @@ -1074,12 +1078,6 @@ pub const Symbol = struct { | ... | @@ -1074,12 +1078,6 @@ pub const Symbol = struct { |
| 1074 | pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff, end: Reloc.Index) void { | 1078 | pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff, end: Reloc.Index) void { |
| 1075 | const sym = si.get(coff); | 1079 | const sym = si.get(coff); |
| 1076 | | 1080 | |
| 1077 | // TODO: Would this be better modeled using an actual reloc? Would need a si for the header | | |
| 1078 | if (sym.flags.is_entry) { | | |
| 1079 | log.debug("updateEntryRVA({d}, 0x{x})", .{ si, sym.rva }); | | |
| 1080 | coff.optionalHeaderStandardPtr().address_of_entry_point = sym.rva; | | |
| 1081 | } | | |
| 1082 | | | |
| 1083 | var ri = sym.target_relocs; | 1081 | var ri = sym.target_relocs; |
| 1084 | while (ri != end) { | 1082 | while (ri != end) { |
| 1085 | const reloc = ri.get(coff); | 1083 | const reloc = ri.get(coff); |
| ... | @@ -1549,6 +1547,7 @@ fn create( | ... | @@ -1549,6 +1547,7 @@ fn create( |
| 1549 | .input_section_pending_index = 0, | 1547 | .input_section_pending_index = 0, |
| 1550 | .inputs_complete = false, | 1548 | .inputs_complete = false, |
| 1551 | .exports_complete = false, | 1549 | .exports_complete = false, |
| | 1550 | .special_symbols_complete = false, |
| 1552 | .strings = .empty, | 1551 | .strings = .empty, |
| 1553 | .string_bytes = .empty, | 1552 | .string_bytes = .empty, |
| 1554 | .section_table = .empty, | 1553 | .section_table = .empty, |
| ... | @@ -1567,7 +1566,6 @@ fn create( | ... | @@ -1567,7 +1566,6 @@ fn create( |
| 1567 | }), | 1566 | }), |
| 1568 | .pending_uavs = .empty, | 1567 | .pending_uavs = .empty, |
| 1569 | .relocs = .empty, | 1568 | .relocs = .empty, |
| 1570 | .entry = .none, | | |
| 1571 | .const_prog_node = .none, | 1569 | .const_prog_node = .none, |
| 1572 | .synth_prog_node = .none, | 1570 | .synth_prog_node = .none, |
| 1573 | .symbol_prog_node = .none, | 1571 | .symbol_prog_node = .none, |
| ... | @@ -2525,7 +2523,6 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { | ... | @@ -2525,7 +2523,6 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 2525 | .type = .unknown, | 2523 | .type = .unknown, |
| 2526 | .dll_storage_class = .default, | 2524 | .dll_storage_class = .default, |
| 2527 | .weak_external_strat = undefined, | 2525 | .weak_external_strat = undefined, |
| 2528 | .is_entry = false, | | |
| 2529 | }, | 2526 | }, |
| 2530 | .loc_relocs = .none, | 2527 | .loc_relocs = .none, |
| 2531 | .target_relocs = .none, | 2528 | .target_relocs = .none, |
| ... | @@ -2642,6 +2639,14 @@ fn getOrPutGlobalSymbol( | ... | @@ -2642,6 +2639,14 @@ fn getOrPutGlobalSymbol( |
| 2642 | return sym_gop; | 2639 | return sym_gop; |
| 2643 | } | 2640 | } |
| 2644 | | 2641 | |
| | 2642 | fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index { |
| | 2643 | if (coff.globals.get(.{ |
| | 2644 | .name = coff.getString(name).unwrap() orelse return .null, |
| | 2645 | .lib_name = .none, |
| | 2646 | })) |si| if (si.get(coff).ni != .none) return si; |
| | 2647 | return .null; |
| | 2648 | } |
| | 2649 | |
| 2645 | pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index { | 2650 | pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index { |
| 2646 | const gop = try coff.getOrPutGlobalSymbol(opts); | 2651 | const gop = try coff.getOrPutGlobalSymbol(opts); |
| 2647 | if (gop.found_existing) { | 2652 | if (gop.found_existing) { |
| ... | @@ -3423,8 +3428,6 @@ pub fn addReloc( | ... | @@ -3423,8 +3428,6 @@ pub fn addReloc( |
| 3423 | ) !void { | 3428 | ) !void { |
| 3424 | const gpa = coff.base.comp.gpa; | 3429 | const gpa = coff.base.comp.gpa; |
| 3425 | const target = target_si.get(coff); | 3430 | const target = target_si.get(coff); |
| 3426 | // TODO: Could duplicate the uninit flag on Symbol.flags? | | |
| 3427 | assert(!coff.targetLoad(loc_si.get(coff).section_number.header(coff).flags).CNT_UNINITIALIZED_DATA); | | |
| 3428 | | 3431 | |
| 3429 | const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len); | 3432 | const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len); |
| 3430 | log.debug("addReloc({d}@{d}+0x{x} -> {d}@{d}+0x{x}{s}) = {d}", .{ | 3433 | log.debug("addReloc({d}@{d}+0x{x} -> {d}@{d}+0x{x}{s}) = {d}", .{ |
| ... | @@ -4386,11 +4389,10 @@ fn loadObject( | ... | @@ -4386,11 +4389,10 @@ fn loadObject( |
| 4386 | // Resolve this once we see alias | 4389 | // Resolve this once we see alias |
| 4387 | alias.weak_external_psi = .wrap(@intCast(i)); | 4390 | alias.weak_external_psi = .wrap(@intCast(i)); |
| 4388 | } else { | 4391 | } else { |
| 4389 | sym.setValue(if (alias.si == .null) .{ | 4392 | sym.setValue(if (alias.si.unwrap()) |alias_si| .{ |
| 4390 | // See .external branch above | 4393 | .alias_si = alias_si, |
| 4391 | .alias_name = alias.name, | | |
| 4392 | } else .{ | 4394 | } else .{ |
| 4393 | .alias_si = alias.si, | 4395 | .alias_name = alias.name, |
| 4394 | }); | 4396 | }); |
| 4395 | sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux; | 4397 | sym.flags.weak_external_strat = pending_symbols.values()[i + 1].value.weak_external_aux; |
| 4396 | } | 4398 | } |
| ... | @@ -5027,35 +5029,9 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -5027,35 +5029,9 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { |
| 5027 | } | 5029 | } |
| 5028 | } | 5030 | } |
| 5029 | | 5031 | |
| 5030 | if (coff.isImage() and comp.config.link_libc) { | | |
| 5031 | const entries: []const struct { ?[]const u8, []const u8 } = if (coff.isExe()) | | |
| 5032 | if (comp.zcu == null) switch (coff.optionalHeaderField(.subsystem)) { | | |
| 5033 | .WINDOWS_CUI => &.{ | | |
| 5034 | .{ "main", "mainCRTStartup" }, | | |
| 5035 | .{ "wmain", "wmainCRTStartup" }, | | |
| 5036 | }, | | |
| 5037 | .WINDOWS_GUI => &.{ | | |
| 5038 | .{ "WinMain", "WinMainCRTStartup" }, | | |
| 5039 | .{ "wWinMain", "wWinMainCRTStartup" }, | | |
| 5040 | }, | | |
| 5041 | else => unreachable, | | |
| 5042 | } else &.{} | | |
| 5043 | else | | |
| 5044 | &.{.{ null, "_DllMainCRTStartup" }}; | | |
| 5045 | | | |
| 5046 | for (entries) |entry| { | | |
| 5047 | if (entry[0]) |required_name| { | | |
| 5048 | const str = coff.getString(required_name).unwrap() orelse continue; | | |
| 5049 | const si = coff.globals.get(.{ .name = str, .lib_name = .none }) orelse continue; | | |
| 5050 | if (si.get(coff).ni == .none) continue; | | |
| 5051 | } | | |
| 5052 | | | |
| 5053 | const si = try coff.globalSymbol(.{ .name = entry[1], .type = .code }); | | |
| 5054 | coff.updateEntry(si.get(coff).gmi); | | |
| 5055 | } | | |
| 5056 | } | | |
| 5057 | | | |
| 5058 | coff.inputs_complete = true; | 5032 | coff.inputs_complete = true; |
| | 5033 | if (comp.zcu == null) |
| | 5034 | coff.exports_complete = true; |
| 5059 | } | 5035 | } |
| 5060 | | 5036 | |
| 5061 | pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | 5037 | pub fn updateNav(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { |
| ... | @@ -5347,17 +5323,6 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { | ... | @@ -5347,17 +5323,6 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 5347 | const gpa = comp.gpa; | 5323 | const gpa = comp.gpa; |
| 5348 | const max_notes = 4; | 5324 | const max_notes = 4; |
| 5349 | | 5325 | |
| 5350 | if (coff.isImage()) { | | |
| 5351 | if (coff.entry == .none) | | |
| 5352 | comp.link_diags.addError("no entry point defined", .{}) | | |
| 5353 | else if (coff.entry.symbol(coff).get(coff).ni == .none) { | | |
| 5354 | comp.link_diags.addError( | | |
| 5355 | "no definition for entry point '{s}' found", | | |
| 5356 | .{coff.entry.globalName(coff).name.toSlice(coff)}, | | |
| 5357 | ); | | |
| 5358 | } | | |
| 5359 | } | | |
| 5360 | | | |
| 5361 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; | 5326 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; |
| 5362 | for (coff.relocs.items, 0..) |reloc, reloc_i| { | 5327 | for (coff.relocs.items, 0..) |reloc, reloc_i| { |
| 5363 | const target_sym = reloc.target.get(coff); | 5328 | const target_sym = reloc.target.get(coff); |
| ... | @@ -5406,12 +5371,20 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { | ... | @@ -5406,12 +5371,20 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 5406 | for (undef_indices.items[start_i .. i + 1]) |reference_i| { | 5371 | for (undef_indices.items[start_i .. i + 1]) |reference_i| { |
| 5407 | if (err.note_slot == num_full_notes) break; | 5372 | if (err.note_slot == num_full_notes) break; |
| 5408 | | 5373 | |
| 5409 | const loc_si = coff.relocs.items[reference_i].loc; | 5374 | const reloc = &coff.relocs.items[reference_i]; |
| | 5375 | const loc_si = reloc.loc; |
| 5410 | if (loc_si == prev_loc_si) continue; | 5376 | if (loc_si == prev_loc_si) continue; |
| 5411 | defer prev_loc_si = loc_si; | 5377 | defer prev_loc_si = loc_si; |
| 5412 | | 5378 | |
| 5413 | const loc_sym = loc_si.get(coff); | 5379 | const loc_sym = loc_si.get(coff); |
| 5414 | switch (coff.getNode(loc_sym.ni)) { | 5380 | switch (coff.getNode(loc_sym.ni)) { |
| | 5381 | .data_directories => { |
| | 5382 | const dir_align = std.mem.Alignment.of(std.coff.ImageDataDirectory); |
| | 5383 | const dir: std.coff.IMAGE.DIRECTORY_ENTRY = |
| | 5384 | @enumFromInt(dir_align.backward(reloc.offset) / @sizeOf(std.coff.IMAGE.DIRECTORY_ENTRY)); |
| | 5385 | err.addNote("referenced by data directory entry: {t}", .{dir}); |
| | 5386 | }, |
| | 5387 | .optional_header => err.addNote("referenced by optional header field", .{}), |
| 5415 | .input_section => |isi| { | 5388 | .input_section => |isi| { |
| 5416 | const other_ioi = isi.input(coff); | 5389 | const other_ioi = isi.input(coff); |
| 5417 | if (loc_sym.gmi == .none) { | 5390 | if (loc_sym.gmi == .none) { |
| ... | @@ -5577,6 +5550,17 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5577,6 +5550,17 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5577 | }) coff.late_globals_pending_index += 1; | 5550 | }) coff.late_globals_pending_index += 1; |
| 5578 | break :task; | 5551 | break :task; |
| 5579 | } | 5552 | } |
| | 5553 | if (coff.exports_complete and !coff.special_symbols_complete) { |
| | 5554 | coff.special_symbols_complete = true; |
| | 5555 | coff.flushSpecialSymbols() catch |err| switch (err) { |
| | 5556 | error.OutOfMemory => |e| return e, |
| | 5557 | else => |e| return comp.link_diags.fail( |
| | 5558 | "linker failed to flush special symbols: {t}", |
| | 5559 | .{e}, |
| | 5560 | ), |
| | 5561 | }; |
| | 5562 | break :task; |
| | 5563 | } |
| 5580 | var lazy_it = coff.lazy.iterator(); | 5564 | var lazy_it = coff.lazy.iterator(); |
| 5581 | while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) { | 5565 | while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) { |
| 5582 | const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid }; | 5566 | const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid }; |
| ... | @@ -5713,7 +5697,9 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { | ... | @@ -5713,7 +5697,9 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 5713 | if (coff.pending_uavs.count() > 0) return true; | 5697 | if (coff.pending_uavs.count() > 0) return true; |
| 5714 | if (coff.pending_input != null) return true; | 5698 | if (coff.pending_input != null) return true; |
| 5715 | if (coff.inputs_complete and coff.globals.count() > coff.global_pending_index) return true; | 5699 | if (coff.inputs_complete and coff.globals.count() > coff.global_pending_index) return true; |
| | 5700 | assert(!coff.exports_complete or coff.inputs_complete); |
| 5716 | if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true; | 5701 | if (coff.exports_complete and coff.late_globals.items.len > coff.late_globals_pending_index) return true; |
| | 5702 | if (coff.exports_complete and !coff.special_symbols_complete) return true; |
| 5717 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; | 5703 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| 5718 | if (coff.symbol_table.pending.count() > 0) return true; | 5704 | if (coff.symbol_table.pending.count() > 0) return true; |
| 5719 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; | 5705 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; |
| ... | @@ -6258,6 +6244,105 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6258,6 +6244,105 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6258 | return true; | 6244 | return true; |
| 6259 | } | 6245 | } |
| 6260 | | 6246 | |
| | 6247 | fn flushSpecialSymbols(coff: *Coff) !void { |
| | 6248 | const comp = coff.base.comp; |
| | 6249 | const gpa = comp.gpa; |
| | 6250 | const machine = coff.targetLoad(&coff.headerPtr().machine); |
| | 6251 | |
| | 6252 | if (coff.isImage()) { |
| | 6253 | // TODO: Use explicitly specified entry if set, add err if not found |
| | 6254 | const entries: []const struct { ?[]const u8, []const u8 } = if (coff.isExe()) |
| | 6255 | if (comp.config.link_libc) switch (coff.optionalHeaderField(.subsystem)) { |
| | 6256 | .WINDOWS_CUI => &.{ |
| | 6257 | .{ "main", "mainCRTStartup" }, |
| | 6258 | .{ "wmain", "wmainCRTStartup" }, |
| | 6259 | }, |
| | 6260 | .WINDOWS_GUI => &.{ |
| | 6261 | .{ "WinMain", "WinMainCRTStartup" }, |
| | 6262 | .{ "wWinMain", "wWinMainCRTStartup" }, |
| | 6263 | }, |
| | 6264 | else => unreachable, |
| | 6265 | } else &.{ |
| | 6266 | .{ "wWinMainCRTStartup", "wWinMainCRTStartup" }, |
| | 6267 | } |
| | 6268 | else |
| | 6269 | &.{.{ null, "_DllMainCRTStartup" }}; |
| | 6270 | |
| | 6271 | const entry_si = for (entries) |entry| { |
| | 6272 | if (entry[0]) |required_name| |
| | 6273 | if (coff.getDefinedGlobal(required_name) == .null) continue; |
| | 6274 | |
| | 6275 | break try coff.globalSymbol(.{ .name = entry[1], .type = .code }); |
| | 6276 | } else .null; |
| | 6277 | |
| | 6278 | if (entry_si != .null) { |
| | 6279 | log.debug( |
| | 6280 | "entry({s}, {d})", |
| | 6281 | .{ entry_si.get(coff).gmi.globalName(coff).name.toSlice(coff), entry_si }, |
| | 6282 | ); |
| | 6283 | |
| | 6284 | try coff.symbols.ensureTotalCapacity(gpa, 1); |
| | 6285 | const optional_hdr_si = coff.addSymbolAssumeCapacity(); |
| | 6286 | const optional_hdr_sym = optional_hdr_si.get(coff); |
| | 6287 | optional_hdr_sym.ni = Node.known.optional_header; |
| | 6288 | assert(optional_hdr_sym.loc_relocs == .none); |
| | 6289 | optional_hdr_sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| | 6290 | |
| | 6291 | const optional_hdr = coff.optionalHeaderStandardPtr(); |
| | 6292 | optional_hdr.address_of_entry_point = std.mem.nativeTo( |
| | 6293 | u32, |
| | 6294 | entry_si.get(coff).rva, |
| | 6295 | coff.targetEndian(), |
| | 6296 | ); |
| | 6297 | |
| | 6298 | try coff.addReloc( |
| | 6299 | optional_hdr_si, |
| | 6300 | @intFromPtr(&optional_hdr.address_of_entry_point) - @intFromPtr(optional_hdr), |
| | 6301 | entry_si, |
| | 6302 | .{ .known = 0 }, |
| | 6303 | switch (machine) { |
| | 6304 | else => |tag| @panic(@tagName(tag)), |
| | 6305 | .AMD64 => .{ .AMD64 = .ADDR32NB }, |
| | 6306 | .I386 => .{ .I386 = .DIR32NB }, |
| | 6307 | }, |
| | 6308 | ); |
| | 6309 | } |
| | 6310 | } |
| | 6311 | |
| | 6312 | if (coff.getDefinedGlobal("_tls_used").unwrap()) |tls_used_si| { |
| | 6313 | const tls_directory = coff.dataDirectoryPtr(.TLS); |
| | 6314 | tls_directory.* = .{ |
| | 6315 | .virtual_address = tls_used_si.get(coff).rva, |
| | 6316 | .size = switch (coff.targetLoad(&coff.optionalHeaderStandardPtr().magic)) { |
| | 6317 | _ => unreachable, |
| | 6318 | .PE32 => 24, |
| | 6319 | .@"PE32+" => 40, |
| | 6320 | }, |
| | 6321 | }; |
| | 6322 | if (coff.targetEndian() != native_endian) |
| | 6323 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| | 6324 | |
| | 6325 | try coff.symbols.ensureTotalCapacity(gpa, 1); |
| | 6326 | const data_dir_si = coff.addSymbolAssumeCapacity(); |
| | 6327 | const data_dir_sym = data_dir_si.get(coff); |
| | 6328 | data_dir_sym.ni = Node.known.data_directories; |
| | 6329 | assert(data_dir_sym.loc_relocs == .none); |
| | 6330 | data_dir_sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| | 6331 | |
| | 6332 | try coff.addReloc( |
| | 6333 | data_dir_si, |
| | 6334 | @intFromPtr(&tls_directory.virtual_address) - @intFromPtr(coff.dataDirectorySlice().ptr), |
| | 6335 | tls_used_si, |
| | 6336 | .{ .known = 0 }, |
| | 6337 | switch (machine) { |
| | 6338 | else => |tag| @panic(@tagName(tag)), |
| | 6339 | .AMD64 => .{ .AMD64 = .ADDR32NB }, |
| | 6340 | .I386 => .{ .I386 = .DIR32NB }, |
| | 6341 | }, |
| | 6342 | ); |
| | 6343 | } |
| | 6344 | } |
| | 6345 | |
| 6261 | fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | 6346 | fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 6262 | const zcu = pt.zcu; | 6347 | const zcu = pt.zcu; |
| 6263 | const gpa = zcu.gpa; | 6348 | const gpa = zcu.gpa; |
| ... | @@ -6312,7 +6397,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { | ... | @@ -6312,7 +6397,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 6312 | } | 6397 | } |
| 6313 | | 6398 | |
| 6314 | fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | 6399 | fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6315 | log.debug("flushMoved({s})", .{@tagName(coff.getNode(ni))}); | 6400 | log.debug("flushMoved({s}, n{d})", .{ @tagName(coff.getNode(ni)), ni }); |
| 6316 | switch (coff.getNode(ni)) { | 6401 | switch (coff.getNode(ni)) { |
| 6317 | .file, | 6402 | .file, |
| 6318 | .header, | 6403 | .header, |
| ... | @@ -6500,7 +6585,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -6500,7 +6585,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6500 | | 6585 | |
| 6501 | fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { | 6586 | fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6502 | const offset, const size = ni.location(&coff.mf).resolve(&coff.mf); | 6587 | const offset, const size = ni.location(&coff.mf).resolve(&coff.mf); |
| 6503 | log.debug("flushResized({s}, 0x{x})", .{ @tagName(coff.getNode(ni)), size }); | 6588 | log.debug("flushResized({s}, n{d}, 0x{x})", .{ @tagName(coff.getNode(ni)), ni, size }); |
| 6504 | | 6589 | |
| 6505 | switch (coff.getNode(ni)) { | 6590 | switch (coff.getNode(ni)) { |
| 6506 | .file => { | 6591 | .file => { |
| ... | @@ -6779,6 +6864,7 @@ fn updateExportsInner( | ... | @@ -6779,6 +6864,7 @@ fn updateExportsInner( |
| 6779 | }; | 6864 | }; |
| 6780 | while (try coff.idle(pt.tid)) {} | 6865 | while (try coff.idle(pt.tid)) {} |
| 6781 | | 6866 | |
| | 6867 | const machine = coff.targetLoad(&coff.headerPtr().machine); |
| 6782 | const exported_ni = exported_si.node(coff); | 6868 | const exported_ni = exported_si.node(coff); |
| 6783 | const exported_sym = exported_si.get(coff); | 6869 | const exported_sym = exported_si.get(coff); |
| 6784 | for (export_indices) |export_index| { | 6870 | for (export_indices) |export_index| { |
| ... | @@ -6795,18 +6881,7 @@ fn updateExportsInner( | ... | @@ -6795,18 +6881,7 @@ fn updateExportsInner( |
| 6795 | export_sym.section_number = exported_sym.section_number; | 6881 | export_sym.section_number = exported_sym.section_number; |
| 6796 | defer export_si.applyTargetRelocs(coff, .none); | 6882 | defer export_si.applyTargetRelocs(coff, .none); |
| 6797 | | 6883 | |
| 6798 | if (coff.isImage()) { | 6884 | if (!coff.isImage()) continue; |
| 6799 | if (@"export".opts.name.eqlSlice("_tls_used", ip)) { | | |
| 6800 | const tls_directory = coff.dataDirectoryPtr(.TLS); | | |
| 6801 | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.value.size }; | | |
| 6802 | if (coff.targetEndian() != native_endian) | | |
| 6803 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); | | |
| 6804 | } else if ((coff.isExe() and @"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) or | | |
| 6805 | (!coff.isExe() and @"export".opts.name.eqlSlice("_DllMainCRTStartup", ip))) | | |
| 6806 | { | | |
| 6807 | coff.updateEntry(export_sym.gmi); | | |
| 6808 | } | | |
| 6809 | } else continue; | | |
| 6810 | | 6885 | |
| 6811 | const entries_ctx = ExportTable.Adapter{ .coff = coff }; | 6886 | const entries_ctx = ExportTable.Adapter{ .coff = coff }; |
| 6812 | const gop = try coff.export_table.entries.getOrPutAdapted( | 6887 | const gop = try coff.export_table.entries.getOrPutAdapted( |
| ... | @@ -6888,7 +6963,11 @@ fn updateExportsInner( | ... | @@ -6888,7 +6963,11 @@ fn updateExportsInner( |
| 6888 | @intCast(@sizeOf(std.coff.ExportAddressTableEntry) * gop.index), | 6963 | @intCast(@sizeOf(std.coff.ExportAddressTableEntry) * gop.index), |
| 6889 | export_si, | 6964 | export_si, |
| 6890 | .{ .known = 0 }, | 6965 | .{ .known = 0 }, |
| 6891 | .{ .AMD64 = .ADDR32NB }, | 6966 | switch (machine) { |
| | 6967 | else => |tag| @panic(@tagName(tag)), |
| | 6968 | .AMD64 => .{ .AMD64 = .ADDR32NB }, |
| | 6969 | .I386 => .{ .I386 = .DIR32NB }, |
| | 6970 | }, |
| 6892 | ); | 6971 | ); |
| 6893 | } else { | 6972 | } else { |
| 6894 | gop.value_ptr.si = export_si; | 6973 | gop.value_ptr.si = export_si; |
| ... | @@ -6898,20 +6977,6 @@ fn updateExportsInner( | ... | @@ -6898,20 +6977,6 @@ fn updateExportsInner( |
| 6898 | } | 6977 | } |
| 6899 | } | 6978 | } |
| 6900 | | 6979 | |
| 6901 | /// Caller ensures that `applyTargetRelocs` will be called on `si` eventually | | |
| 6902 | fn updateEntry(coff: *Coff, gmi: Node.GlobalMapIndex) void { | | |
| 6903 | const si = gmi.symbol(coff); | | |
| 6904 | log.debug("updateEntry({s}, {d})", .{ gmi.globalName(coff).name.toSlice(coff), si }); | | |
| 6905 | | | |
| 6906 | if (coff.entry != .none) | | |
| 6907 | coff.entry.symbol(coff).get(coff).flags.is_entry = false; | | |
| 6908 | | | |
| 6909 | // TODO: Should we detect the subsystem like link.exe does (if not explicitly set) based on entry name? | | |
| 6910 | | | |
| 6911 | coff.entry = gmi; | | |
| 6912 | si.get(coff).flags.is_entry = true; | | |
| 6913 | } | | |
| 6914 | | | |
| 6915 | pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void { | 6980 | pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void { |
| 6916 | _ = coff; | 6981 | _ = coff; |
| 6917 | _ = exported; | 6982 | _ = exported; |
| ... | @@ -6928,11 +6993,15 @@ fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void { | ... | @@ -6928,11 +6993,15 @@ fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 6928 | const stderr = try io.lockStderr(&buffer, null); | 6993 | const stderr = try io.lockStderr(&buffer, null); |
| 6929 | defer io.unlockStderr(); | 6994 | defer io.unlockStderr(); |
| 6930 | const w = &stderr.file_writer.interface; | 6995 | const w = &stderr.file_writer.interface; |
| 6931 | try coff.dump(w, tid); | 6996 | _ = try coff.dump(w, tid); |
| 6932 | } | 6997 | } |
| 6933 | | 6998 | |
| 6934 | pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !void { | 6999 | pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { |
| 6935 | try coff.printNode(tid, w, .root, 0); | 7000 | if (coff.dump_snapshot) { |
| | 7001 | try coff.printNode(tid, w, .root, 0); |
| | 7002 | return .enabled; |
| | 7003 | } |
| | 7004 | return .disabled; |
| 6936 | } | 7005 | } |
| 6937 | | 7006 | |
| 6938 | pub fn printNode( | 7007 | pub fn printNode( |