| ... | @@ -74,12 +74,12 @@ pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct { | ... | @@ -74,12 +74,12 @@ pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct { |
| 74 | alignment: InternPool.Alignment, | 74 | alignment: InternPool.Alignment, |
| 75 | }), | 75 | }), |
| 76 | relocs: std.ArrayList(Reloc), | 76 | relocs: std.ArrayList(Reloc), |
| | 77 | entry: Node.GlobalMapIndex, |
| 77 | const_prog_node: std.Progress.Node, | 78 | const_prog_node: std.Progress.Node, |
| 78 | synth_prog_node: std.Progress.Node, | 79 | synth_prog_node: std.Progress.Node, |
| 79 | symbol_prog_node: std.Progress.Node, | 80 | symbol_prog_node: std.Progress.Node, |
| 80 | member_prog_node: std.Progress.Node, | 81 | member_prog_node: std.Progress.Node, |
| 81 | input_prog_node: std.Progress.Node, | 82 | input_prog_node: std.Progress.Node, |
| 82 | subsystem: ?std.zig.Subsystem, | | |
| 83 | dump_snapshot: bool, | 83 | dump_snapshot: bool, |
| 84 | | 84 | |
| 85 | pub const default_file_alignment: u16 = 0x200; | 85 | pub const default_file_alignment: u16 = 0x200; |
| ... | @@ -728,10 +728,37 @@ pub const ImportTable = struct { | ... | @@ -728,10 +728,37 @@ pub const ImportTable = struct { |
| 728 | import_lookup_table_ni: MappedFile.Node.Index, | 728 | import_lookup_table_ni: MappedFile.Node.Index, |
| 729 | import_address_table_si: Symbol.Index, | 729 | import_address_table_si: Symbol.Index, |
| 730 | import_hint_name_table_ni: MappedFile.Node.Index, | 730 | import_hint_name_table_ni: MappedFile.Node.Index, |
| | 731 | // All .iat_ptr globals that reference this table. |
| | 732 | // This is separate from `iat_symbol_indices` because multiple symbols |
| | 733 | // can reference to the same iat entry, after name demangling. |
| | 734 | import_address_table_symbols: std.ArrayList(Symbol.Index), |
| 731 | len: u32, | 735 | len: u32, |
| 732 | hint_name_len: u32, | 736 | hint_name_len: u32, |
| 733 | }; | 737 | }; |
| 734 | | 738 | |
| | 739 | pub fn TableEntry(comptime magic: std.coff.OptionalHeader.Magic) type { |
| | 740 | const Payload = packed union(u31) { |
| | 741 | ordinal: packed struct(u31) { |
| | 742 | ordinal: u16, |
| | 743 | _: u15 = 0, |
| | 744 | }, |
| | 745 | hint_name_rva: u31, |
| | 746 | }; |
| | 747 | |
| | 748 | return switch (magic) { |
| | 749 | _ => comptime unreachable, |
| | 750 | .PE32 => packed struct(u32) { |
| | 751 | payload: Payload, |
| | 752 | is_ordinal: bool, |
| | 753 | }, |
| | 754 | .@"PE32+" => packed struct(u64) { |
| | 755 | payload: Payload, |
| | 756 | _: u32 = 0, |
| | 757 | is_ordinal: bool, |
| | 758 | }, |
| | 759 | }; |
| | 760 | } |
| | 761 | |
| 735 | const Adapter = struct { | 762 | const Adapter = struct { |
| 736 | coff: *Coff, | 763 | coff: *Coff, |
| 737 | | 764 | |
| ... | @@ -864,7 +891,8 @@ pub const Symbol = struct { | ... | @@ -864,7 +891,8 @@ pub const Symbol = struct { |
| 864 | dll_storage_class: DllStorageClass, | 891 | dll_storage_class: DllStorageClass, |
| 865 | // Only defined for .alias_si and .alias_name | 892 | // Only defined for .alias_si and .alias_name |
| 866 | weak_external_strat: WeakExternalStrat, | 893 | weak_external_strat: WeakExternalStrat, |
| 867 | _: u8 = 0, | 894 | is_entry: bool, |
| | 895 | _: u7 = 0, |
| 868 | }, | 896 | }, |
| 869 | /// Relocations contained within this symbol | 897 | /// Relocations contained within this symbol |
| 870 | loc_relocs: Reloc.Index, | 898 | loc_relocs: Reloc.Index, |
| ... | @@ -1038,7 +1066,15 @@ pub const Symbol = struct { | ... | @@ -1038,7 +1066,15 @@ pub const Symbol = struct { |
| 1038 | } | 1066 | } |
| 1039 | | 1067 | |
| 1040 | pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff) void { | 1068 | pub fn applyTargetRelocs(si: Symbol.Index, coff: *Coff) void { |
| 1041 | var ri = si.get(coff).target_relocs; | 1069 | const sym = si.get(coff); |
| | 1070 | |
| | 1071 | // TODO: Would this be better modeled using an actual reloc? Would need a si for the header |
| | 1072 | if (sym.flags.is_entry) { |
| | 1073 | log.debug("updateEntryRVA({d}, 0x{x})", .{ si, sym.rva }); |
| | 1074 | coff.optionalHeaderStandardPtr().address_of_entry_point = sym.rva; |
| | 1075 | } |
| | 1076 | |
| | 1077 | var ri = sym.target_relocs; |
| 1042 | while (ri != .none) { | 1078 | while (ri != .none) { |
| 1043 | const reloc = ri.get(coff); | 1079 | const reloc = ri.get(coff); |
| 1044 | assert(reloc.target == si); | 1080 | assert(reloc.target == si); |
| ... | @@ -1525,12 +1561,12 @@ fn create( | ... | @@ -1525,12 +1561,12 @@ fn create( |
| 1525 | }), | 1561 | }), |
| 1526 | .pending_uavs = .empty, | 1562 | .pending_uavs = .empty, |
| 1527 | .relocs = .empty, | 1563 | .relocs = .empty, |
| | 1564 | .entry = .none, |
| 1528 | .const_prog_node = .none, | 1565 | .const_prog_node = .none, |
| 1529 | .synth_prog_node = .none, | 1566 | .synth_prog_node = .none, |
| 1530 | .symbol_prog_node = .none, | 1567 | .symbol_prog_node = .none, |
| 1531 | .member_prog_node = .none, | 1568 | .member_prog_node = .none, |
| 1532 | .input_prog_node = .none, | 1569 | .input_prog_node = .none, |
| 1533 | .subsystem = options.subsystem, | | |
| 1534 | .dump_snapshot = options.enable_link_snapshots, | 1570 | .dump_snapshot = options.enable_link_snapshots, |
| 1535 | }; | 1571 | }; |
| 1536 | errdefer coff.deinit(); | 1572 | errdefer coff.deinit(); |
| ... | @@ -1549,6 +1585,11 @@ fn create( | ... | @@ -1549,6 +1585,11 @@ fn create( |
| 1549 | major_subsystem_version, | 1585 | major_subsystem_version, |
| 1550 | minor_subsystem_version, | 1586 | minor_subsystem_version, |
| 1551 | magic, | 1587 | magic, |
| | 1588 | if (options.subsystem) |s| switch (s) { |
| | 1589 | .console => .WINDOWS_CUI, |
| | 1590 | .windows => .WINDOWS_GUI, |
| | 1591 | else => return error.UnsupportedCOFFSubsystem, |
| | 1592 | } else .WINDOWS_CUI, |
| 1552 | section_align, | 1593 | section_align, |
| 1553 | std.fs.path.basename(path.sub_path), | 1594 | std.fs.path.basename(path.sub_path), |
| 1554 | ); | 1595 | ); |
| ... | @@ -1619,6 +1660,10 @@ fn isArchive(coff: *const Coff) bool { | ... | @@ -1619,6 +1660,10 @@ fn isArchive(coff: *const Coff) bool { |
| 1619 | }; | 1660 | }; |
| 1620 | } | 1661 | } |
| 1621 | | 1662 | |
| | 1663 | fn isExe(coff: *const Coff) bool { |
| | 1664 | return coff.base.comp.config.output_mode == .Exe; |
| | 1665 | } |
| | 1666 | |
| 1622 | fn isObj(coff: *const Coff) bool { | 1667 | fn isObj(coff: *const Coff) bool { |
| 1623 | return coff.base.comp.config.output_mode == .Obj; | 1668 | return coff.base.comp.config.output_mode == .Obj; |
| 1624 | } | 1669 | } |
| ... | @@ -1639,6 +1684,7 @@ fn initHeaders( | ... | @@ -1639,6 +1684,7 @@ fn initHeaders( |
| 1639 | major_subsystem_version: u16, | 1684 | major_subsystem_version: u16, |
| 1640 | minor_subsystem_version: u16, | 1685 | minor_subsystem_version: u16, |
| 1641 | magic: std.coff.OptionalHeader.Magic, | 1686 | magic: std.coff.OptionalHeader.Magic, |
| | 1687 | subsystem: std.coff.Subsystem, |
| 1642 | section_align: std.mem.Alignment, | 1688 | section_align: std.mem.Alignment, |
| 1643 | file_name: []const u8, | 1689 | file_name: []const u8, |
| 1644 | ) !void { | 1690 | ) !void { |
| ... | @@ -1841,7 +1887,7 @@ fn initHeaders( | ... | @@ -1841,7 +1887,7 @@ fn initHeaders( |
| 1841 | .size_of_image = 0, | 1887 | .size_of_image = 0, |
| 1842 | .size_of_headers = 0, | 1888 | .size_of_headers = 0, |
| 1843 | .checksum = 0, | 1889 | .checksum = 0, |
| 1844 | .subsystem = .WINDOWS_CUI, | 1890 | .subsystem = subsystem, |
| 1845 | .dll_flags = .{ | 1891 | .dll_flags = .{ |
| 1846 | .HIGH_ENTROPY_VA = true, | 1892 | .HIGH_ENTROPY_VA = true, |
| 1847 | .DYNAMIC_BASE = true, | 1893 | .DYNAMIC_BASE = true, |
| ... | @@ -1890,7 +1936,7 @@ fn initHeaders( | ... | @@ -1890,7 +1936,7 @@ fn initHeaders( |
| 1890 | .size_of_image = 0, | 1936 | .size_of_image = 0, |
| 1891 | .size_of_headers = 0, | 1937 | .size_of_headers = 0, |
| 1892 | .checksum = 0, | 1938 | .checksum = 0, |
| 1893 | .subsystem = .WINDOWS_CUI, | 1939 | .subsystem = subsystem, |
| 1894 | .dll_flags = .{ | 1940 | .dll_flags = .{ |
| 1895 | .HIGH_ENTROPY_VA = true, | 1941 | .HIGH_ENTROPY_VA = true, |
| 1896 | .DYNAMIC_BASE = true, | 1942 | .DYNAMIC_BASE = true, |
| ... | @@ -2079,9 +2125,6 @@ pub fn initBuiltins(coff: *Coff) !void { | ... | @@ -2079,9 +2125,6 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2079 | const gpa = comp.gpa; | 2125 | const gpa = comp.gpa; |
| 2080 | const target = &comp.root_mod.resolved_target.result; | 2126 | const target = &comp.root_mod.resolved_target.result; |
| 2081 | if (coff.isImage()) { | 2127 | if (coff.isImage()) { |
| 2082 | try coff.symbols.ensureUnusedCapacity(gpa, 1); | | |
| 2083 | try coff.globals.ensureUnusedCapacity(gpa, 1); | | |
| 2084 | | | |
| 2085 | const si = try coff.globalSymbol(.{ .name = "__ImageBase", .type = .data }); | 2128 | const si = try coff.globalSymbol(.{ .name = "__ImageBase", .type = .data }); |
| 2086 | const sym = si.get(coff); | 2129 | const sym = si.get(coff); |
| 2087 | sym.ni = Node.known.header; | 2130 | sym.ni = Node.known.header; |
| ... | @@ -2099,8 +2142,16 @@ pub fn initBuiltins(coff: *Coff) !void { | ... | @@ -2099,8 +2142,16 @@ pub fn initBuiltins(coff: *Coff) !void { |
| 2099 | | 2142 | |
| 2100 | for (lists) |list| { | 2143 | for (lists) |list| { |
| 2101 | const addr_info = coff.targetAddrInfo(); | 2144 | const addr_info = coff.targetAddrInfo(); |
| 2102 | const start_osmi = try coff.objectSectionMapIndex(list.start, addr_info.alignment, .{ .read = true }); | 2145 | const start_osmi = try coff.objectSectionMapIndex( |
| 2103 | const end_osmi = try coff.objectSectionMapIndex(list.end, addr_info.alignment, .{ .read = true }); | 2146 | list.start, |
| | 2147 | addr_info.alignment, |
| | 2148 | .{ .read = true }, |
| | 2149 | ); |
| | 2150 | const end_osmi = try coff.objectSectionMapIndex( |
| | 2151 | list.end, |
| | 2152 | addr_info.alignment, |
| | 2153 | .{ .read = true }, |
| | 2154 | ); |
| 2104 | | 2155 | |
| 2105 | const start_sym = start_osmi.symbol(coff).get(coff); | 2156 | const start_sym = start_osmi.symbol(coff).get(coff); |
| 2106 | try start_sym.ni.resize(&coff.mf, gpa, addr_info.size); | 2157 | try start_sym.ni.resize(&coff.mf, gpa, addr_info.size); |
| ... | @@ -2460,6 +2511,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { | ... | @@ -2460,6 +2511,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 2460 | .type = .unknown, | 2511 | .type = .unknown, |
| 2461 | .dll_storage_class = .default, | 2512 | .dll_storage_class = .default, |
| 2462 | .weak_external_strat = undefined, | 2513 | .weak_external_strat = undefined, |
| | 2514 | .is_entry = false, |
| 2463 | }, | 2515 | }, |
| 2464 | .loc_relocs = .none, | 2516 | .loc_relocs = .none, |
| 2465 | .target_relocs = .none, | 2517 | .target_relocs = .none, |
| ... | @@ -2482,14 +2534,14 @@ fn getOrPutString(coff: *Coff, string: []const u8) !String { | ... | @@ -2482,14 +2534,14 @@ fn getOrPutString(coff: *Coff, string: []const u8) !String { |
| 2482 | fn getOrPutOptionalString(coff: *Coff, string: ?[]const u8) !String.Optional { | 2534 | fn getOrPutOptionalString(coff: *Coff, string: ?[]const u8) !String.Optional { |
| 2483 | return (try coff.getOrPutString(string orelse return .none)).toOptional(); | 2535 | return (try coff.getOrPutString(string orelse return .none)).toOptional(); |
| 2484 | } | 2536 | } |
| 2485 | fn getString(coff: *Coff, string: []const u8) ?String { | 2537 | fn getString(coff: *Coff, string: []const u8) String.Optional { |
| 2486 | if (coff.strings.getKeyAdapted( | 2538 | if (coff.strings.getKeyAdapted( |
| 2487 | string, | 2539 | string, |
| 2488 | std.hash_map.StringIndexAdapter{ .bytes = &coff.string_bytes }, | 2540 | std.hash_map.StringIndexAdapter{ .bytes = &coff.string_bytes }, |
| 2489 | )) |key| | 2541 | )) |key| |
| 2490 | return @enumFromInt(key) | 2542 | return @as(String, @enumFromInt(key)).toOptional() |
| 2491 | else | 2543 | else |
| 2492 | return null; | 2544 | return .none; |
| 2493 | } | 2545 | } |
| 2494 | | 2546 | |
| 2495 | /// If the name does not fit in the symbol header, adds it to the symbol table string table. | 2547 | /// If the name does not fit in the symbol header, adds it to the symbol table string table. |
| ... | @@ -4882,12 +4934,13 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { | ... | @@ -4882,12 +4934,13 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { |
| 4882 | | 4934 | |
| 4883 | pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { | 4935 | pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { |
| 4884 | _ = prog_node; | 4936 | _ = prog_node; |
| | 4937 | const base = coff.base; |
| | 4938 | const comp = base.comp; |
| | 4939 | |
| 4885 | log.debug("prelink()", .{}); | 4940 | log.debug("prelink()", .{}); |
| 4886 | | 4941 | |
| 4887 | if (coff.pending_default_libs.items.len > 0) { | 4942 | if (coff.pending_default_libs.items.len > 0) { |
| 4888 | // Libs provided by /DEFAULTLIB arguments in objects are searched after all other inputs | 4943 | // Libs provided by /DEFAULTLIB arguments in objects are searched after all other inputs |
| 4889 | const base = coff.base; | | |
| 4890 | const comp = base.comp; | | |
| 4891 | const gpa = comp.gpa; | 4944 | const gpa = comp.gpa; |
| 4892 | const arena = comp.arena; | 4945 | const arena = comp.arena; |
| 4893 | const target = &comp.root_mod.resolved_target.result; | 4946 | const target = &comp.root_mod.resolved_target.result; |
| ... | @@ -4949,6 +5002,34 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { | ... | @@ -4949,6 +5002,34 @@ pub fn prelink(coff: *Coff, prog_node: std.Progress.Node) link.Error!void { |
| 4949 | } | 5002 | } |
| 4950 | } | 5003 | } |
| 4951 | | 5004 | |
| | 5005 | if (coff.isImage() and comp.config.link_libc) { |
| | 5006 | const entries: []const struct { ?[]const u8, []const u8 } = if (coff.isExe()) |
| | 5007 | if (comp.zcu == null) switch (coff.optionalHeaderField(.subsystem)) { |
| | 5008 | .WINDOWS_CUI => &.{ |
| | 5009 | .{ "main", "mainCRTStartup" }, |
| | 5010 | .{ "wmain", "wmainCRTStartup" }, |
| | 5011 | }, |
| | 5012 | .WINDOWS_GUI => &.{ |
| | 5013 | .{ "WinMain", "WinMainCRTStartup" }, |
| | 5014 | .{ "wWinMain", "wWinMainCRTStartup" }, |
| | 5015 | }, |
| | 5016 | else => unreachable, |
| | 5017 | } else &.{} |
| | 5018 | else |
| | 5019 | &.{.{ null, "_DllMainCRTStartup" }}; |
| | 5020 | |
| | 5021 | for (entries) |entry| { |
| | 5022 | if (entry[0]) |required_name| { |
| | 5023 | const str = coff.getString(required_name).unwrap() orelse continue; |
| | 5024 | const si = coff.globals.get(.{ .name = str, .lib_name = .none }) orelse continue; |
| | 5025 | if (si.get(coff).ni == .none) continue; |
| | 5026 | } |
| | 5027 | |
| | 5028 | const si = try coff.globalSymbol(.{ .name = entry[1], .type = .code }); |
| | 5029 | coff.updateEntry(si.get(coff).gmi); |
| | 5030 | } |
| | 5031 | } |
| | 5032 | |
| 4952 | coff.inputs_complete = true; | 5033 | coff.inputs_complete = true; |
| 4953 | } | 5034 | } |
| 4954 | | 5035 | |
| ... | @@ -5241,6 +5322,17 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { | ... | @@ -5241,6 +5322,17 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 5241 | const gpa = comp.gpa; | 5322 | const gpa = comp.gpa; |
| 5242 | const max_notes = 4; | 5323 | const max_notes = 4; |
| 5243 | | 5324 | |
| | 5325 | if (coff.isImage()) { |
| | 5326 | if (coff.entry == .none) |
| | 5327 | comp.link_diags.addError("no entry point defined", .{}) |
| | 5328 | else if (coff.entry.symbol(coff).get(coff).ni == .none) { |
| | 5329 | comp.link_diags.addError( |
| | 5330 | "no definition for entry point '{s}' found", |
| | 5331 | .{coff.entry.globalName(coff).name.toSlice(coff)}, |
| | 5332 | ); |
| | 5333 | } |
| | 5334 | } |
| | 5335 | |
| 5244 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; | 5336 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; |
| 5245 | for (coff.relocs.items, 0..) |reloc, reloc_i| { | 5337 | for (coff.relocs.items, 0..) |reloc, reloc_i| { |
| 5246 | const target_sym = reloc.target.get(coff); | 5338 | const target_sym = reloc.target.get(coff); |
| ... | @@ -5988,6 +6080,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -5988,6 +6080,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 5988 | .import_lookup_table_ni = import_lookup_table_ni, | 6080 | .import_lookup_table_ni = import_lookup_table_ni, |
| 5989 | .import_address_table_si = import_address_table_si, | 6081 | .import_address_table_si = import_address_table_si, |
| 5990 | .import_hint_name_table_ni = import_hint_name_table_ni, | 6082 | .import_hint_name_table_ni = import_hint_name_table_ni, |
| | 6083 | .import_address_table_symbols = .empty, |
| 5991 | .len = 0, | 6084 | .len = 0, |
| 5992 | .hint_name_len = @intCast(import_hint_name_table_len), | 6085 | .hint_name_len = @intCast(import_hint_name_table_len), |
| 5993 | }; | 6086 | }; |
| ... | @@ -6034,20 +6127,20 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6034,20 +6127,20 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6034 | gop.value_ptr.len = import_symbol_index + 1; | 6127 | gop.value_ptr.len = import_symbol_index + 1; |
| 6035 | const new_symbol_table_size = addr_info.size * (import_symbol_index + 2); | 6128 | const new_symbol_table_size = addr_info.size * (import_symbol_index + 2); |
| 6036 | | 6129 | |
| | 6130 | try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size); |
| | 6131 | const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff); |
| | 6132 | try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size); |
| | 6133 | |
| 6037 | const opt_name = import.name.toSlice(coff); | 6134 | const opt_name = import.name.toSlice(coff); |
| 6038 | const opt_import_hint_name_index = if (opt_name) |name| blk: { | 6135 | const opt_import_hint_name_index = if (opt_name) |name| blk: { |
| 6039 | const import_hint_name_index = gop.value_ptr.hint_name_len; | 6136 | const import_hint_name_index = gop.value_ptr.hint_name_len; |
| 6040 | gop.value_ptr.hint_name_len = @intCast( | 6137 | gop.value_ptr.hint_name_len = @intCast( |
| 6041 | import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1), | 6138 | import_hint_name_align.forward(import_hint_name_index + 2 + name.len + 1), |
| 6042 | ); | 6139 | ); |
| | 6140 | try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len); |
| 6043 | break :blk import_hint_name_index; | 6141 | break :blk import_hint_name_index; |
| 6044 | } else null; | 6142 | } else null; |
| 6045 | | 6143 | |
| 6046 | try gop.value_ptr.import_lookup_table_ni.resize(&coff.mf, gpa, new_symbol_table_size); | | |
| 6047 | const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff); | | |
| 6048 | try import_address_table_ni.resize(&coff.mf, gpa, new_symbol_table_size); | | |
| 6049 | try gop.value_ptr.import_hint_name_table_ni.resize(&coff.mf, gpa, gop.value_ptr.hint_name_len); | | |
| 6050 | | | |
| 6051 | const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: { | 6144 | const import_hint_name_rva = if (opt_import_hint_name_index) |import_hint_name_index| blk: { |
| 6052 | const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf); | 6145 | const import_hint_name_slice = gop.value_ptr.import_hint_name_table_ni.slice(&coff.mf); |
| 6053 | const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2])); | 6146 | const ordinal_hint: *u16 = @ptrCast(@alignCast(import_hint_name_slice[import_hint_name_index..][0..2])); |
| ... | @@ -6062,26 +6155,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6062,26 +6155,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6062 | switch (addr_info.magic) { | 6155 | switch (addr_info.magic) { |
| 6063 | _ => unreachable, | 6156 | _ => unreachable, |
| 6064 | inline .PE32, .@"PE32+" => |ct_magic| { | 6157 | inline .PE32, .@"PE32+" => |ct_magic| { |
| 6065 | const Payload = packed union(u31) { | 6158 | const Entry = ImportTable.TableEntry(ct_magic); |
| 6066 | ordinal: packed struct(u31) { | | |
| 6067 | ordinal: u16, | | |
| 6068 | _: u15 = 0, | | |
| 6069 | }, | | |
| 6070 | hint_name_rva: u31, | | |
| 6071 | }; | | |
| 6072 | | | |
| 6073 | const Entry = switch (ct_magic) { | | |
| 6074 | _ => comptime unreachable, | | |
| 6075 | .PE32 => packed struct(u32) { | | |
| 6076 | payload: Payload, | | |
| 6077 | is_ordinal: bool, | | |
| 6078 | }, | | |
| 6079 | .@"PE32+" => packed struct(u64) { | | |
| 6080 | payload: Payload, | | |
| 6081 | _: u32 = 0, | | |
| 6082 | is_ordinal: bool, | | |
| 6083 | }, | | |
| 6084 | }; | | |
| 6085 | const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice)); | 6159 | const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice)); |
| 6086 | const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice)); | 6160 | const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice)); |
| 6087 | const import_hint_name_rvas: [2]Entry = .{ | 6161 | const import_hint_name_rvas: [2]Entry = .{ |
| ... | @@ -6112,6 +6186,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { | ... | @@ -6112,6 +6186,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool { |
| 6112 | sym.ni = iat_sym.ni; | 6186 | sym.ni = iat_sym.ni; |
| 6113 | sym.setValue(.{ .node_offset = iat_offset }); | 6187 | sym.setValue(.{ .node_offset = iat_offset }); |
| 6114 | si.flushMoved(coff); | 6188 | si.flushMoved(coff); |
| | 6189 | (try gop.value_ptr.import_address_table_symbols.addOne(gpa)).* = si; |
| 6115 | }, | 6190 | }, |
| 6116 | .thunk => { | 6191 | .thunk => { |
| 6117 | sym.section_number = Symbol.Index.text.get(coff).section_number; | 6192 | sym.section_number = Symbol.Index.text.get(coff).section_number; |
| ... | @@ -6281,15 +6356,18 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -6281,15 +6356,18 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6281 | coff.computeNodeRva(ni), | 6356 | coff.computeNodeRva(ni), |
| 6282 | ), | 6357 | ), |
| 6283 | .import_address_table => |import_index| { | 6358 | .import_address_table => |import_index| { |
| 6284 | const import_address_table_si = import_index.get(coff).import_address_table_si; | 6359 | const entry = import_index.get(coff); |
| | 6360 | const import_address_table_si = entry.import_address_table_si; |
| 6285 | import_address_table_si.flushMoved(coff); | 6361 | import_address_table_si.flushMoved(coff); |
| 6286 | coff.targetStore( | 6362 | coff.targetStore( |
| 6287 | &coff.importDirectoryEntryPtr(import_index).import_address_table_rva, | 6363 | &coff.importDirectoryEntryPtr(import_index).import_address_table_rva, |
| 6288 | import_address_table_si.get(coff).rva, | 6364 | import_address_table_si.get(coff).rva, |
| 6289 | ); | 6365 | ); |
| | 6366 | |
| | 6367 | for (entry.import_address_table_symbols.items) |iat_ptr_si| |
| | 6368 | iat_ptr_si.flushMoved(coff); |
| 6290 | }, | 6369 | }, |
| 6291 | .import_hint_name_table => |import_index| { | 6370 | .import_hint_name_table => |import_index| { |
| 6292 | const target_endian = coff.targetEndian(); | | |
| 6293 | const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic); | 6371 | const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic); |
| 6294 | const import_hint_name_rva = coff.computeNodeRva(ni); | 6372 | const import_hint_name_rva = coff.computeNodeRva(ni); |
| 6295 | coff.targetStore( | 6373 | coff.targetStore( |
| ... | @@ -6302,32 +6380,36 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -6302,32 +6380,36 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6302 | import_entry.import_address_table_si.node(coff).slice(&coff.mf); | 6380 | import_entry.import_address_table_si.node(coff).slice(&coff.mf); |
| 6303 | const import_hint_name_slice = ni.slice(&coff.mf); | 6381 | const import_hint_name_slice = ni.slice(&coff.mf); |
| 6304 | const import_hint_name_align = ni.alignment(&coff.mf); | 6382 | const import_hint_name_align = ni.alignment(&coff.mf); |
| | 6383 | |
| 6305 | var import_hint_name_index: u32 = 0; | 6384 | var import_hint_name_index: u32 = 0; |
| 6306 | for (0..import_entry.len) |import_symbol_index| { | 6385 | for (0..import_entry.len) |import_symbol_index| { |
| 6307 | import_hint_name_index = @intCast(import_hint_name_align.forward( | | |
| 6308 | std.mem.indexOfScalarPos( | | |
| 6309 | u8, | | |
| 6310 | import_hint_name_slice, | | |
| 6311 | import_hint_name_index, | | |
| 6312 | 0, | | |
| 6313 | ).? + 1, | | |
| 6314 | )); | | |
| 6315 | switch (magic) { | 6386 | switch (magic) { |
| 6316 | _ => unreachable, | 6387 | _ => unreachable, |
| 6317 | inline .PE32, .@"PE32+" => |ct_magic| { | 6388 | inline .PE32, .@"PE32+" => |ct_magic| { |
| 6318 | const Addr = TargetAddr(ct_magic); | 6389 | const Entry = ImportTable.TableEntry(ct_magic); |
| 6319 | const import_lookup_table: []Addr = @ptrCast(@alignCast(import_lookup_slice)); | 6390 | const import_lookup_table: []Entry = @ptrCast(@alignCast(import_lookup_slice)); |
| 6320 | const import_address_table: []Addr = @ptrCast(@alignCast(import_address_slice)); | 6391 | const import_address_table: []Entry = @ptrCast(@alignCast(import_address_slice)); |
| 6321 | const rva = std.mem.nativeTo( | 6392 | |
| 6322 | Addr, | 6393 | var entry = coff.targetLoad(&import_lookup_table[import_symbol_index]); |
| 6323 | import_hint_name_rva + import_hint_name_index, | 6394 | if (entry.is_ordinal) |
| 6324 | target_endian, | 6395 | continue; |
| 6325 | ); | 6396 | |
| 6326 | import_lookup_table[import_symbol_index] = rva; | 6397 | import_hint_name_index = @intCast(import_hint_name_align.forward( |
| 6327 | import_address_table[import_symbol_index] = rva; | 6398 | std.mem.indexOfScalarPos( |
| | 6399 | u8, |
| | 6400 | import_hint_name_slice, |
| | 6401 | import_hint_name_index, |
| | 6402 | 0, |
| | 6403 | ).? + 1, |
| | 6404 | )); |
| | 6405 | |
| | 6406 | entry.payload.hint_name_rva = @intCast(import_hint_name_rva + import_hint_name_index); |
| | 6407 | import_hint_name_index += 2; |
| | 6408 | |
| | 6409 | coff.targetStore(&import_lookup_table[import_symbol_index], entry); |
| | 6410 | coff.targetStore(&import_address_table[import_symbol_index], entry); |
| 6328 | }, | 6411 | }, |
| 6329 | } | 6412 | } |
| 6330 | import_hint_name_index += 2; | | |
| 6331 | } | 6413 | } |
| 6332 | }, | 6414 | }, |
| 6333 | .export_directory_table => { | 6415 | .export_directory_table => { |
| ... | @@ -6679,14 +6761,16 @@ fn updateExportsInner( | ... | @@ -6679,14 +6761,16 @@ fn updateExportsInner( |
| 6679 | export_sym.section_number = exported_sym.section_number; | 6761 | export_sym.section_number = exported_sym.section_number; |
| 6680 | defer export_si.applyTargetRelocs(coff); | 6762 | defer export_si.applyTargetRelocs(coff); |
| 6681 | | 6763 | |
| 6682 | if (isImage(coff)) { | 6764 | if (coff.isImage()) { |
| 6683 | if (@"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) { | 6765 | if (@"export".opts.name.eqlSlice("_tls_used", ip)) { |
| 6684 | coff.optionalHeaderStandardPtr().address_of_entry_point = exported_sym.rva; | | |
| 6685 | } else if (@"export".opts.name.eqlSlice("_tls_used", ip)) { | | |
| 6686 | const tls_directory = coff.dataDirectoryPtr(.TLS); | 6766 | const tls_directory = coff.dataDirectoryPtr(.TLS); |
| 6687 | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.value.size }; | 6767 | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.value.size }; |
| 6688 | if (coff.targetEndian() != native_endian) | 6768 | if (coff.targetEndian() != native_endian) |
| 6689 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); | 6769 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| | 6770 | } else if ((coff.isExe() and @"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) or |
| | 6771 | (!coff.isExe() and @"export".opts.name.eqlSlice("_DllMainCRTStartup", ip))) |
| | 6772 | { |
| | 6773 | coff.updateEntry(export_sym.gmi); |
| 6690 | } | 6774 | } |
| 6691 | } else continue; | 6775 | } else continue; |
| 6692 | | 6776 | |
| ... | @@ -6780,6 +6864,20 @@ fn updateExportsInner( | ... | @@ -6780,6 +6864,20 @@ fn updateExportsInner( |
| 6780 | } | 6864 | } |
| 6781 | } | 6865 | } |
| 6782 | | 6866 | |
| | 6867 | /// Caller ensures that `applyTargetRelocs` will be called on `si` eventually |
| | 6868 | fn updateEntry(coff: *Coff, gmi: Node.GlobalMapIndex) void { |
| | 6869 | const si = gmi.symbol(coff); |
| | 6870 | log.debug("updateEntry({s}, {d})", .{ gmi.globalName(coff).name.toSlice(coff), si }); |
| | 6871 | |
| | 6872 | if (coff.entry != .none) |
| | 6873 | coff.entry.symbol(coff).get(coff).flags.is_entry = false; |
| | 6874 | |
| | 6875 | // TODO: Should we detect the subsystem like link.exe does (if not explicitly set) based on entry name? |
| | 6876 | |
| | 6877 | coff.entry = gmi; |
| | 6878 | si.get(coff).flags.is_entry = true; |
| | 6879 | } |
| | 6880 | |
| 6783 | pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void { | 6881 | pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void { |
| 6784 | _ = coff; | 6882 | _ = coff; |
| 6785 | _ = exported; | 6883 | _ = exported; |