| ... | @@ -22,6 +22,7 @@ base: link.File, | ... | @@ -22,6 +22,7 @@ base: link.File, |
| 22 | mf: MappedFile, | 22 | mf: MappedFile, |
| 23 | nodes: std.MultiArrayList(Node), | 23 | nodes: std.MultiArrayList(Node), |
| 24 | import_table: ImportTable, | 24 | import_table: ImportTable, |
| | 25 | export_table: ExportTable, |
| 25 | strings: std.HashMapUnmanaged( | 26 | strings: std.HashMapUnmanaged( |
| 26 | u32, | 27 | u32, |
| 27 | void, | 28 | void, |
| ... | @@ -146,6 +147,12 @@ pub const Node = union(enum) { | ... | @@ -146,6 +147,12 @@ pub const Node = union(enum) { |
| 146 | import_address_table: ImportTable.Index, | 147 | import_address_table: ImportTable.Index, |
| 147 | import_hint_name_table: ImportTable.Index, | 148 | import_hint_name_table: ImportTable.Index, |
| 148 | | 149 | |
| | 150 | export_directory_table, |
| | 151 | export_address_table, |
| | 152 | export_name_pointer_table, |
| | 153 | export_ordinal_table, |
| | 154 | export_name_table, |
| | 155 | |
| 149 | pseudo_section: PseudoSectionMapIndex, | 156 | pseudo_section: PseudoSectionMapIndex, |
| 150 | object_section: ObjectSectionMapIndex, | 157 | object_section: ObjectSectionMapIndex, |
| 151 | global: GlobalMapIndex, | 158 | global: GlobalMapIndex, |
| ... | @@ -270,6 +277,44 @@ pub const Node = union(enum) { | ... | @@ -270,6 +277,44 @@ pub const Node = union(enum) { |
| 270 | } | 277 | } |
| 271 | }; | 278 | }; |
| 272 | | 279 | |
| | 280 | pub const ExportTable = struct { |
| | 281 | ni: MappedFile.Node.Index, |
| | 282 | export_address_table_ni: MappedFile.Node.Index, |
| | 283 | name_pointer_table_ni: MappedFile.Node.Index, |
| | 284 | ordinal_table_ni: MappedFile.Node.Index, |
| | 285 | name_table_ni: MappedFile.Node.Index, |
| | 286 | entries: std.AutoArrayHashMapUnmanaged(void, Entry), |
| | 287 | |
| | 288 | pub const Entry = struct { |
| | 289 | name_index: u32, |
| | 290 | name_len: u32, |
| | 291 | }; |
| | 292 | |
| | 293 | const Adapter = struct { |
| | 294 | coff: *Coff, |
| | 295 | |
| | 296 | pub fn eql(adapter: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool { |
| | 297 | const coff = adapter.coff; |
| | 298 | const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf); |
| | 299 | const rhs = coff.export_table.entries.values()[rhs_index]; |
| | 300 | return std.mem.eql(u8, name_table_slice[rhs.name_index..][0..rhs.name_len], lhs_key); |
| | 301 | } |
| | 302 | |
| | 303 | pub fn hash(_: Adapter, key: []const u8) u32 { |
| | 304 | assert(std.mem.indexOfScalar(u8, key, 0) == null); |
| | 305 | return std.array_hash_map.hashString(key); |
| | 306 | } |
| | 307 | }; |
| | 308 | |
| | 309 | pub const Index = enum(u32) { |
| | 310 | _, |
| | 311 | |
| | 312 | pub fn get(export_index: ExportTable.Index, coff: *Coff) *Entry { |
| | 313 | return &coff.export_table.entries.values()[@intFromEnum(export_index)]; |
| | 314 | } |
| | 315 | }; |
| | 316 | }; |
| | 317 | |
| 273 | pub const ImportTable = struct { | 318 | pub const ImportTable = struct { |
| 274 | ni: MappedFile.Node.Index, | 319 | ni: MappedFile.Node.Index, |
| 275 | entries: std.array_hash_map.Auto(void, Entry), | 320 | entries: std.array_hash_map.Auto(void, Entry), |
| ... | @@ -314,6 +359,7 @@ pub const String = enum(u32) { | ... | @@ -314,6 +359,7 @@ pub const String = enum(u32) { |
| 314 | @".rdata" = 13, | 359 | @".rdata" = 13, |
| 315 | @".text" = 20, | 360 | @".text" = 20, |
| 316 | @".tls$" = 26, | 361 | @".tls$" = 26, |
| | 362 | @".edata" = 32, |
| 317 | _, | 363 | _, |
| 318 | | 364 | |
| 319 | pub const Optional = enum(u32) { | 365 | pub const Optional = enum(u32) { |
| ... | @@ -321,6 +367,7 @@ pub const String = enum(u32) { | ... | @@ -321,6 +367,7 @@ pub const String = enum(u32) { |
| 321 | @".rdata" = @intFromEnum(String.@".rdata"), | 367 | @".rdata" = @intFromEnum(String.@".rdata"), |
| 322 | @".text" = @intFromEnum(String.@".text"), | 368 | @".text" = @intFromEnum(String.@".text"), |
| 323 | @".tls$" = @intFromEnum(String.@".tls$"), | 369 | @".tls$" = @intFromEnum(String.@".tls$"), |
| | 370 | @".edata" = @intFromEnum(String.@".edata"), |
| 324 | none = std.math.maxInt(u32), | 371 | none = std.math.maxInt(u32), |
| 325 | _, | 372 | _, |
| 326 | | 373 | |
| ... | @@ -695,6 +742,14 @@ fn create( | ... | @@ -695,6 +742,14 @@ fn create( |
| 695 | .ni = .none, | 742 | .ni = .none, |
| 696 | .entries = .empty, | 743 | .entries = .empty, |
| 697 | }, | 744 | }, |
| | 745 | .export_table = .{ |
| | 746 | .ni = .none, |
| | 747 | .export_address_table_ni = .none, |
| | 748 | .name_pointer_table_ni = .none, |
| | 749 | .ordinal_table_ni = .none, |
| | 750 | .name_table_ni = .none, |
| | 751 | .entries = .empty, |
| | 752 | }, |
| 698 | .strings = .empty, | 753 | .strings = .empty, |
| 699 | .string_bytes = .empty, | 754 | .string_bytes = .empty, |
| 700 | .image_section_table = .empty, | 755 | .image_section_table = .empty, |
| ... | @@ -741,6 +796,7 @@ pub fn deinit(coff: *Coff) void { | ... | @@ -741,6 +796,7 @@ pub fn deinit(coff: *Coff) void { |
| 741 | coff.mf.deinit(gpa); | 796 | coff.mf.deinit(gpa); |
| 742 | coff.nodes.deinit(gpa); | 797 | coff.nodes.deinit(gpa); |
| 743 | coff.import_table.entries.deinit(gpa); | 798 | coff.import_table.entries.deinit(gpa); |
| | 799 | coff.export_table.entries.deinit(gpa); |
| 744 | coff.strings.deinit(gpa); | 800 | coff.strings.deinit(gpa); |
| 745 | coff.string_bytes.deinit(gpa); | 801 | coff.string_bytes.deinit(gpa); |
| 746 | coff.image_section_table.deinit(gpa); | 802 | coff.image_section_table.deinit(gpa); |
| ... | @@ -780,7 +836,7 @@ fn initHeaders( | ... | @@ -780,7 +836,7 @@ fn initHeaders( |
| 780 | else | 836 | else |
| 781 | 0; | 837 | 0; |
| 782 | | 838 | |
| 783 | const expected_nodes_len = Node.known_count + 6 + | 839 | const expected_nodes_len = Node.known_count + 12 + |
| 784 | @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2; | 840 | @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2; |
| 785 | try coff.nodes.ensureTotalCapacity(gpa, expected_nodes_len); | 841 | try coff.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 786 | coff.nodes.appendAssumeCapacity(.file); | 842 | coff.nodes.appendAssumeCapacity(.file); |
| ... | @@ -1005,6 +1061,67 @@ fn initHeaders( | ... | @@ -1005,6 +1061,67 @@ fn initHeaders( |
| 1005 | ); | 1061 | ); |
| 1006 | coff.nodes.appendAssumeCapacity(.import_directory_table); | 1062 | coff.nodes.appendAssumeCapacity(.import_directory_table); |
| 1007 | | 1063 | |
| | 1064 | { |
| | 1065 | // TODO: Could create this lazily when processing the first export instead? |
| | 1066 | const edata_section_ni = (try coff.pseudoSectionMapIndex( |
| | 1067 | .@".edata", |
| | 1068 | .of(std.coff.ExportDirectoryTable), |
| | 1069 | .{ .read = true }, |
| | 1070 | )).symbol(coff).node(coff); |
| | 1071 | |
| | 1072 | const name = "TODO_NAME.dll"; |
| | 1073 | const name_index = @sizeOf(std.coff.ExportDirectoryTable); |
| | 1074 | coff.export_table.ni = try coff.mf.addLastChildNode( |
| | 1075 | gpa, |
| | 1076 | edata_section_ni, |
| | 1077 | .{ |
| | 1078 | .size = @sizeOf(std.coff.ExportDirectoryTable) + name.len + 1, |
| | 1079 | .alignment = .of(std.coff.ExportDirectoryTable), |
| | 1080 | .fixed = true, |
| | 1081 | .moved = true, |
| | 1082 | }, |
| | 1083 | ); |
| | 1084 | @memcpy(coff.export_table.ni.slice(&coff.mf)[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]); |
| | 1085 | |
| | 1086 | coff.export_table.export_address_table_ni = try coff.mf.addLastChildNode(gpa, edata_section_ni, .{ |
| | 1087 | .alignment = .of(u32), |
| | 1088 | .moved = true, |
| | 1089 | }); |
| | 1090 | coff.export_table.name_pointer_table_ni = try coff.mf.addLastChildNode(gpa, edata_section_ni, .{ |
| | 1091 | .alignment = .of(u32), |
| | 1092 | .moved = true, |
| | 1093 | }); |
| | 1094 | coff.export_table.ordinal_table_ni = try coff.mf.addLastChildNode(gpa, edata_section_ni, .{ |
| | 1095 | .alignment = .of(u16), |
| | 1096 | .moved = true, |
| | 1097 | }); |
| | 1098 | coff.export_table.name_table_ni = try coff.mf.addLastChildNode(gpa, edata_section_ni, .{ |
| | 1099 | .alignment = .of(u8), |
| | 1100 | .moved = true, |
| | 1101 | }); |
| | 1102 | |
| | 1103 | coff.nodes.appendAssumeCapacity(.export_directory_table); |
| | 1104 | coff.nodes.appendAssumeCapacity(.export_address_table); |
| | 1105 | coff.nodes.appendAssumeCapacity(.export_name_pointer_table); |
| | 1106 | coff.nodes.appendAssumeCapacity(.export_ordinal_table); |
| | 1107 | coff.nodes.appendAssumeCapacity(.export_name_table); |
| | 1108 | |
| | 1109 | const export_directory_table = coff.exportDirectoryTable(); |
| | 1110 | export_directory_table.* = .{ |
| | 1111 | .flags = 0, |
| | 1112 | .time_date_stamp = timestamp, |
| | 1113 | .major_version = 0, |
| | 1114 | .minor_version = 0, |
| | 1115 | .name_rva = 0, |
| | 1116 | .ordinal_base = 1, |
| | 1117 | .number_of_entries = 0, |
| | 1118 | .number_of_names = 0, |
| | 1119 | .export_address_table_rva = 0, |
| | 1120 | .name_pointer_table_rva = 0, |
| | 1121 | .ordinal_table_rva = 0, |
| | 1122 | }; |
| | 1123 | } |
| | 1124 | |
| 1008 | // While tls variables allocated at runtime are writable, the template itself is not | 1125 | // While tls variables allocated at runtime are writable, the template itself is not |
| 1009 | if (comp.config.any_non_single_threaded) _ = try coff.objectSectionMapIndex( | 1126 | if (comp.config.any_non_single_threaded) _ = try coff.objectSectionMapIndex( |
| 1010 | .@".tls$", | 1127 | .@".tls$", |
| ... | @@ -1048,6 +1165,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { | ... | @@ -1048,6 +1165,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1048 | .optional_header, | 1165 | .optional_header, |
| 1049 | .data_directories, | 1166 | .data_directories, |
| 1050 | .section_table, | 1167 | .section_table, |
| | 1168 | .export_name_table, |
| 1051 | => unreachable, | 1169 | => unreachable, |
| 1052 | .image_section => |si| si, | 1170 | .image_section => |si| si, |
| 1053 | .import_directory_table => break :parent_rva coff.targetLoad( | 1171 | .import_directory_table => break :parent_rva coff.targetLoad( |
| ... | @@ -1062,6 +1180,18 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { | ... | @@ -1062,6 +1180,18 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1062 | .import_hint_name_table => |import_index| break :parent_rva coff.targetLoad( | 1180 | .import_hint_name_table => |import_index| break :parent_rva coff.targetLoad( |
| 1063 | &coff.importDirectoryEntryPtr(import_index).name_rva, | 1181 | &coff.importDirectoryEntryPtr(import_index).name_rva, |
| 1064 | ), | 1182 | ), |
| | 1183 | .export_directory_table => break :parent_rva coff.targetLoad( |
| | 1184 | &coff.dataDirectoryPtr(.EXPORT).virtual_address, |
| | 1185 | ), |
| | 1186 | .export_address_table => break :parent_rva coff.targetLoad( |
| | 1187 | &coff.exportDirectoryTable().export_address_table_rva, |
| | 1188 | ), |
| | 1189 | .export_name_pointer_table => break :parent_rva coff.targetLoad( |
| | 1190 | &coff.exportDirectoryTable().name_pointer_table_rva, |
| | 1191 | ), |
| | 1192 | .export_ordinal_table => break :parent_rva coff.targetLoad( |
| | 1193 | &coff.exportDirectoryTable().ordinal_table_rva, |
| | 1194 | ), |
| 1065 | inline .pseudo_section, | 1195 | inline .pseudo_section, |
| 1066 | .object_section, | 1196 | .object_section, |
| 1067 | .global, | 1197 | .global, |
| ... | @@ -1181,6 +1311,22 @@ pub fn importDirectoryEntryPtr( | ... | @@ -1181,6 +1311,22 @@ pub fn importDirectoryEntryPtr( |
| 1181 | return &coff.importDirectoryTableSlice()[@intFromEnum(import_index)]; | 1311 | return &coff.importDirectoryTableSlice()[@intFromEnum(import_index)]; |
| 1182 | } | 1312 | } |
| 1183 | | 1313 | |
| | 1314 | pub fn exportDirectoryTable(coff: *Coff) *std.coff.ExportDirectoryTable { |
| | 1315 | return @ptrCast(@alignCast(coff.export_table.ni.slice(&coff.mf))); |
| | 1316 | } |
| | 1317 | |
| | 1318 | pub fn exportAddressTableSlice(coff: *Coff) []std.coff.ExportAddressTableEntry { |
| | 1319 | return @ptrCast(@alignCast(coff.export_table.export_address_table_ni.slice(&coff.mf))); |
| | 1320 | } |
| | 1321 | |
| | 1322 | pub fn exportNamePointerTableSlice(coff: *Coff) []std.coff.ExportNamePointerTableEntry { |
| | 1323 | return @ptrCast(@alignCast(coff.export_table.name_pointer_table_ni.slice(&coff.mf))); |
| | 1324 | } |
| | 1325 | |
| | 1326 | pub fn exportOrdinalTableSlice(coff: *Coff) []std.coff.ExportOrdinalTableEntry { |
| | 1327 | return @ptrCast(@alignCast(coff.export_table.ordinal_table_ni.slice(&coff.mf))); |
| | 1328 | } |
| | 1329 | |
| 1184 | fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { | 1330 | fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 1185 | defer coff.symbol_table.addOneAssumeCapacity().* = .{ | 1331 | defer coff.symbol_table.addOneAssumeCapacity().* = .{ |
| 1186 | .ni = .none, | 1332 | .ni = .none, |
| ... | @@ -1729,6 +1875,82 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void { | ... | @@ -1729,6 +1875,82 @@ pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void { |
| 1729 | }; | 1875 | }; |
| 1730 | } | 1876 | } |
| 1731 | | 1877 | |
| | 1878 | fn flushExports(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| | 1879 | const export_count = coff.export_table.entries.count(); |
| | 1880 | if (export_count == 0) return; |
| | 1881 | |
| | 1882 | const gpa = coff.base.comp.zcu.?.gpa; |
| | 1883 | const edt = coff.exportDirectoryTable(); |
| | 1884 | edt.number_of_names = @intCast(export_count); |
| | 1885 | edt.number_of_entries = @intCast(export_count); |
| | 1886 | |
| | 1887 | try coff.export_table.name_pointer_table_ni.resize( |
| | 1888 | &coff.mf, |
| | 1889 | gpa, |
| | 1890 | export_count * @sizeOf(std.coff.ExportNamePointerTableEntry), |
| | 1891 | ); |
| | 1892 | |
| | 1893 | try coff.export_table.ordinal_table_ni.resize( |
| | 1894 | &coff.mf, |
| | 1895 | gpa, |
| | 1896 | export_count * @sizeOf(std.coff.ExportOrdinalTableEntry), |
| | 1897 | ); |
| | 1898 | |
| | 1899 | while (try coff.idle(tid)) {} |
| | 1900 | if (coff.targetEndian() != native_endian) |
| | 1901 | std.mem.byteSwapAllFields(std.coff.ExportDirectoryTable, edt); |
| | 1902 | |
| | 1903 | const name_table_rva = coff.computeNodeRva(coff.export_table.name_table_ni); |
| | 1904 | for ( |
| | 1905 | coff.exportNamePointerTableSlice(), |
| | 1906 | coff.exportOrdinalTableSlice(), |
| | 1907 | coff.export_table.entries.values(), |
| | 1908 | 0.., |
| | 1909 | ) |*np, *ord, entry, entry_i| { |
| | 1910 | np.name_rva = name_table_rva + entry.name_index; |
| | 1911 | if (coff.targetEndian() != native_endian) |
| | 1912 | std.mem.byteSwapAllFields(std.coff.ExportNamePointerTableEntry, np); |
| | 1913 | |
| | 1914 | ord.unbiased_ordinal = @intCast(entry_i); |
| | 1915 | if (coff.targetEndian() != native_endian) |
| | 1916 | std.mem.byteSwapAllFields(std.coff.ExportOrdinalTableEntry, &ord); |
| | 1917 | } |
| | 1918 | |
| | 1919 | const Context = struct { |
| | 1920 | np: []std.coff.ExportNamePointerTableEntry, |
| | 1921 | ord: []std.coff.ExportOrdinalTableEntry, |
| | 1922 | entries: []ExportTable.Entry, |
| | 1923 | names: []const u8, |
| | 1924 | |
| | 1925 | pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool { |
| | 1926 | const lhs_entry = &ctx.entries[lhs]; |
| | 1927 | const rhs_entry = &ctx.entries[rhs]; |
| | 1928 | return std.mem.lessThan( |
| | 1929 | u8, |
| | 1930 | ctx.names[lhs_entry.name_index..][0..lhs_entry.name_len], |
| | 1931 | ctx.names[rhs_entry.name_index..][0..rhs_entry.name_len], |
| | 1932 | ); |
| | 1933 | } |
| | 1934 | |
| | 1935 | pub fn swap(ctx: @This(), lhs: usize, rhs: usize) void { |
| | 1936 | std.mem.swap(std.coff.ExportNamePointerTableEntry, &ctx.np[lhs], &ctx.np[rhs]); |
| | 1937 | std.mem.swap(std.coff.ExportOrdinalTableEntry, &ctx.ord[lhs], &ctx.ord[rhs]); |
| | 1938 | std.mem.swap(ExportTable.Entry, &ctx.entries[lhs], &ctx.entries[rhs]); |
| | 1939 | } |
| | 1940 | }; |
| | 1941 | |
| | 1942 | std.sort.pdqContext(0, export_count, Context{ |
| | 1943 | .np = coff.exportNamePointerTableSlice(), |
| | 1944 | .ord = coff.exportOrdinalTableSlice(), |
| | 1945 | .entries = coff.export_table.entries.values(), |
| | 1946 | .names = coff.export_table.name_table_ni.slice(&coff.mf), |
| | 1947 | }); |
| | 1948 | |
| | 1949 | // TODO: Is there a way to know if this is the last flush? We could skip doing this if so. |
| | 1950 | // TODO: Need to reindex with adaptor? |
| | 1951 | //try coff.export_table.entries.reIndexContext(gpa, ExportTable.Adapter{ .coff = coff }); |
| | 1952 | } |
| | 1953 | |
| 1732 | pub fn flush( | 1954 | pub fn flush( |
| 1733 | coff: *Coff, | 1955 | coff: *Coff, |
| 1734 | arena: std.mem.Allocator, | 1956 | arena: std.mem.Allocator, |
| ... | @@ -1739,6 +1961,9 @@ pub fn flush( | ... | @@ -1739,6 +1961,9 @@ pub fn flush( |
| 1739 | _ = prog_node; | 1961 | _ = prog_node; |
| 1740 | while (try coff.idle(tid)) {} | 1962 | while (try coff.idle(tid)) {} |
| 1741 | | 1963 | |
| | 1964 | coff.flushExports(tid) catch |err| |
| | 1965 | return coff.base.comp.link_diags.fail("linker failed to flush exports: {t}", .{err}); |
| | 1966 | |
| 1742 | // hack for stage2_x86_64 + coff | 1967 | // hack for stage2_x86_64 + coff |
| 1743 | const comp = coff.base.comp; | 1968 | const comp = coff.base.comp; |
| 1744 | if (comp.compiler_rt_dyn_lib) |crt_file| { | 1969 | if (comp.compiler_rt_dyn_lib) |crt_file| { |
| ... | @@ -1932,19 +2157,20 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { | ... | @@ -1932,19 +2157,20 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { |
| 1932 | const comp = zcu.comp; | 2157 | const comp = zcu.comp; |
| 1933 | const gpa = zcu.gpa; | 2158 | const gpa = zcu.gpa; |
| 1934 | const gn = gmi.globalName(coff); | 2159 | const gn = gmi.globalName(coff); |
| | 2160 | |
| | 2161 | const target_endian = coff.targetEndian(); |
| | 2162 | const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic); |
| | 2163 | const addr_size: u64, const addr_align: std.mem.Alignment = switch (magic) { |
| | 2164 | _ => unreachable, |
| | 2165 | .PE32 => .{ 4, .@"4" }, |
| | 2166 | .@"PE32+" => .{ 8, .@"8" }, |
| | 2167 | }; |
| | 2168 | |
| | 2169 | const name = gn.name.toSlice(coff); |
| 1935 | if (gn.lib_name.toSlice(coff)) |lib_name| { | 2170 | if (gn.lib_name.toSlice(coff)) |lib_name| { |
| 1936 | const name = gn.name.toSlice(coff); | | |
| 1937 | try coff.nodes.ensureUnusedCapacity(gpa, 4); | 2171 | try coff.nodes.ensureUnusedCapacity(gpa, 4); |
| 1938 | try coff.symbol_table.ensureUnusedCapacity(gpa, 1); | 2172 | try coff.symbol_table.ensureUnusedCapacity(gpa, 1); |
| 1939 | | 2173 | |
| 1940 | const target_endian = coff.targetEndian(); | | |
| 1941 | const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic); | | |
| 1942 | const addr_size: u64, const addr_align: std.mem.Alignment = switch (magic) { | | |
| 1943 | _ => unreachable, | | |
| 1944 | .PE32 => .{ 4, .@"4" }, | | |
| 1945 | .@"PE32+" => .{ 8, .@"8" }, | | |
| 1946 | }; | | |
| 1947 | | | |
| 1948 | const gop = try coff.import_table.entries.getOrPutAdapted( | 2174 | const gop = try coff.import_table.entries.getOrPutAdapted( |
| 1949 | gpa, | 2175 | gpa, |
| 1950 | lib_name, | 2176 | lib_name, |
| ... | @@ -2089,6 +2315,47 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { | ... | @@ -2089,6 +2315,47 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { |
| 2089 | coff.nodes.appendAssumeCapacity(.{ .global = gmi }); | 2315 | coff.nodes.appendAssumeCapacity(.{ .global = gmi }); |
| 2090 | sym.rva = coff.computeNodeRva(sym.ni); | 2316 | sym.rva = coff.computeNodeRva(sym.ni); |
| 2091 | si.applyLocationRelocs(coff); | 2317 | si.applyLocationRelocs(coff); |
| | 2318 | } else { |
| | 2319 | const entries_ctx = ExportTable.Adapter{ .coff = coff }; |
| | 2320 | const gop = try coff.export_table.entries.getOrPutAdapted( |
| | 2321 | gpa, |
| | 2322 | name, |
| | 2323 | entries_ctx, |
| | 2324 | ); |
| | 2325 | |
| | 2326 | if (!gop.found_existing) { |
| | 2327 | errdefer _ = coff.export_table.entries.pop(); |
| | 2328 | if (coff.export_table.entries.count() > std.math.maxInt(@FieldType(std.coff.ExportDirectoryTable, "number_of_entries"))) |
| | 2329 | return coff.base.comp.link_diags.fail("exceeded maximum number of exports", .{}); |
| | 2330 | |
| | 2331 | const name_index = coff.export_table.name_table_ni.fileLocation(&coff.mf, true).size; |
| | 2332 | const new_name_table_size = name_index + name.len + 1; |
| | 2333 | if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index"))) |
| | 2334 | return coff.base.comp.link_diags.fail("exports name table limit reached", .{}); |
| | 2335 | |
| | 2336 | try coff.export_table.name_table_ni.resize(&coff.mf, gpa, new_name_table_size); |
| | 2337 | |
| | 2338 | const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf); |
| | 2339 | @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]); |
| | 2340 | |
| | 2341 | gop.value_ptr.* = .{ |
| | 2342 | .name_index = @intCast(name_index), |
| | 2343 | .name_len = @intCast(name.len), |
| | 2344 | }; |
| | 2345 | |
| | 2346 | const si = gmi.symbol(coff); |
| | 2347 | const sym = si.get(coff); |
| | 2348 | |
| | 2349 | try coff.export_table.export_address_table_ni.resize( |
| | 2350 | &coff.mf, |
| | 2351 | gpa, |
| | 2352 | coff.export_table.entries.count() * @sizeOf(std.coff.ExportAddressTableEntry), |
| | 2353 | ); |
| | 2354 | const ea = &coff.exportAddressTableSlice()[gop.index]; |
| | 2355 | ea.export_or_forwarder_rva = sym.rva; |
| | 2356 | if (coff.targetEndian() != native_endian) |
| | 2357 | std.mem.byteSwapAllFields(std.coff.ExportAddressTableEntry, &ea); |
| | 2358 | } |
| 2092 | } | 2359 | } |
| 2093 | } | 2360 | } |
| 2094 | | 2361 | |
| ... | @@ -2218,6 +2485,27 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -2218,6 +2485,27 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 2218 | import_hint_name_index += 2; | 2485 | import_hint_name_index += 2; |
| 2219 | } | 2486 | } |
| 2220 | }, | 2487 | }, |
| | 2488 | .export_directory_table => { |
| | 2489 | const rva = coff.computeNodeRva(ni); |
| | 2490 | coff.targetStore(&coff.dataDirectoryPtr(.EXPORT).virtual_address, rva); |
| | 2491 | coff.targetStore(&coff.exportDirectoryTable().name_rva, rva + @sizeOf(std.coff.ExportDirectoryTable)); |
| | 2492 | }, |
| | 2493 | .export_address_table => coff.targetStore( |
| | 2494 | &coff.exportDirectoryTable().export_address_table_rva, |
| | 2495 | coff.computeNodeRva(ni), |
| | 2496 | ), |
| | 2497 | .export_name_pointer_table => coff.targetStore( |
| | 2498 | &coff.exportDirectoryTable().name_pointer_table_rva, |
| | 2499 | coff.computeNodeRva(ni), |
| | 2500 | ), |
| | 2501 | .export_ordinal_table => coff.targetStore( |
| | 2502 | &coff.exportDirectoryTable().ordinal_table_rva, |
| | 2503 | coff.computeNodeRva(ni), |
| | 2504 | ), |
| | 2505 | .export_name_table => { |
| | 2506 | // .export_name_pointer_table entries are updated in flush |
| | 2507 | log.warn("flushMoved export_name_table unhandled", .{}); |
| | 2508 | }, |
| 2221 | inline .pseudo_section, | 2509 | inline .pseudo_section, |
| 2222 | .object_section, | 2510 | .object_section, |
| 2223 | .global, | 2511 | .global, |
| ... | @@ -2272,6 +2560,11 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { | ... | @@ -2272,6 +2560,11 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 2272 | @intCast(size), | 2560 | @intCast(size), |
| 2273 | ), | 2561 | ), |
| 2274 | .import_lookup_table, .import_address_table, .import_hint_name_table => {}, | 2562 | .import_lookup_table, .import_address_table, .import_hint_name_table => {}, |
| | 2563 | .export_directory_table => coff.targetStore( |
| | 2564 | &coff.dataDirectoryPtr(.EXPORT).size, |
| | 2565 | @intCast(size), |
| | 2566 | ), |
| | 2567 | .export_address_table, .export_name_pointer_table, .export_ordinal_table, .export_name_table => {}, |
| 2275 | inline .pseudo_section, | 2568 | inline .pseudo_section, |
| 2276 | .object_section, | 2569 | .object_section, |
| 2277 | => |smi| smi.symbol(coff).get(coff).size = @intCast(size), | 2570 | => |smi| smi.symbol(coff).get(coff).size = @intCast(size), |