| ... | ... | @@ -31,6 +31,18 @@ long_names_table: LongNamesTable, |
| 31 | 31 | import_table: ImportTable, |
| 32 | 32 | export_table: ExportTable, |
| 33 | 33 | symbol_table: SymbolTable, |
| 34 | inputs: std.ArrayList(struct { |
| 35 | path: std.Build.Cache.Path, |
| 36 | archive_name: ?[]const u8, |
| 37 | first_si: Symbol.Index, |
| 38 | last_si: Symbol.Index, |
| 39 | }), |
| 40 | input_sections: std.ArrayList(struct { |
| 41 | ii: Node.InputIndex, |
| 42 | si: Symbol.Index, |
| 43 | file_location: MappedFile.Node.FileLocation, |
| 44 | }), |
| 45 | input_section_pending_index: u32, |
| 34 | 46 | strings: std.HashMapUnmanaged( |
| 35 | 47 | u32, |
| 36 | 48 | void, |
| ... | ... | @@ -59,6 +71,7 @@ const_prog_node: std.Progress.Node, |
| 59 | 71 | synth_prog_node: std.Progress.Node, |
| 60 | 72 | symbol_prog_node: std.Progress.Node, |
| 61 | 73 | member_prog_node: std.Progress.Node, |
| 74 | input_prog_node: std.Progress.Node, |
| 62 | 75 | dump_snapshot: bool, |
| 63 | 76 | |
| 64 | 77 | pub const default_file_alignment: u16 = 0x200; |
| ... | ... | @@ -185,6 +198,7 @@ pub const Node = union(enum) { |
| 185 | 198 | |
| 186 | 199 | pseudo_section: PseudoSectionMapIndex, |
| 187 | 200 | object_section: ObjectSectionMapIndex, |
| 201 | input_section: InputSectionIndex, |
| 188 | 202 | global: GlobalMapIndex, |
| 189 | 203 | nav: NavMapIndex, |
| 190 | 204 | uav: UavMapIndex, |
| ... | ... | @@ -266,6 +280,46 @@ pub const Node = union(enum) { |
| 266 | 280 | } |
| 267 | 281 | }; |
| 268 | 282 | |
| 283 | pub const InputIndex = enum(u32) { |
| 284 | _, |
| 285 | |
| 286 | pub fn path(ii: InputIndex, coff: *const Coff) std.Build.Cache.Path { |
| 287 | return coff.inputs.items[@intFromEnum(ii)].path; |
| 288 | } |
| 289 | |
| 290 | pub fn archiveName(ii: InputIndex, coff: *const Coff) ?[]const u8 { |
| 291 | return coff.inputs.items[@intFromEnum(ii)].archive_name; |
| 292 | } |
| 293 | |
| 294 | pub fn firstSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { |
| 295 | return coff.inputs.items[@intFromEnum(ii)].first_si; |
| 296 | } |
| 297 | |
| 298 | pub fn lastSymbol(ii: InputIndex, coff: *const Coff) Symbol.Index { |
| 299 | return coff.inputs.items[@intFromEnum(ii)].last_si; |
| 300 | } |
| 301 | }; |
| 302 | |
| 303 | pub const InputSectionIndex = enum(u32) { |
| 304 | _, |
| 305 | |
| 306 | pub fn input(isi: InputSectionIndex, coff: *const Coff) InputIndex { |
| 307 | return coff.input_sections.items[@intFromEnum(isi)].ii; |
| 308 | } |
| 309 | |
| 310 | pub fn fileLocation(isi: InputSectionIndex, coff: *const Coff) MappedFile.Node.FileLocation { |
| 311 | return coff.input_sections.items[@intFromEnum(isi)].file_location; |
| 312 | } |
| 313 | |
| 314 | pub fn symbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index { |
| 315 | return coff.input_sections.items[@intFromEnum(isi)].si; |
| 316 | } |
| 317 | |
| 318 | pub fn lastSymbol(isi: InputSectionIndex, coff: *const Coff) Symbol.Index { |
| 319 | return coff.input_sections.items[@intFromEnum(isi)].last_si; |
| 320 | } |
| 321 | }; |
| 322 | |
| 269 | 323 | pub const LazyMapRef = struct { |
| 270 | 324 | kind: link.File.LazySymbol.Kind, |
| 271 | 325 | index: u32, |
| ... | ... | @@ -648,15 +702,15 @@ pub const Section = struct { |
| 648 | 702 | si: Symbol.Index, |
| 649 | 703 | relocation_table_ni: MappedFile.Node.Index, |
| 650 | 704 | |
| 651 | | pub const RelocationIndex = enum(u32) { |
| 705 | pub const RelocationIndex = enum(u16) { |
| 652 | 706 | none, |
| 653 | 707 | _, |
| 654 | 708 | |
| 655 | | pub fn wrap(i: ?u32) RelocationIndex { |
| 709 | pub fn wrap(i: ?u16) RelocationIndex { |
| 656 | 710 | return @enumFromInt((i orelse return .none) + 1); |
| 657 | 711 | } |
| 658 | 712 | |
| 659 | | pub fn unwrap(sri: RelocationIndex) ?u32 { |
| 713 | pub fn unwrap(sri: RelocationIndex) ?u16 { |
| 660 | 714 | return switch (sri) { |
| 661 | 715 | .none => null, |
| 662 | 716 | _ => @intFromEnum(sri) - 1, |
| ... | ... | @@ -680,7 +734,12 @@ pub const GlobalName = struct { name: String, lib_name: String.Optional }; |
| 680 | 734 | pub const Symbol = struct { |
| 681 | 735 | ni: MappedFile.Node.Index, |
| 682 | 736 | rva: u32, |
| 683 | | size: u32, |
| 737 | value: union { |
| 738 | /// For generated symbols, this is their size |
| 739 | size: u32, |
| 740 | /// For globals from input sections, this is the offset within the input section |
| 741 | input_offset: u32, |
| 742 | }, |
| 684 | 743 | /// Relocations contained within this symbol |
| 685 | 744 | loc_relocs: Reloc.Index, |
| 686 | 745 | /// Relocations targeting this symbol |
| ... | ... | @@ -704,6 +763,10 @@ pub const Symbol = struct { |
| 704 | 763 | return sn.section(coff).si; |
| 705 | 764 | } |
| 706 | 765 | |
| 766 | pub fn name(sn: SectionNumber, coff: *const Coff) String { |
| 767 | return coff.section_table.keys()[sn.toIndex()]; |
| 768 | } |
| 769 | |
| 707 | 770 | pub fn section(sn: SectionNumber, coff: *const Coff) *Section { |
| 708 | 771 | return &coff.section_table.values()[sn.toIndex()]; |
| 709 | 772 | } |
| ... | ... | @@ -732,6 +795,10 @@ pub const Symbol = struct { |
| 732 | 795 | return ni; |
| 733 | 796 | } |
| 734 | 797 | |
| 798 | pub fn next(si: Symbol.Index) Symbol.Index { |
| 799 | return @enumFromInt(@intFromEnum(si) + 1); |
| 800 | } |
| 801 | |
| 735 | 802 | pub fn knownString(si: Symbol.Index) String.Optional { |
| 736 | 803 | return switch (si) { |
| 737 | 804 | .null, _ => .none, |
| ... | ... | @@ -742,6 +809,10 @@ pub const Symbol = struct { |
| 742 | 809 | pub fn flushMoved(si: Symbol.Index, coff: *Coff) void { |
| 743 | 810 | const sym = si.get(coff); |
| 744 | 811 | sym.rva = coff.computeNodeRva(sym.ni); |
| 812 | if (sym.gmi != .none and coff.getNode(sym.ni) == .input_section) { |
| 813 | // Symbols in input sections share a ni with their section |
| 814 | sym.rva += sym.value.input_offset; |
| 815 | } |
| 745 | 816 | si.applyLocationRelocs(coff); |
| 746 | 817 | si.applyTargetRelocs(coff); |
| 747 | 818 | } |
| ... | ... | @@ -761,13 +832,18 @@ pub const Symbol = struct { |
| 761 | 832 | |
| 762 | 833 | pub fn applyLocationRelocs(si: Symbol.Index, coff: *Coff) void { |
| 763 | 834 | const sym = si.get(coff); |
| 764 | | for (coff.relocs.items[@intFromEnum(sym.loc_relocs)..]) |*reloc| { |
| 765 | | if (reloc.loc != si) break; |
| 766 | | if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore( |
| 767 | | &entry.virtual_address, |
| 768 | | @intCast(coff.computeNodeSectionOffset(sym.ni) + reloc.offset), |
| 769 | | ); |
| 770 | | reloc.apply(coff); |
| 835 | switch (sym.loc_relocs) { |
| 836 | .none => {}, |
| 837 | else => |loc_relocs| { |
| 838 | for (coff.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| { |
| 839 | if (reloc.loc != si) break; |
| 840 | if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore( |
| 841 | &entry.virtual_address, |
| 842 | @intCast(coff.computeSymbolSectionOffset(sym) + reloc.offset), |
| 843 | ); |
| 844 | reloc.apply(coff); |
| 845 | } |
| 846 | }, |
| 771 | 847 | } |
| 772 | 848 | } |
| 773 | 849 | |
| ... | ... | @@ -783,11 +859,16 @@ pub const Symbol = struct { |
| 783 | 859 | |
| 784 | 860 | pub fn deleteLocationRelocs(si: Symbol.Index, coff: *Coff) void { |
| 785 | 861 | const sym = si.get(coff); |
| 786 | | for (coff.relocs.items[@intFromEnum(sym.loc_relocs)..]) |*reloc| { |
| 787 | | if (reloc.loc != si) break; |
| 788 | | reloc.delete(coff); |
| 862 | switch (sym.loc_relocs) { |
| 863 | .none => {}, |
| 864 | else => |loc_relocs| { |
| 865 | for (coff.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| { |
| 866 | if (reloc.loc != si) break; |
| 867 | reloc.delete(coff); |
| 868 | } |
| 869 | sym.loc_relocs = .none; |
| 870 | }, |
| 789 | 871 | } |
| 790 | | sym.loc_relocs = .none; |
| 791 | 872 | } |
| 792 | 873 | }; |
| 793 | 874 | |
| ... | ... | @@ -797,14 +878,20 @@ pub const Symbol = struct { |
| 797 | 878 | }; |
| 798 | 879 | |
| 799 | 880 | pub const Reloc = extern struct { |
| 881 | offset: u64, |
| 882 | addend: i64, |
| 800 | 883 | type: Reloc.Type, |
| 884 | sri: Section.RelocationIndex, |
| 801 | 885 | prev: Reloc.Index, |
| 802 | 886 | next: Reloc.Index, |
| 803 | 887 | loc: Symbol.Index, |
| 804 | 888 | target: Symbol.Index, |
| 805 | | sri: Section.RelocationIndex, |
| 806 | | offset: u64, |
| 807 | | addend: i64, |
| 889 | flags: packed struct(u8) { |
| 890 | // Indicates the addend is not known and should be recovered from the location itself. |
| 891 | // COFF relocation tables don't encode the addend, only the location. |
| 892 | recover_addend: bool, |
| 893 | _: u7 = 0, |
| 894 | }, |
| 808 | 895 | |
| 809 | 896 | pub const Type = extern union { |
| 810 | 897 | AMD64: std.coff.IMAGE.REL.AMD64, |
| ... | ... | @@ -827,7 +914,7 @@ pub const Reloc = extern struct { |
| 827 | 914 | } |
| 828 | 915 | }; |
| 829 | 916 | |
| 830 | | pub fn apply(reloc: *const Reloc, coff: *Coff) void { |
| 917 | pub fn apply(reloc: *Reloc, coff: *Coff) void { |
| 831 | 918 | const loc_sym = reloc.loc.get(coff); |
| 832 | 919 | switch (loc_sym.ni) { |
| 833 | 920 | .none => return, |
| ... | ... | @@ -836,9 +923,11 @@ pub const Reloc = extern struct { |
| 836 | 923 | |
| 837 | 924 | const loc_slice = loc_sym.ni.slice(&coff.mf)[@intCast(reloc.offset)..]; |
| 838 | 925 | const target_endian = coff.targetEndian(); |
| 926 | const target_machine = coff.targetLoad(&coff.headerPtr().machine); |
| 839 | 927 | |
| 840 | 928 | if (!coff.isImage()) { |
| 841 | | switch (coff.targetLoad(&coff.headerPtr().machine)) { |
| 929 | assert(!reloc.flags.recover_addend); |
| 930 | switch (target_machine) { |
| 842 | 931 | else => |machine| @panic(@tagName(machine)), |
| 843 | 932 | .AMD64 => switch (reloc.type.AMD64) { |
| 844 | 933 | else => |kind| @panic(@tagName(kind)), |
| ... | ... | @@ -890,6 +979,54 @@ pub const Reloc = extern struct { |
| 890 | 979 | } |
| 891 | 980 | |
| 892 | 981 | return; |
| 982 | } else if (reloc.flags.recover_addend) { |
| 983 | reloc.flags.recover_addend = false; |
| 984 | reloc.addend = switch (target_machine) { |
| 985 | else => |machine| @panic(@tagName(machine)), |
| 986 | .AMD64 => switch (reloc.type.AMD64) { |
| 987 | else => |kind| @panic(@tagName(kind)), |
| 988 | .ABSOLUTE => 0, |
| 989 | .ADDR64 => @bitCast(std.mem.readInt( |
| 990 | u64, |
| 991 | loc_slice[0..8], |
| 992 | target_endian, |
| 993 | )), |
| 994 | .ADDR32, |
| 995 | .ADDR32NB, |
| 996 | .REL32, |
| 997 | .REL32_1, |
| 998 | .REL32_2, |
| 999 | .REL32_3, |
| 1000 | .REL32_4, |
| 1001 | .REL32_5, |
| 1002 | .SECREL, |
| 1003 | => std.mem.readInt( |
| 1004 | u32, |
| 1005 | loc_slice[0..4], |
| 1006 | target_endian, |
| 1007 | ), |
| 1008 | }, |
| 1009 | .I386 => switch (reloc.type.I386) { |
| 1010 | else => |kind| @panic(@tagName(kind)), |
| 1011 | .ABSOLUTE => 0, |
| 1012 | .DIR16, |
| 1013 | .REL16, |
| 1014 | => std.mem.readInt( |
| 1015 | u16, |
| 1016 | loc_slice[0..2], |
| 1017 | target_endian, |
| 1018 | ), |
| 1019 | .DIR32, |
| 1020 | .DIR32NB, |
| 1021 | .REL32, |
| 1022 | .SECREL, |
| 1023 | => std.mem.readInt( |
| 1024 | u32, |
| 1025 | loc_slice[0..4], |
| 1026 | target_endian, |
| 1027 | ), |
| 1028 | }, |
| 1029 | }; |
| 893 | 1030 | } |
| 894 | 1031 | |
| 895 | 1032 | const target_sym = reloc.target.get(coff); |
| ... | ... | @@ -899,8 +1036,7 @@ pub const Reloc = extern struct { |
| 899 | 1036 | } |
| 900 | 1037 | |
| 901 | 1038 | const target_rva = target_sym.rva +% @as(u64, @bitCast(reloc.addend)); |
| 902 | | |
| 903 | | switch (coff.targetLoad(&coff.headerPtr().machine)) { |
| 1039 | switch (target_machine) { |
| 904 | 1040 | else => |machine| @panic(@tagName(machine)), |
| 905 | 1041 | .AMD64 => switch (reloc.type.AMD64) { |
| 906 | 1042 | else => |kind| @panic(@tagName(kind)), |
| ... | ... | @@ -962,7 +1098,7 @@ pub const Reloc = extern struct { |
| 962 | 1098 | .SECREL => std.mem.writeInt( |
| 963 | 1099 | u32, |
| 964 | 1100 | loc_slice[0..4], |
| 965 | | @intCast(coff.computeNodeSectionOffset(target_sym.ni) + reloc.addend), |
| 1101 | @intCast(coff.computeSymbolSectionOffset(target_sym) + reloc.addend), |
| 966 | 1102 | target_endian, |
| 967 | 1103 | ), |
| 968 | 1104 | }, |
| ... | ... | @@ -1002,7 +1138,7 @@ pub const Reloc = extern struct { |
| 1002 | 1138 | .SECREL => std.mem.writeInt( |
| 1003 | 1139 | u32, |
| 1004 | 1140 | loc_slice[0..4], |
| 1005 | | @intCast(coff.computeNodeSectionOffset(target_sym.ni) + reloc.addend), |
| 1141 | @intCast(coff.computeSymbolSectionOffset(target_sym) + reloc.addend), |
| 1006 | 1142 | target_endian, |
| 1007 | 1143 | ), |
| 1008 | 1144 | }, |
| ... | ... | @@ -1133,6 +1269,9 @@ fn create( |
| 1133 | 1269 | .pending = .empty, |
| 1134 | 1270 | .pending_shrink = false, |
| 1135 | 1271 | }, |
| 1272 | .inputs = .empty, |
| 1273 | .input_sections = .empty, |
| 1274 | .input_section_pending_index = 0, |
| 1136 | 1275 | .strings = .empty, |
| 1137 | 1276 | .string_bytes = .empty, |
| 1138 | 1277 | .section_table = .empty, |
| ... | ... | @@ -1154,6 +1293,7 @@ fn create( |
| 1154 | 1293 | .synth_prog_node = .none, |
| 1155 | 1294 | .symbol_prog_node = .none, |
| 1156 | 1295 | .member_prog_node = .none, |
| 1296 | .input_prog_node = .none, |
| 1157 | 1297 | .dump_snapshot = options.enable_link_snapshots, |
| 1158 | 1298 | }; |
| 1159 | 1299 | errdefer coff.deinit(); |
| ... | ... | @@ -1561,7 +1701,7 @@ fn initHeaders( |
| 1561 | 1701 | coff.symbols.addOneAssumeCapacity().* = .{ |
| 1562 | 1702 | .ni = .none, |
| 1563 | 1703 | .rva = 0, |
| 1564 | | .size = 0, |
| 1704 | .value = .{ .size = 0 }, |
| 1565 | 1705 | .loc_relocs = .none, |
| 1566 | 1706 | .target_relocs = .none, |
| 1567 | 1707 | .section_number = .UNDEFINED, |
| ... | ... | @@ -1701,12 +1841,18 @@ pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void { |
| 1701 | 1841 | coff.symbol_prog_node = prog_node.start("Symbols", coff.symbol_table.pending.count()); |
| 1702 | 1842 | coff.member_prog_node = prog_node.start("Members", coff.pending_members.count()); |
| 1703 | 1843 | } |
| 1844 | coff.input_prog_node = prog_node.start( |
| 1845 | "Inputs", |
| 1846 | coff.input_sections.items.len - coff.input_section_pending_index, |
| 1847 | ); |
| 1704 | 1848 | coff.mf.update_prog_node = prog_node.start("Relocations", coff.mf.updates.items.len); |
| 1705 | 1849 | } |
| 1706 | 1850 | |
| 1707 | 1851 | pub fn endProgress(coff: *Coff) void { |
| 1708 | 1852 | coff.mf.update_prog_node.end(); |
| 1709 | 1853 | coff.mf.update_prog_node = .none; |
| 1854 | coff.input_prog_node.end(); |
| 1855 | coff.input_prog_node = .none; |
| 1710 | 1856 | if (!isImage(coff)) { |
| 1711 | 1857 | coff.member_prog_node.end(); |
| 1712 | 1858 | coff.member_prog_node = .none; |
| ... | ... | @@ -1736,11 +1882,11 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1736 | 1882 | .section_table, |
| 1737 | 1883 | .export_name_table, |
| 1738 | 1884 | .placeholder, |
| 1739 | | |
| 1740 | 1885 | .symbol_table, |
| 1741 | 1886 | .string_table, |
| 1742 | 1887 | .relocation_table, |
| 1743 | 1888 | .relocation_table_entry, |
| 1889 | .input_section, |
| 1744 | 1890 | => unreachable, |
| 1745 | 1891 | .image_section => |si| si, |
| 1746 | 1892 | .import_directory_table => break :parent_rva coff.targetLoad( |
| ... | ... | @@ -1781,9 +1927,12 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1781 | 1927 | const offset, _ = ni.location(&coff.mf).resolve(&coff.mf); |
| 1782 | 1928 | return @intCast(parent_rva + offset); |
| 1783 | 1929 | } |
| 1784 | | fn computeNodeSectionOffset(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1785 | | var section_offset: u32 = 0; |
| 1786 | | var parent_ni = ni; |
| 1930 | fn computeSymbolSectionOffset(coff: *Coff, sym: *const Symbol) u32 { |
| 1931 | var section_offset: u32 = if (sym.gmi != .none and coff.getNode(sym.ni) == .input_section) |
| 1932 | sym.value.input_offset |
| 1933 | else |
| 1934 | 0; |
| 1935 | var parent_ni = sym.ni; |
| 1787 | 1936 | while (true) { |
| 1788 | 1937 | const offset, _ = parent_ni.location(&coff.mf).resolve(&coff.mf); |
| 1789 | 1938 | section_offset += @intCast(offset); |
| ... | ... | @@ -1981,7 +2130,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 1981 | 2130 | defer coff.symbols.addOneAssumeCapacity().* = .{ |
| 1982 | 2131 | .ni = .none, |
| 1983 | 2132 | .rva = 0, |
| 1984 | | .size = 0, |
| 2133 | .value = .{ .size = 0 }, |
| 1985 | 2134 | .loc_relocs = .none, |
| 1986 | 2135 | .target_relocs = .none, |
| 1987 | 2136 | .section_number = .UNDEFINED, |
| ... | ... | @@ -2003,6 +2152,15 @@ fn getOrPutString(coff: *Coff, string: []const u8) !String { |
| 2003 | 2152 | fn getOrPutOptionalString(coff: *Coff, string: ?[]const u8) !String.Optional { |
| 2004 | 2153 | return (try coff.getOrPutString(string orelse return .none)).toOptional(); |
| 2005 | 2154 | } |
| 2155 | fn getString(coff: *Coff, string: []const u8) ?String { |
| 2156 | if (coff.strings.getKeyAdapted( |
| 2157 | string, |
| 2158 | std.hash_map.StringIndexAdapter{ .bytes = &coff.string_bytes }, |
| 2159 | )) |key| |
| 2160 | return @enumFromInt(key) |
| 2161 | else |
| 2162 | return null; |
| 2163 | } |
| 2006 | 2164 | |
| 2007 | 2165 | /// If the name does not fit in the symbol header, adds it to the symbol table string table. |
| 2008 | 2166 | /// If the caller knows this name already has a String associated with it, they can avoid |
| ... | ... | @@ -2105,7 +2263,7 @@ fn navSection( |
| 2105 | 2263 | const ip = &zcu.intern_pool; |
| 2106 | 2264 | const default: String, const attributes: ObjectSectionAttributes = |
| 2107 | 2265 | if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{ |
| 2108 | | .@".tls$", .{ .read = true, .write = !coff.isImage() }, |
| 2266 | .@".tls$", .{ .read = true, .write = true }, |
| 2109 | 2267 | } else if (ip.isFunctionType(nav_resolved.type)) .{ |
| 2110 | 2268 | .@".text", .{ .read = true, .execute = true }, |
| 2111 | 2269 | } else if (nav_resolved.@"const") .{ |
| ... | ... | @@ -2189,7 +2347,7 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol. |
| 2189 | 2347 | @enumFromInt(@intFromEnum(reloc_info.parent.atom_index)), |
| 2190 | 2348 | reloc_info.offset, |
| 2191 | 2349 | target_si, |
| 2192 | | reloc_info.addend, |
| 2350 | .{ .known = reloc_info.addend }, |
| 2193 | 2351 | switch (coff.targetLoad(&coff.headerPtr().machine)) { |
| 2194 | 2352 | else => unreachable, |
| 2195 | 2353 | .AMD64 => .{ .AMD64 = .ADDR64 }, |
| ... | ... | @@ -2467,19 +2625,40 @@ fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void |
| 2467 | 2625 | }; |
| 2468 | 2626 | |
| 2469 | 2627 | coff.targetStore(&entry.value, switch (sym.section_number) { |
| 2470 | | .UNDEFINED => sym.size, |
| 2628 | .UNDEFINED => sym.value.size, |
| 2471 | 2629 | .ABSOLUTE, |
| 2472 | 2630 | .DEBUG, |
| 2473 | 2631 | => unreachable, |
| 2474 | 2632 | else => switch (coff.getNode(sym.ni)) { |
| 2475 | 2633 | .image_section => 0, |
| 2476 | | else => coff.computeNodeSectionOffset(sym.ni), |
| 2634 | else => coff.computeSymbolSectionOffset(sym), |
| 2477 | 2635 | }, |
| 2478 | 2636 | }); |
| 2479 | 2637 | |
| 2480 | 2638 | log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti }); |
| 2481 | 2639 | } |
| 2482 | 2640 | |
| 2641 | fn flushInputSection(coff: *Coff, isi: Node.InputSectionIndex) !void { |
| 2642 | const file_loc = isi.fileLocation(coff); |
| 2643 | if (file_loc.size == 0) return; |
| 2644 | const comp = coff.base.comp; |
| 2645 | const io = comp.io; |
| 2646 | const gpa = comp.gpa; |
| 2647 | const ii = isi.input(coff); |
| 2648 | const path = ii.path(coff); |
| 2649 | const file = try path.root_dir.handle.openFile(io, path.sub_path, .{}); |
| 2650 | defer file.close(io); |
| 2651 | var fr = file.reader(io, &.{}); |
| 2652 | try fr.seekTo(file_loc.offset); |
| 2653 | var nw: MappedFile.Node.Writer = undefined; |
| 2654 | const si = isi.symbol(coff); |
| 2655 | si.node(coff).writer(&coff.mf, gpa, &nw); |
| 2656 | defer nw.deinit(); |
| 2657 | if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size) |
| 2658 | return error.EndOfStream; |
| 2659 | si.applyLocationRelocs(coff); |
| 2660 | } |
| 2661 | |
| 2483 | 2662 | fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !Symbol.Index { |
| 2484 | 2663 | assert(coff.base.comp.zcu != null); |
| 2485 | 2664 | |
| ... | ... | @@ -2612,7 +2791,7 @@ fn pseudoSectionMapIndex( |
| 2612 | 2791 | const gpa = coff.base.comp.gpa; |
| 2613 | 2792 | const pseudo_section_gop = try coff.pseudo_section_table.getOrPut(gpa, name); |
| 2614 | 2793 | const psmi: Node.PseudoSectionMapIndex = @enumFromInt(pseudo_section_gop.index); |
| 2615 | | if (!pseudo_section_gop.found_existing) { |
| 2794 | const sn = if (!pseudo_section_gop.found_existing) sn: { |
| 2616 | 2795 | const default_parent: Symbol.Index = if (attributes.execute) |
| 2617 | 2796 | .text |
| 2618 | 2797 | else if (attributes.write) |
| ... | ... | @@ -2626,11 +2805,10 @@ fn pseudoSectionMapIndex( |
| 2626 | 2805 | default_parent.knownString().toSlice(coff).?, |
| 2627 | 2806 | )) |
| 2628 | 2807 | default_parent |
| 2629 | | else if (coff.section_table.get(name)) |section| parent: { |
| 2630 | | const header = section.si.get(coff).section_number.header(coff); |
| 2631 | | try coff.verifyParentSectionAttributes(name, name, .fromFlags(header.flags), attributes); |
| 2632 | | break :parent section.si; |
| 2633 | | } else try coff.addSection(name, attributes.asFlags()); |
| 2808 | else if (coff.section_table.get(name)) |section| |
| 2809 | section.si |
| 2810 | else |
| 2811 | try coff.addSection(name, attributes.asFlags()); |
| 2634 | 2812 | |
| 2635 | 2813 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2636 | 2814 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -2644,9 +2822,30 @@ fn pseudoSectionMapIndex( |
| 2644 | 2822 | assert(sym.loc_relocs == .none); |
| 2645 | 2823 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 2646 | 2824 | coff.nodes.appendAssumeCapacity(.{ .pseudo_section = psmi }); |
| 2647 | | } |
| 2825 | break :sn sym.section_number; |
| 2826 | } else pseudo_section_gop.value_ptr.get(coff).section_number; |
| 2827 | |
| 2828 | try coff.verifyParentSectionAttributes( |
| 2829 | .pseudo, |
| 2830 | sn.name(coff), |
| 2831 | name, |
| 2832 | .fromFlags(sn.header(coff).flags), |
| 2833 | attributes, |
| 2834 | ); |
| 2835 | |
| 2648 | 2836 | return psmi; |
| 2649 | 2837 | } |
| 2838 | |
| 2839 | fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 { |
| 2840 | // In images we want to sort object sections into the final root section name. |
| 2841 | // Otherwise, we want to keep the full name so that this sort can occur correctly when |
| 2842 | // the object is finally linked into an image. |
| 2843 | return if (coff.isImage()) |
| 2844 | name[0 .. std.mem.indexOfScalar(u8, name, '$') orelse name.len] |
| 2845 | else |
| 2846 | name; |
| 2847 | } |
| 2848 | |
| 2650 | 2849 | fn objectSectionMapIndex( |
| 2651 | 2850 | coff: *Coff, |
| 2652 | 2851 | name: String, |
| ... | ... | @@ -2654,23 +2853,20 @@ fn objectSectionMapIndex( |
| 2654 | 2853 | attributes: ObjectSectionAttributes, |
| 2655 | 2854 | ) !Node.ObjectSectionMapIndex { |
| 2656 | 2855 | const gpa = coff.base.comp.gpa; |
| 2856 | const effective_attributes = if (coff.isImage() and std.mem.startsWith(u8, name.toSlice(coff), ".tls")) attr: { |
| 2857 | // In images, the .tls section is a read-only template |
| 2858 | var attr = attributes; |
| 2859 | attr.write = false; |
| 2860 | break :attr attr; |
| 2861 | } else attributes; |
| 2862 | |
| 2657 | 2863 | const object_section_gop = try coff.object_section_table.getOrPut(gpa, name); |
| 2658 | 2864 | const osmi: Node.ObjectSectionMapIndex = @enumFromInt(object_section_gop.index); |
| 2659 | | if (!object_section_gop.found_existing) { |
| 2865 | const sn = if (!object_section_gop.found_existing) sn: { |
| 2660 | 2866 | try coff.ensureUnusedStringCapacity(name.toSlice(coff).len); |
| 2661 | 2867 | const name_slice = name.toSlice(coff); |
| 2662 | | const prefix_index = std.mem.indexOfScalar(u8, name_slice, '$') orelse name_slice.len; |
| 2663 | | const parent_name = coff.getOrPutStringAssumeCapacity(if (coff.isImage()) |
| 2664 | | name_slice[0..prefix_index] |
| 2665 | | else |
| 2666 | | name_slice[0..@min(prefix_index + 1, name_slice.len)]); |
| 2667 | | const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, attributes)).symbol(coff); |
| 2668 | | try coff.verifyParentSectionAttributes( |
| 2669 | | parent_name, |
| 2670 | | name, |
| 2671 | | .fromFlags(parent.get(coff).section_number.header(coff).flags), |
| 2672 | | attributes, |
| 2673 | | ); |
| 2868 | const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice)); |
| 2869 | const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, effective_attributes)).symbol(coff); |
| 2674 | 2870 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2675 | 2871 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 2676 | 2872 | const parent_ni = parent.node(coff); |
| ... | ... | @@ -2704,12 +2900,23 @@ fn objectSectionMapIndex( |
| 2704 | 2900 | assert(sym.loc_relocs == .none); |
| 2705 | 2901 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 2706 | 2902 | coff.nodes.appendAssumeCapacity(.{ .object_section = osmi }); |
| 2707 | | } |
| 2903 | break :sn sym.section_number; |
| 2904 | } else object_section_gop.value_ptr.get(coff).section_number; |
| 2905 | |
| 2906 | try coff.verifyParentSectionAttributes( |
| 2907 | .object, |
| 2908 | sn.name(coff), |
| 2909 | name, |
| 2910 | .fromFlags(sn.header(coff).flags), |
| 2911 | effective_attributes, |
| 2912 | ); |
| 2913 | |
| 2708 | 2914 | return osmi; |
| 2709 | 2915 | } |
| 2710 | 2916 | |
| 2711 | 2917 | fn verifyParentSectionAttributes( |
| 2712 | 2918 | coff: *Coff, |
| 2919 | kind: enum { pseudo, object }, |
| 2713 | 2920 | parent_name: String, |
| 2714 | 2921 | child_name: String, |
| 2715 | 2922 | parent_attrs: ObjectSectionAttributes, |
| ... | ... | @@ -2718,18 +2925,25 @@ fn verifyParentSectionAttributes( |
| 2718 | 2925 | if (parent_attrs == child_attrs) return; |
| 2719 | 2926 | |
| 2720 | 2927 | const fields = std.meta.fields(ObjectSectionAttributes); |
| 2721 | | var err = try coff.base.comp.link_diags.addErrorWithNotes(fields.len); |
| 2722 | | try err.addMsg("object '{s}' was placed in parent section '{s}' with mismatched flags", .{ |
| 2928 | const BackingT = @typeInfo(ObjectSectionAttributes).@"struct".backing_integer.?; |
| 2929 | const num_notes = @popCount(@as(BackingT, @bitCast(parent_attrs)) ^ @as(BackingT, @bitCast(child_attrs))); |
| 2930 | var err = try coff.base.comp.link_diags.addErrorWithNotes(num_notes); |
| 2931 | try err.addMsg("{t} section '{s}' was placed in parent section '{s}' with mismatched flags", .{ |
| 2932 | kind, |
| 2723 | 2933 | child_name.toSlice(coff), |
| 2724 | 2934 | parent_name.toSlice(coff), |
| 2725 | 2935 | }); |
| 2726 | 2936 | |
| 2727 | 2937 | inline for (fields) |field| { |
| 2728 | | err.addNote("{s}: parent = {d} child = {d}", .{ |
| 2729 | | field.name, |
| 2730 | | @intFromBool(@field(child_attrs, field.name)), |
| 2731 | | @intFromBool(@field(parent_attrs, field.name)), |
| 2732 | | }); |
| 2938 | if (@field(child_attrs, field.name) != @field(parent_attrs, field.name)) { |
| 2939 | err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{ |
| 2940 | field.name, |
| 2941 | @intFromBool(@field(child_attrs, field.name)), |
| 2942 | child_name.toSlice(coff), |
| 2943 | @intFromBool(@field(parent_attrs, field.name)), |
| 2944 | parent_name.toSlice(coff), |
| 2945 | }); |
| 2946 | } |
| 2733 | 2947 | } |
| 2734 | 2948 | |
| 2735 | 2949 | return error.LinkFailure; |
| ... | ... | @@ -2740,13 +2954,24 @@ pub fn addReloc( |
| 2740 | 2954 | loc_si: Symbol.Index, |
| 2741 | 2955 | offset: u64, |
| 2742 | 2956 | target_si: Symbol.Index, |
| 2743 | | addend: i64, |
| 2957 | addend: union(enum) { |
| 2958 | known: i64, |
| 2959 | pending: void, |
| 2960 | }, |
| 2744 | 2961 | @"type": Reloc.Type, |
| 2745 | 2962 | ) !void { |
| 2746 | 2963 | const gpa = coff.base.comp.gpa; |
| 2747 | 2964 | const target = target_si.get(coff); |
| 2748 | 2965 | |
| 2749 | | log.debug("addReloc({d}@{d}+{d} -> {d}@{d}+{d})", .{ loc_si, loc_si.get(coff).section_number, offset, target_si, target_si.get(coff).section_number, addend }); |
| 2966 | log.debug("addReloc({d}@{d}+{d} -> {d}@{d}+{d}{s})", .{ |
| 2967 | loc_si, |
| 2968 | loc_si.get(coff).section_number, |
| 2969 | offset, |
| 2970 | target_si, |
| 2971 | target_si.get(coff).section_number, |
| 2972 | if (addend == .pending) 0 else addend.known, |
| 2973 | if (addend == .pending) "p" else "k", |
| 2974 | }); |
| 2750 | 2975 | |
| 2751 | 2976 | try coff.relocs.ensureUnusedCapacity(gpa, 1); |
| 2752 | 2977 | |
| ... | ... | @@ -2817,7 +3042,10 @@ pub fn addReloc( |
| 2817 | 3042 | .target = target_si, |
| 2818 | 3043 | .sri = sri, |
| 2819 | 3044 | .offset = offset, |
| 2820 | | .addend = addend, |
| 3045 | .addend = if (addend == .pending) 0 else addend.known, |
| 3046 | .flags = .{ |
| 3047 | .recover_addend = addend == .pending, |
| 3048 | }, |
| 2821 | 3049 | }; |
| 2822 | 3050 | switch (target.target_relocs) { |
| 2823 | 3051 | .none => {}, |
| ... | ... | @@ -2869,10 +3097,34 @@ pub fn loadInput(coff: *Coff, input: link.Input) (Io.File.Reader.SizeError || |
| 2869 | 3097 | fn fmtArchiveNameString(archiveName: ?[]const u8) std.fmt.Alt(?[]const u8, archiveNameStringEscape) { |
| 2870 | 3098 | return .{ .data = archiveName }; |
| 2871 | 3099 | } |
| 3100 | |
| 2872 | 3101 | fn archiveNameStringEscape(archiveName: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void { |
| 2873 | 3102 | try w.print("({f})", .{std.zig.fmtString(archiveName orelse return)}); |
| 2874 | 3103 | } |
| 2875 | 3104 | |
| 3105 | fn inputSectionHeaderNameSlice( |
| 3106 | coff: *Coff, |
| 3107 | header: *const std.coff.SectionHeader, |
| 3108 | string_table: []const u8, |
| 3109 | path: std.Build.Cache.Path, |
| 3110 | section_i: usize, |
| 3111 | ) ![]const u8 { |
| 3112 | const diags = &coff.base.comp.link_diags; |
| 3113 | return if (header.name[0] == '/') name: { |
| 3114 | const offset_str = std.mem.sliceTo(header.name[1..], 0); |
| 3115 | const name_offset = std.fmt.parseUnsigned(u24, offset_str, 10) catch |
| 3116 | return diags.failParse(path, "ill-formed section name in section {d}: '{s}'", .{ |
| 3117 | section_i, |
| 3118 | header.name[0 .. offset_str.len + 1], |
| 3119 | }); |
| 3120 | |
| 3121 | if (name_offset > string_table.len) |
| 3122 | return diags.failParse(path, "out-of-bounds section name offset in section {d}: {d}", .{ section_i, name_offset }); |
| 3123 | |
| 3124 | break :name std.mem.sliceTo(string_table[name_offset..], 0); |
| 3125 | } else std.mem.sliceTo(&header.name, 0); |
| 3126 | } |
| 3127 | |
| 2876 | 3128 | fn loadObject( |
| 2877 | 3129 | coff: *Coff, |
| 2878 | 3130 | path: std.Build.Cache.Path, |
| ... | ... | @@ -2890,6 +3142,7 @@ fn loadObject( |
| 2890 | 3142 | assert(!coff.isObj()); |
| 2891 | 3143 | |
| 2892 | 3144 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtArchiveNameString(archive_name) }); |
| 3145 | |
| 2893 | 3146 | const header = try r.peekStruct(std.coff.Header, coff.targetEndian()); |
| 2894 | 3147 | if (header.machine != target.toCoffMachine()) |
| 2895 | 3148 | return diags.failParse(path, "machine mismatch: expected {t}, found {t}", .{ |
| ... | ... | @@ -2927,6 +3180,16 @@ fn loadObject( |
| 2927 | 3180 | symbol_table_end + string_table_len > fl.size) |
| 2928 | 3181 | return diags.failParse(path, "bad string table", .{}); |
| 2929 | 3182 | |
| 3183 | const ii: Node.InputIndex = @enumFromInt(coff.inputs.items.len); |
| 3184 | try coff.inputs.ensureUnusedCapacity(gpa, 1); |
| 3185 | const input = coff.inputs.addOneAssumeCapacity(); |
| 3186 | input.* = .{ |
| 3187 | .path = path, |
| 3188 | .archive_name = if (archive_name) |m| try gpa.dupe(u8, m) else null, |
| 3189 | .first_si = .null, |
| 3190 | .last_si = .null, |
| 3191 | }; |
| 3192 | |
| 2930 | 3193 | const string_table = string_table: { |
| 2931 | 3194 | const string_table = try gpa.alloc(u8, string_table_len); |
| 2932 | 3195 | errdefer gpa.free(string_table); |
| ... | ... | @@ -2942,38 +3205,34 @@ fn loadObject( |
| 2942 | 3205 | |
| 2943 | 3206 | const InputSection = struct { |
| 2944 | 3207 | header: std.coff.SectionHeader, |
| 2945 | | psmi: Node.PseudoSectionMapIndex, |
| 3208 | name: String, |
| 3209 | si: Symbol.Index, |
| 2946 | 3210 | }; |
| 2947 | 3211 | |
| 2948 | | try fr.seekTo(fl.offset + @sizeOf(std.coff.Header)); |
| 2949 | 3212 | const sections: []const InputSection = if (coff.isImage()) sections: { |
| 2950 | 3213 | const sections = try gpa.alloc(InputSection, header.number_of_sections); |
| 2951 | 3214 | errdefer gpa.free(sections); |
| 2952 | 3215 | |
| 2953 | | for (sections, 0..) |*section, section_i| { |
| 2954 | | section.header = try r.takeStruct(std.coff.SectionHeader, target_endian); |
| 2955 | | if (section.header.flags.LNK_INFO) { |
| 2956 | | if (std.mem.eql(u8, &section.header.name, ".drectve")) |
| 2957 | | return diags.failParse(path, "TODO handle arguments in .drectve section", .{}); |
| 3216 | var num_input_sections: u16 = 0; |
| 3217 | var reqd_object_sections: std.AutoArrayHashMapUnmanaged(String, void) = .empty; |
| 3218 | defer reqd_object_sections.deinit(gpa); |
| 3219 | var reqd_pseudo_sections: std.StringArrayHashMapUnmanaged(void) = .empty; |
| 3220 | defer reqd_pseudo_sections.deinit(gpa); |
| 3221 | try reqd_object_sections.ensureUnusedCapacity(gpa, sections.len); |
| 3222 | try reqd_pseudo_sections.ensureUnusedCapacity(gpa, sections.len); |
| 2958 | 3223 | |
| 2959 | | continue; |
| 2960 | | } |
| 2961 | | |
| 2962 | | if (section.header.flags.LNK_REMOVE or |
| 2963 | | section.header.flags.MEM_DISCARDABLE) |
| 2964 | | { |
| 2965 | | // TODO: Merge .debug$* sections and output to PDB |
| 2966 | | continue; |
| 2967 | | } |
| 2968 | | |
| 2969 | | if (section.header.flags.LNK_COMDAT) |
| 2970 | | // This will be necessary if we do the equivalent of /Gy for compiler-rt |
| 2971 | | return diags.failParse(path, "TODO handle COMDAT sections in input objects", .{}); |
| 3224 | try fr.seekTo(fl.offset + @sizeOf(std.coff.Header)); |
| 3225 | for (sections, 0..) |*section, section_i| { |
| 3226 | section.* = .{ |
| 3227 | .header = try r.takeStruct(std.coff.SectionHeader, target_endian), |
| 3228 | .name = undefined, |
| 3229 | .si = .null, |
| 3230 | }; |
| 2972 | 3231 | |
| 2973 | 3232 | const section_name_slice = if (section.header.name[0] == '/') name: { |
| 2974 | 3233 | const offset_str = std.mem.sliceTo(section.header.name[1..], 0); |
| 2975 | 3234 | const name_offset = std.fmt.parseUnsigned(u24, offset_str, 10) catch |
| 2976 | | return diags.failParse(path, "ill-formed section name in section {d}: '{s}'", .{ |
| 3235 | return diags.failParse(path, "ill-formed section name offset in section {d}: '{s}'", .{ |
| 2977 | 3236 | section_i, |
| 2978 | 3237 | section.header.name[0 .. offset_str.len + 1], |
| 2979 | 3238 | }); |
| ... | ... | @@ -2983,26 +3242,137 @@ fn loadObject( |
| 2983 | 3242 | |
| 2984 | 3243 | break :name std.mem.sliceTo(string_table[name_offset..], 0); |
| 2985 | 3244 | } else std.mem.sliceTo(&section.header.name, 0); |
| 3245 | section.name = coff.getOrPutStringAssumeCapacity(section_name_slice); |
| 2986 | 3246 | |
| 2987 | | const section_name = coff.getOrPutStringAssumeCapacity(section_name_slice); |
| 2988 | | const osmi = try coff.objectSectionMapIndex( |
| 2989 | | section_name, |
| 2990 | | if (section.header.flags.ALIGN.toByteUnits()) |align_bytes| |
| 2991 | | .fromByteUnits(align_bytes) |
| 2992 | | else |
| 2993 | | .@"1", |
| 2994 | | .fromFlags(section.header.flags), |
| 3247 | if (section.header.pointer_to_linenumbers + |
| 3248 | section.header.number_of_linenumbers * std.coff.LineNumber.sizeOf() > fl.size) |
| 3249 | return diags.failParse(path, "bad line numbers location in section {d} `{s}`", .{ |
| 3250 | section_i, |
| 3251 | section_name_slice, |
| 3252 | }); |
| 3253 | |
| 3254 | if (section.header.pointer_to_relocations + |
| 3255 | section.header.number_of_relocations * std.coff.Relocation.sizeOf() > fl.size) |
| 3256 | return diags.failParse(path, "bad relocations location in section {d} `{s}`", .{ |
| 3257 | section_i, |
| 3258 | section_name_slice, |
| 3259 | }); |
| 3260 | |
| 3261 | if (section.header.pointer_to_raw_data + section.header.size_of_raw_data > fl.size) |
| 3262 | return diags.failParse(path, "bad raw data location in section {d} `{s}`", .{ |
| 3263 | section_i, |
| 3264 | section_name_slice, |
| 3265 | }); |
| 3266 | |
| 3267 | if (section.header.flags.LNK_REMOVE or |
| 3268 | section.header.flags.MEM_DISCARDABLE) |
| 3269 | { |
| 3270 | // TODO: Merge .debug$* sections and output to PDB |
| 3271 | continue; |
| 3272 | } |
| 3273 | |
| 3274 | num_input_sections += 1; |
| 3275 | _ = reqd_object_sections.getOrPutAssumeCapacity(section.name); |
| 3276 | _ = reqd_pseudo_sections.getOrPutAssumeCapacity( |
| 3277 | coff.objectSectionParentName(section.name.toSlice(coff)), |
| 2995 | 3278 | ); |
| 3279 | } |
| 3280 | |
| 3281 | var symbol_capacity: u16 = num_input_sections; |
| 3282 | var node_capacity: u16 = 0; |
| 3283 | { |
| 3284 | var iter = reqd_object_sections.count(); |
| 3285 | while (iter > 0) { |
| 3286 | iter -= 1; |
| 3287 | if (coff.object_section_table.contains(reqd_object_sections.keys()[iter])) |
| 3288 | reqd_object_sections.swapRemoveAt(iter); |
| 3289 | } |
| 2996 | 3290 | |
| 2997 | | _ = osmi; |
| 3291 | node_capacity += @intCast(reqd_object_sections.count()); |
| 3292 | symbol_capacity += @intCast(reqd_object_sections.count()); |
| 3293 | } |
| 3294 | |
| 3295 | { |
| 3296 | var iter = reqd_pseudo_sections.count(); |
| 3297 | while (iter > 0) { |
| 3298 | // TODO: Track the extra number of strings and their length and reserve? These have not been reserved as |
| 3299 | // part of the ensureManyUnusedStringCapacity call above |
| 3300 | iter -= 1; |
| 3301 | const name = coff.getString(reqd_pseudo_sections.keys()[iter]) orelse continue; |
| 3302 | if (coff.pseudo_section_table.contains(name)) |
| 3303 | reqd_pseudo_sections.swapRemoveAt(iter); |
| 3304 | } |
| 3305 | |
| 3306 | node_capacity += @intCast(reqd_pseudo_sections.count()); |
| 3307 | symbol_capacity += @intCast(reqd_pseudo_sections.count()); |
| 3308 | } |
| 3309 | |
| 3310 | try coff.nodes.ensureUnusedCapacity(gpa, node_capacity); |
| 3311 | try coff.symbols.ensureUnusedCapacity(gpa, symbol_capacity + num_input_sections); |
| 3312 | try coff.input_sections.ensureUnusedCapacity(gpa, num_input_sections); |
| 3313 | |
| 3314 | for (sections) |*section| { |
| 3315 | if (section.header.flags.LNK_INFO) { |
| 3316 | if (std.mem.eql(u8, &section.header.name, ".drectve")) { |
| 3317 | try fr.seekTo(fl.offset + section.header.pointer_to_raw_data); |
| 3318 | var buf: [128]u8 = undefined; |
| 3319 | var section_r = r.limited(.limited(section.header.size_of_raw_data), &buf); |
| 3320 | while (section_r.interface.takeDelimiter(' ') catch |err| switch (err) { |
| 3321 | error.StreamTooLong => return diags.failParse(path, "unexpectedly long .drectve argument", .{}), |
| 3322 | else => |e| return e, |
| 3323 | }) |arg| { |
| 3324 | // Microsoft tools emit 3 space characters into this section even with /Zl |
| 3325 | if (arg.len > 0) |
| 3326 | return diags.failParse(path, "unsupported argument in .drectve section: `{s}`", .{arg}); |
| 3327 | } |
| 3328 | } |
| 3329 | |
| 3330 | continue; |
| 3331 | } |
| 2998 | 3332 | |
| 2999 | | // TODO: Decide to merge this section |
| 3000 | | // TODO: Map flags (might need to figure out a better tls flag?) |
| 3333 | if (section.header.flags.LNK_REMOVE or |
| 3334 | section.header.flags.MEM_DISCARDABLE) |
| 3335 | { |
| 3336 | continue; |
| 3337 | } |
| 3001 | 3338 | |
| 3002 | | //coff.objectSectionMapIndex(name: String, alignment: Alignment, attributes: ObjectSectionAttributes) |
| 3339 | if (section.header.flags.LNK_COMDAT) |
| 3340 | // This will be necessary if we do the equivalent of /Gy for compiler-rt |
| 3341 | return diags.failParse(path, "TODO handle COMDAT sections in input objects", .{}); |
| 3003 | 3342 | |
| 3004 | | // TODO: Load relocations, update for new offset? Or can just work with the object section parent? |
| 3343 | log.debug("loadInputSection({s})", .{section.name.toSlice(coff)}); |
| 3005 | 3344 | |
| 3345 | const parent_osmi = try coff.objectSectionMapIndex( |
| 3346 | section.name, |
| 3347 | coff.mf.flags.block_size, |
| 3348 | .fromFlags(section.header.flags), |
| 3349 | ); |
| 3350 | const parent_si = parent_osmi.symbol(coff); |
| 3351 | const ni = try coff.mf.addLastChildNode(gpa, parent_si.node(coff), .{ |
| 3352 | .size = section.header.size_of_raw_data, |
| 3353 | .alignment = if (section.header.flags.ALIGN.toByteUnits()) |align_bytes| |
| 3354 | .fromByteUnits(align_bytes) |
| 3355 | else |
| 3356 | .@"1", |
| 3357 | .moved = true, |
| 3358 | }); |
| 3359 | coff.nodes.appendAssumeCapacity(.{ .input_section = @enumFromInt(coff.input_sections.items.len) }); |
| 3360 | |
| 3361 | section.si = coff.addSymbolAssumeCapacity(); |
| 3362 | const sym = section.si.get(coff); |
| 3363 | sym.ni = ni; |
| 3364 | sym.section_number = parent_si.get(coff).section_number; |
| 3365 | |
| 3366 | coff.input_sections.addOneAssumeCapacity().* = .{ |
| 3367 | .ii = ii, |
| 3368 | .si = section.si, |
| 3369 | .file_location = .{ |
| 3370 | .offset = fl.offset + section.header.pointer_to_raw_data, |
| 3371 | .size = section.header.size_of_raw_data, |
| 3372 | }, |
| 3373 | }; |
| 3374 | |
| 3375 | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| 3006 | 3376 | } |
| 3007 | 3377 | |
| 3008 | 3378 | break :sections sections; |
| ... | ... | @@ -3019,38 +3389,42 @@ fn loadObject( |
| 3019 | 3389 | const member = mi.get(coff); |
| 3020 | 3390 | try member.initHeader(coff, path_str, header.time_date_stamp); |
| 3021 | 3391 | |
| 3392 | // TODO: This could be deferred to an idle task? |
| 3393 | |
| 3022 | 3394 | { |
| 3023 | 3395 | var nw: MappedFile.Node.Writer = undefined; |
| 3024 | 3396 | member.content_ni.writer(&coff.mf, gpa, &nw); |
| 3025 | 3397 | defer nw.deinit(); |
| 3026 | 3398 | |
| 3027 | 3399 | try fr.seekTo(fl.offset); |
| 3028 | | try r.streamExact(&nw.interface, fl.size); |
| 3400 | if (try nw.interface.sendFileAll(fr, .limited64(fl.size)) != fl.size) |
| 3401 | return error.EndOfStream; |
| 3029 | 3402 | } |
| 3030 | 3403 | |
| 3031 | 3404 | break :mi mi; |
| 3032 | 3405 | } else undefined; |
| 3033 | 3406 | |
| 3407 | // TODO: Also reserve memory for the symbols / globals / relocs within each section |
| 3408 | |
| 3034 | 3409 | try fr.seekTo(fl.offset + header.pointer_to_symbol_table); |
| 3035 | | const symbol_size = std.coff.Symbol.sizeOf(); |
| 3410 | const symbol_size = comptime std.coff.Symbol.sizeOf(); |
| 3036 | 3411 | |
| 3412 | var symbols: std.ArrayList(Symbol.Index) = .empty; |
| 3413 | try symbols.ensureUnusedCapacity(gpa, header.number_of_symbols); |
| 3414 | |
| 3415 | const first_si = coff.symbols.items.len; |
| 3037 | 3416 | var symbol_ix: u32 = 0; |
| 3038 | 3417 | while (symbol_ix < header.number_of_symbols) { |
| 3039 | | const symbol: *align(2) std.coff.Symbol = @ptrCast(@alignCast(try r.take(symbol_size))); |
| 3418 | var symbol: std.coff.Symbol = undefined; |
| 3419 | @memcpy(std.mem.asBytes(&symbol)[0..symbol_size], try r.take(symbol_size)); |
| 3420 | if (target_endian != native_endian) |
| 3421 | std.mem.byteSwapAllFields(std.coff.Symbol, &symbol); |
| 3422 | |
| 3040 | 3423 | defer { |
| 3041 | 3424 | r.toss(symbol.number_of_aux_symbols * symbol_size); |
| 3042 | 3425 | symbol_ix += symbol.number_of_aux_symbols + 1; |
| 3043 | 3426 | } |
| 3044 | 3427 | |
| 3045 | | switch (symbol.section_number) { |
| 3046 | | .UNDEFINED, .ABSOLUTE, .DEBUG => continue, |
| 3047 | | else => switch (symbol.storage_class) { |
| 3048 | | .STATIC => if (symbol.value == 0) continue, |
| 3049 | | .EXTERNAL => {}, |
| 3050 | | else => continue, |
| 3051 | | }, |
| 3052 | | } |
| 3053 | | |
| 3054 | 3428 | const name = std.mem.sliceTo(if (std.mem.eql(u8, symbol.name[0..4], "\x00\x00\x00\x00")) name: { |
| 3055 | 3429 | const index = std.mem.readInt(u32, symbol.name[4..], target_endian); |
| 3056 | 3430 | if (index >= string_table.len) |
| ... | ... | @@ -3058,21 +3432,125 @@ fn loadObject( |
| 3058 | 3432 | break :name string_table[index..]; |
| 3059 | 3433 | } else &symbol.name, 0); |
| 3060 | 3434 | |
| 3061 | | // Section numbers are 1-based here |
| 3062 | | if (!is_archive and @intFromEnum(symbol.section_number) > sections.len) |
| 3063 | | return diags.failParse(path, "bad section number {d} for '{s}'", .{ symbol.section_number, name }); |
| 3435 | const si = symbols.addOneAssumeCapacity(); |
| 3436 | si.* = .null; |
| 3437 | |
| 3438 | switch (symbol.section_number) { |
| 3439 | .UNDEFINED, .ABSOLUTE, .DEBUG => continue, |
| 3440 | else => switch (symbol.storage_class) { |
| 3441 | .STATIC => if (symbol.value == 0 and symbol.type == std.coff.SymType{ |
| 3442 | .complex_type = .NULL, |
| 3443 | .base_type = .NULL, |
| 3444 | }) { |
| 3445 | if (symbol.number_of_aux_symbols != 1) |
| 3446 | return diags.failParse(path, "invalid number of aux symbols for section {d}: {d}", .{ |
| 3447 | symbol_ix, |
| 3448 | symbol.number_of_aux_symbols, |
| 3449 | }); |
| 3450 | |
| 3451 | var section_def: std.coff.SectionDefinition = undefined; |
| 3452 | @memcpy(std.mem.asBytes(&section_def)[0..symbol_size], try r.peek(symbol_size)); |
| 3453 | if (target_endian != native_endian) |
| 3454 | std.mem.byteSwapAllFields(std.coff.SectionDefinition, &section_def); |
| 3455 | |
| 3456 | // TODO: Extract the COMDAT section info |
| 3457 | |
| 3458 | if (section_def.number > sections.len) |
| 3459 | return diags.failParse( |
| 3460 | path, |
| 3461 | "section symbol for '{s}' contained an out of bounds section number: {d}", |
| 3462 | .{ name, section_def.number }, |
| 3463 | ); |
| 3464 | |
| 3465 | // It's valid for this to not match the symbol's section number (ie. .drectve sets this) |
| 3466 | if (section_def.number == 0) |
| 3467 | continue; |
| 3468 | |
| 3469 | const section = &sections[section_def.number - 1]; |
| 3470 | if (section_def.number_of_relocations != section.header.number_of_relocations) |
| 3471 | return diags.failParse( |
| 3472 | path, |
| 3473 | "section symbol for '{s}' relocation count did not match section header: {d} vs {d}", |
| 3474 | .{ name, section_def.number_of_relocations, section.header.number_of_relocations }, |
| 3475 | ); |
| 3476 | |
| 3477 | if (section_def.number_of_linenumbers != section.header.number_of_linenumbers) |
| 3478 | return diags.failParse( |
| 3479 | path, |
| 3480 | "section symbol for '{s}' line number count did not match section header: {d} vs {d}", |
| 3481 | .{ name, section_def.number_of_linenumbers, section.header.number_of_linenumbers }, |
| 3482 | ); |
| 3483 | |
| 3484 | si.* = section.si; |
| 3485 | continue; |
| 3486 | }, |
| 3487 | .EXTERNAL => {}, |
| 3488 | else => continue, |
| 3489 | }, |
| 3490 | } |
| 3064 | 3491 | |
| 3065 | 3492 | if (is_archive) { |
| 3066 | 3493 | try coff.ensureMemberSymbol(mi, coff.getOrPutStringAssumeCapacity(name)); |
| 3067 | 3494 | continue; |
| 3068 | 3495 | } |
| 3069 | 3496 | |
| 3497 | // Section numbers are 1-based here |
| 3498 | if (@intFromEnum(symbol.section_number) <= 0 or @intFromEnum(symbol.section_number) > sections.len) |
| 3499 | return diags.failParse(path, "bad section number {d} for '{s}'", .{ symbol.section_number, name }); |
| 3500 | |
| 3070 | 3501 | const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = name }); |
| 3502 | // TODO: Support weak symbols |
| 3071 | 3503 | if (global_gop.found_existing) |
| 3072 | 3504 | return diags.failParse(path, "multiple definitions of '{s}'", .{name}); |
| 3505 | si.* = global_gop.value_ptr.*; |
| 3506 | |
| 3507 | const section = sections[@intCast(@intFromEnum(symbol.section_number) - 1)]; |
| 3508 | const section_sym = section.si.get(coff); |
| 3073 | 3509 | |
| 3074 | | // TODO: Get the sym and set the ni to point to wherever it was copied in the pseudo section |
| 3075 | | // TODO: May need to cache offsets and determine symbol sizes later (once we can sort by section offset) |
| 3510 | const sym = si.get(coff); |
| 3511 | sym.ni = section_sym.ni; |
| 3512 | sym.value = .{ .input_offset = symbol.value }; |
| 3513 | sym.section_number = section_sym.section_number; |
| 3514 | } |
| 3515 | |
| 3516 | if (coff.symbols.items.len > first_si) { |
| 3517 | input.first_si = @enumFromInt(first_si); |
| 3518 | input.last_si = @enumFromInt(coff.symbols.items.len - 1); |
| 3519 | } |
| 3520 | |
| 3521 | const relocation_size = std.coff.Relocation.sizeOf(); |
| 3522 | for (sections) |section| { |
| 3523 | if (section.si == .null) continue; |
| 3524 | |
| 3525 | const loc_sym = section.si.get(coff); |
| 3526 | assert(loc_sym.loc_relocs == .none); |
| 3527 | loc_sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 3528 | |
| 3529 | if (section.header.number_of_relocations == 0) continue; |
| 3530 | |
| 3531 | try coff.relocs.ensureUnusedCapacity(gpa, section.header.number_of_relocations); |
| 3532 | try fr.seekTo(fl.offset + section.header.pointer_to_relocations); |
| 3533 | for (0..section.header.number_of_relocations) |reloc_i| { |
| 3534 | var reloc: std.coff.Relocation = undefined; |
| 3535 | @memcpy(std.mem.asBytes(&reloc)[0..relocation_size], try r.take(relocation_size)); |
| 3536 | if (target_endian != native_endian) |
| 3537 | std.mem.byteSwapAllFields(std.coff.Relocation, &reloc); |
| 3538 | |
| 3539 | if (reloc.symbol_table_index >= symbols.items.len) |
| 3540 | return diags.failParse( |
| 3541 | path, |
| 3542 | "relocation {d} in section '{s}' targets invalid symbol index {d}", |
| 3543 | .{ reloc_i, section.name.toSlice(coff), reloc.symbol_table_index }, |
| 3544 | ); |
| 3545 | |
| 3546 | try coff.addReloc( |
| 3547 | section.si, |
| 3548 | reloc.virtual_address - section.header.virtual_address, |
| 3549 | symbols.items[reloc.symbol_table_index], |
| 3550 | .pending, |
| 3551 | @bitCast(reloc.type), // TODO: Checks on this cast? |
| 3552 | ); |
| 3553 | } |
| 3076 | 3554 | } |
| 3077 | 3555 | } |
| 3078 | 3556 | |
| ... | ... | @@ -3184,13 +3662,13 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 3184 | 3662 | error.WriteFailed => return nw.err.?, |
| 3185 | 3663 | else => |e| return e, |
| 3186 | 3664 | }; |
| 3187 | | si.get(coff).size = @intCast(nw.interface.end); |
| 3665 | si.get(coff).value.size = @intCast(nw.interface.end); |
| 3188 | 3666 | si.applyLocationRelocs(coff); |
| 3189 | 3667 | } |
| 3190 | 3668 | |
| 3191 | 3669 | // TODO: Did my MappedFile resize change affect this? |
| 3192 | 3670 | if (nav.resolved.?.@"linksection".unwrap()) |_| { |
| 3193 | | try ni.resize(&coff.mf, gpa, si.get(coff).size); |
| 3671 | try ni.resize(&coff.mf, gpa, si.get(coff).value.size); |
| 3194 | 3672 | var parent_ni = ni; |
| 3195 | 3673 | while (true) { |
| 3196 | 3674 | parent_ni = parent_ni.parent(&coff.mf); |
| ... | ... | @@ -3318,7 +3796,7 @@ fn updateFuncInner( |
| 3318 | 3796 | error.WriteFailed => return nw.err.?, |
| 3319 | 3797 | else => |e| return e, |
| 3320 | 3798 | }; |
| 3321 | | si.get(coff).size = @intCast(nw.interface.end); |
| 3799 | si.get(coff).value.size = @intCast(nw.interface.end); |
| 3322 | 3800 | si.applyLocationRelocs(coff); |
| 3323 | 3801 | } |
| 3324 | 3802 | |
| ... | ... | @@ -3543,6 +4021,28 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3543 | 4021 | }; |
| 3544 | 4022 | break :task; |
| 3545 | 4023 | } |
| 4024 | // TODO: Idle task for flushing obj into lib? |
| 4025 | if (coff.input_section_pending_index < coff.input_sections.items.len) { |
| 4026 | const isi: Node.InputSectionIndex = @enumFromInt(coff.input_section_pending_index); |
| 4027 | coff.input_section_pending_index += 1; |
| 4028 | const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff))); |
| 4029 | defer sub_prog_node.end(); |
| 4030 | coff.flushInputSection(isi) catch |err| switch (err) { |
| 4031 | else => |e| { |
| 4032 | const ii = isi.input(coff); |
| 4033 | return comp.link_diags.fail( |
| 4034 | "linker failed to read input section '{s}' from \"{f}{f}\": {t}", |
| 4035 | .{ |
| 4036 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 4037 | ii.path(coff).fmtEscapeString(), |
| 4038 | fmtArchiveNameString(ii.archiveName(coff)), |
| 4039 | e, |
| 4040 | }, |
| 4041 | ); |
| 4042 | }, |
| 4043 | }; |
| 4044 | break :task; |
| 4045 | } |
| 3546 | 4046 | while (coff.mf.updates.pop()) |ni| { |
| 3547 | 4047 | const clean_moved = ni.cleanMoved(&coff.mf); |
| 3548 | 4048 | const clean_resized = ni.cleanResized(&coff.mf); |
| ... | ... | @@ -3608,6 +4108,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3608 | 4108 | if (coff.globals.count() > coff.global_pending_index) return true; |
| 3609 | 4109 | if (coff.symbol_table.pending.count() > 0) return true; |
| 3610 | 4110 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| 4111 | if (coff.input_sections.items.len > coff.input_section_pending_index) return true; |
| 3611 | 4112 | if (coff.mf.updates.items.len > 0) return true; |
| 3612 | 4113 | if (coff.pending_members.count() > 0) return true; |
| 3613 | 4114 | if (coff.export_table.pending_sort) return true; |
| ... | ... | @@ -3626,6 +4127,14 @@ fn idleProgNode( |
| 3626 | 4127 | else => |tag| @tagName(tag), |
| 3627 | 4128 | .image_section => |si| std.mem.sliceTo(&si.get(coff).section_number.header(coff).name, 0), |
| 3628 | 4129 | inline .pseudo_section, .object_section => |smi| smi.name(coff).toSlice(coff), |
| 4130 | .input_section => |isi| { |
| 4131 | const ii = isi.input(coff); |
| 4132 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ |
| 4133 | ii.path(coff).fmtEscapeString(), |
| 4134 | fmtArchiveNameString(ii.archiveName(coff)), |
| 4135 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 4136 | }) catch &name; |
| 4137 | }, |
| 3629 | 4138 | .global => |gmi| gmi.globalName(coff).name.toSlice(coff), |
| 3630 | 4139 | .nav => |nmi| { |
| 3631 | 4140 | const ip = &coff.base.comp.zcu.?.intern_pool; |
| ... | ... | @@ -3699,7 +4208,7 @@ fn flushUav( |
| 3699 | 4208 | error.WriteFailed => return nw.err.?, |
| 3700 | 4209 | else => |e| return e, |
| 3701 | 4210 | }; |
| 3702 | | si.get(coff).size = @intCast(nw.interface.end); |
| 4211 | si.get(coff).value.size = @intCast(nw.interface.end); |
| 3703 | 4212 | si.applyLocationRelocs(coff); |
| 3704 | 4213 | } |
| 3705 | 4214 | |
| ... | ... | @@ -3864,12 +4373,12 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !void { |
| 3864 | 4373 | }); |
| 3865 | 4374 | @memcpy(ni.slice(&coff.mf)[0..init.len], &init); |
| 3866 | 4375 | sym.ni = ni; |
| 3867 | | sym.size = init.len; |
| 4376 | sym.value.size = init.len; |
| 3868 | 4377 | try coff.addReloc( |
| 3869 | 4378 | si, |
| 3870 | 4379 | init.len - 4, |
| 3871 | 4380 | gop.value_ptr.import_address_table_si, |
| 3872 | | @intCast(addr_size * import_symbol_index), |
| 4381 | .{ .known = @intCast(addr_size * import_symbol_index) }, |
| 3873 | 4382 | .{ .AMD64 = .REL32 }, |
| 3874 | 4383 | ); |
| 3875 | 4384 | }, |
| ... | ... | @@ -3929,7 +4438,7 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 3929 | 4438 | error.WriteFailed => return nw.err.?, |
| 3930 | 4439 | else => |e| return e, |
| 3931 | 4440 | }; |
| 3932 | | si.get(coff).size = @intCast(nw.interface.end); |
| 4441 | si.get(coff).value.size = @intCast(nw.interface.end); |
| 3933 | 4442 | si.applyLocationRelocs(coff); |
| 3934 | 4443 | } |
| 3935 | 4444 | |
| ... | ... | @@ -3992,6 +4501,15 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3992 | 4501 | @intCast(file_offset), |
| 3993 | 4502 | ); |
| 3994 | 4503 | }, |
| 4504 | .input_section => |isi| { |
| 4505 | const ii = isi.input(coff); |
| 4506 | var si = ii.firstSymbol(coff); |
| 4507 | const last_si = ii.lastSymbol(coff); |
| 4508 | while (@intFromEnum(si) <= @intFromEnum(last_si)) : (si = si.next()) { |
| 4509 | if (si.get(coff).ni != ni) continue; |
| 4510 | si.flushMoved(coff); |
| 4511 | } |
| 4512 | }, |
| 3995 | 4513 | .import_directory_table => coff.targetStore( |
| 3996 | 4514 | &coff.dataDirectoryPtr(.IMPORT).virtual_address, |
| 3997 | 4515 | coff.computeNodeRva(ni), |
| ... | ... | @@ -4204,6 +4722,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 4204 | 4722 | ); |
| 4205 | 4723 | } |
| 4206 | 4724 | }, |
| 4725 | .input_section => {}, |
| 4207 | 4726 | .import_directory_table => coff.targetStore( |
| 4208 | 4727 | &coff.dataDirectoryPtr(.IMPORT).size, |
| 4209 | 4728 | @intCast(size), |
| ... | ... | @@ -4228,7 +4747,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 4228 | 4747 | ); |
| 4229 | 4748 | } |
| 4230 | 4749 | |
| 4231 | | smi.symbol(coff).get(coff).size = @intCast(size); |
| 4750 | smi.symbol(coff).get(coff).value.size = @intCast(size); |
| 4232 | 4751 | }, |
| 4233 | 4752 | .global, |
| 4234 | 4753 | .nav, |
| ... | ... | @@ -4398,7 +4917,7 @@ fn updateExportsInner( |
| 4398 | 4917 | const export_sym = export_si.get(coff); |
| 4399 | 4918 | export_sym.ni = exported_ni; |
| 4400 | 4919 | export_sym.rva = exported_sym.rva; |
| 4401 | | export_sym.size = exported_sym.size; |
| 4920 | export_sym.value.size = exported_sym.value.size; |
| 4402 | 4921 | export_sym.section_number = exported_sym.section_number; |
| 4403 | 4922 | defer export_si.applyTargetRelocs(coff); |
| 4404 | 4923 | |
| ... | ... | @@ -4407,7 +4926,7 @@ fn updateExportsInner( |
| 4407 | 4926 | coff.optionalHeaderStandardPtr().address_of_entry_point = exported_sym.rva; |
| 4408 | 4927 | } else if (@"export".opts.name.eqlSlice("_tls_used", ip)) { |
| 4409 | 4928 | const tls_directory = coff.dataDirectoryPtr(.TLS); |
| 4410 | | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.size }; |
| 4929 | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.value.size }; |
| 4411 | 4930 | if (coff.targetEndian() != native_endian) |
| 4412 | 4931 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| 4413 | 4932 | } |
| ... | ... | @@ -4492,7 +5011,7 @@ fn updateExportsInner( |
| 4492 | 5011 | coff.export_table.export_address_table_si, |
| 4493 | 5012 | @intCast(@sizeOf(std.coff.ExportAddressTableEntry) * gop.index), |
| 4494 | 5013 | export_si, |
| 4495 | | 0, |
| 5014 | .{ .known = 0 }, |
| 4496 | 5015 | .{ .AMD64 = .ADDR32NB }, |
| 4497 | 5016 | ); |
| 4498 | 5017 | } else { |
| ... | ... | @@ -4541,6 +5060,14 @@ pub fn printNode( |
| 4541 | 5060 | .image_section => |si| try w.print("({s})", .{ |
| 4542 | 5061 | std.mem.sliceTo(&si.get(coff).section_number.header(coff).name, 0), |
| 4543 | 5062 | }), |
| 5063 | .input_section => |isi| { |
| 5064 | const ii = isi.input(coff); |
| 5065 | try w.print("({f}{f}, {s})", .{ |
| 5066 | ii.path(coff).fmtEscapeString(), |
| 5067 | fmtArchiveNameString(ii.archiveName(coff)), |
| 5068 | isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff), |
| 5069 | }); |
| 5070 | }, |
| 4544 | 5071 | .import_lookup_table, |
| 4545 | 5072 | .import_address_table, |
| 4546 | 5073 | .import_hint_name_table, |