| ... | ... | @@ -22,6 +22,7 @@ base: link.File, |
| 22 | 22 | mf: MappedFile, |
| 23 | 23 | nodes: std.MultiArrayList(Node), |
| 24 | 24 | import_table: ImportTable, |
| 25 | export_table: ExportTable, |
| 25 | 26 | strings: std.HashMapUnmanaged( |
| 26 | 27 | u32, |
| 27 | 28 | void, |
| ... | ... | @@ -146,6 +147,12 @@ pub const Node = union(enum) { |
| 146 | 147 | import_address_table: ImportTable.Index, |
| 147 | 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 | 156 | pseudo_section: PseudoSectionMapIndex, |
| 150 | 157 | object_section: ObjectSectionMapIndex, |
| 151 | 158 | global: GlobalMapIndex, |
| ... | ... | @@ -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 | 318 | pub const ImportTable = struct { |
| 274 | 319 | ni: MappedFile.Node.Index, |
| 275 | 320 | entries: std.array_hash_map.Auto(void, Entry), |
| ... | ... | @@ -314,6 +359,7 @@ pub const String = enum(u32) { |
| 314 | 359 | @".rdata" = 13, |
| 315 | 360 | @".text" = 20, |
| 316 | 361 | @".tls$" = 26, |
| 362 | @".edata" = 32, |
| 317 | 363 | _, |
| 318 | 364 | |
| 319 | 365 | pub const Optional = enum(u32) { |
| ... | ... | @@ -321,6 +367,7 @@ pub const String = enum(u32) { |
| 321 | 367 | @".rdata" = @intFromEnum(String.@".rdata"), |
| 322 | 368 | @".text" = @intFromEnum(String.@".text"), |
| 323 | 369 | @".tls$" = @intFromEnum(String.@".tls$"), |
| 370 | @".edata" = @intFromEnum(String.@".edata"), |
| 324 | 371 | none = std.math.maxInt(u32), |
| 325 | 372 | _, |
| 326 | 373 | |
| ... | ... | @@ -695,6 +742,14 @@ fn create( |
| 695 | 742 | .ni = .none, |
| 696 | 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 | 753 | .strings = .empty, |
| 699 | 754 | .string_bytes = .empty, |
| 700 | 755 | .image_section_table = .empty, |
| ... | ... | @@ -741,6 +796,7 @@ pub fn deinit(coff: *Coff) void { |
| 741 | 796 | coff.mf.deinit(gpa); |
| 742 | 797 | coff.nodes.deinit(gpa); |
| 743 | 798 | coff.import_table.entries.deinit(gpa); |
| 799 | coff.export_table.entries.deinit(gpa); |
| 744 | 800 | coff.strings.deinit(gpa); |
| 745 | 801 | coff.string_bytes.deinit(gpa); |
| 746 | 802 | coff.image_section_table.deinit(gpa); |
| ... | ... | @@ -780,7 +836,7 @@ fn initHeaders( |
| 780 | 836 | else |
| 781 | 837 | 0; |
| 782 | 838 | |
| 783 | | const expected_nodes_len = Node.known_count + 6 + |
| 839 | const expected_nodes_len = Node.known_count + 12 + |
| 784 | 840 | @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2; |
| 785 | 841 | try coff.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 786 | 842 | coff.nodes.appendAssumeCapacity(.file); |
| ... | ... | @@ -1005,6 +1061,67 @@ fn initHeaders( |
| 1005 | 1061 | ); |
| 1006 | 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 | 1125 | // While tls variables allocated at runtime are writable, the template itself is not |
| 1009 | 1126 | if (comp.config.any_non_single_threaded) _ = try coff.objectSectionMapIndex( |
| 1010 | 1127 | .@".tls$", |
| ... | ... | @@ -1048,6 +1165,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1048 | 1165 | .optional_header, |
| 1049 | 1166 | .data_directories, |
| 1050 | 1167 | .section_table, |
| 1168 | .export_name_table, |
| 1051 | 1169 | => unreachable, |
| 1052 | 1170 | .image_section => |si| si, |
| 1053 | 1171 | .import_directory_table => break :parent_rva coff.targetLoad( |
| ... | ... | @@ -1062,6 +1180,18 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1062 | 1180 | .import_hint_name_table => |import_index| break :parent_rva coff.targetLoad( |
| 1063 | 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 | 1195 | inline .pseudo_section, |
| 1066 | 1196 | .object_section, |
| 1067 | 1197 | .global, |
| ... | ... | @@ -1181,6 +1311,22 @@ pub fn importDirectoryEntryPtr( |
| 1181 | 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 | 1330 | fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 1185 | 1331 | defer coff.symbol_table.addOneAssumeCapacity().* = .{ |
| 1186 | 1332 | .ni = .none, |
| ... | ... | @@ -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 | 1954 | pub fn flush( |
| 1733 | 1955 | coff: *Coff, |
| 1734 | 1956 | arena: std.mem.Allocator, |
| ... | ... | @@ -1739,6 +1961,9 @@ pub fn flush( |
| 1739 | 1961 | _ = prog_node; |
| 1740 | 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 | 1967 | // hack for stage2_x86_64 + coff |
| 1743 | 1968 | const comp = coff.base.comp; |
| 1744 | 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 | 2157 | const comp = zcu.comp; |
| 1933 | 2158 | const gpa = zcu.gpa; |
| 1934 | 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 | 2170 | if (gn.lib_name.toSlice(coff)) |lib_name| { |
| 1936 | | const name = gn.name.toSlice(coff); |
| 1937 | 2171 | try coff.nodes.ensureUnusedCapacity(gpa, 4); |
| 1938 | 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 | 2174 | const gop = try coff.import_table.entries.getOrPutAdapted( |
| 1949 | 2175 | gpa, |
| 1950 | 2176 | lib_name, |
| ... | ... | @@ -2089,6 +2315,47 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { |
| 2089 | 2315 | coff.nodes.appendAssumeCapacity(.{ .global = gmi }); |
| 2090 | 2316 | sym.rva = coff.computeNodeRva(sym.ni); |
| 2091 | 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 | 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 | 2509 | inline .pseudo_section, |
| 2222 | 2510 | .object_section, |
| 2223 | 2511 | .global, |
| ... | ... | @@ -2272,6 +2560,11 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 2272 | 2560 | @intCast(size), |
| 2273 | 2561 | ), |
| 2274 | 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 | 2568 | inline .pseudo_section, |
| 2276 | 2569 | .object_section, |
| 2277 | 2570 | => |smi| smi.symbol(coff).get(coff).size = @intCast(size), |