| ... | ... | @@ -39,6 +39,7 @@ strings: std.HashMapUnmanaged( |
| 39 | 39 | ), |
| 40 | 40 | string_bytes: std.ArrayList(u8), |
| 41 | 41 | section_table: std.ArrayList(Section), |
| 42 | tls_si: Symbol.Index, |
| 42 | 43 | pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index), |
| 43 | 44 | object_section_table: std.array_hash_map.Auto(String, Symbol.Index), |
| 44 | 45 | symbols: std.ArrayList(Symbol), |
| ... | ... | @@ -56,6 +57,9 @@ pending_uavs: std.array_hash_map.Auto(Node.UavMapIndex, struct { |
| 56 | 57 | relocs: std.ArrayList(Reloc), |
| 57 | 58 | const_prog_node: std.Progress.Node, |
| 58 | 59 | synth_prog_node: std.Progress.Node, |
| 60 | symbol_prog_node: std.Progress.Node, |
| 61 | member_prog_node: std.Progress.Node, |
| 62 | dump_snapshot: bool, |
| 59 | 63 | |
| 60 | 64 | pub const default_file_alignment: u16 = 0x200; |
| 61 | 65 | pub const default_size_of_stack_reserve: u32 = 0x1000000; |
| ... | ... | @@ -158,7 +162,6 @@ pub const Node = union(enum) { |
| 158 | 162 | section_table, |
| 159 | 163 | // Archives and objects only |
| 160 | 164 | symbol_table, |
| 161 | | symbol_table_entry, |
| 162 | 165 | // Archives and objects only |
| 163 | 166 | string_table, |
| 164 | 167 | // Archives and objects only |
| ... | ... | @@ -314,8 +317,6 @@ pub const Node = union(enum) { |
| 314 | 317 | optional_header, |
| 315 | 318 | data_directories, |
| 316 | 319 | section_table, |
| 317 | | symbol_table, |
| 318 | | string_table, |
| 319 | 320 | }; |
| 320 | 321 | var mut_known: std.enums.EnumFieldStruct(Known, MappedFile.Node.Index, null) = undefined; |
| 321 | 322 | const info = @typeInfo(Known).@"enum"; |
| ... | ... | @@ -464,20 +465,18 @@ pub const LongNamesTable = struct { |
| 464 | 465 | }; |
| 465 | 466 | |
| 466 | 467 | pub const SymbolTable = struct { |
| 468 | ni: MappedFile.Node.Index, |
| 469 | strings_ni: MappedFile.Node.Index, |
| 467 | 470 | strings: std.AutoArrayHashMapUnmanaged(String, StringIndex), |
| 471 | pending: std.AutoArrayHashMapUnmanaged(Symbol.Index, void), |
| 468 | 472 | |
| 469 | | // Adding nodes to the symbol table has the result of accumulating padding |
| 473 | // Resizing the symbol table node has the result of accumulating padding |
| 470 | 474 | // between the last symbol in the symbol table node and the start of the |
| 471 | | // string table node, due to the growth factor in MappedFile. |
| 475 | // string table node, due to the shifting method when resizing the parent in MappedFile. |
| 472 | 476 | // The spec requires the string table begin immediately after the last symbol, |
| 473 | | // so we compact the symbol table node if needed. |
| 477 | // so we compact the symbol table node and move the string table back if needed. |
| 474 | 478 | pending_shrink: bool, |
| 475 | 479 | |
| 476 | | pub const Add = union(enum) { |
| 477 | | section, |
| 478 | | global, |
| 479 | | }; |
| 480 | | |
| 481 | 480 | pub const StringIndex = enum(u32) { |
| 482 | 481 | _, |
| 483 | 482 | }; |
| ... | ... | @@ -1103,12 +1102,16 @@ fn create( |
| 1103 | 1102 | .entries = .empty, |
| 1104 | 1103 | }, |
| 1105 | 1104 | .symbol_table = .{ |
| 1105 | .ni = .none, |
| 1106 | .strings_ni = .none, |
| 1106 | 1107 | .strings = .empty, |
| 1108 | .pending = .empty, |
| 1107 | 1109 | .pending_shrink = false, |
| 1108 | 1110 | }, |
| 1109 | 1111 | .strings = .empty, |
| 1110 | 1112 | .string_bytes = .empty, |
| 1111 | 1113 | .section_table = .empty, |
| 1114 | .tls_si = .null, |
| 1112 | 1115 | .pseudo_section_table = .empty, |
| 1113 | 1116 | .object_section_table = .empty, |
| 1114 | 1117 | .symbols = .empty, |
| ... | ... | @@ -1124,6 +1127,9 @@ fn create( |
| 1124 | 1127 | .relocs = .empty, |
| 1125 | 1128 | .const_prog_node = .none, |
| 1126 | 1129 | .synth_prog_node = .none, |
| 1130 | .symbol_prog_node = .none, |
| 1131 | .member_prog_node = .none, |
| 1132 | .dump_snapshot = options.enable_link_snapshots, |
| 1127 | 1133 | }; |
| 1128 | 1134 | errdefer coff.deinit(); |
| 1129 | 1135 | |
| ... | ... | @@ -1155,6 +1161,7 @@ pub fn deinit(coff: *Coff) void { |
| 1155 | 1161 | coff.import_table.entries.deinit(gpa); |
| 1156 | 1162 | coff.export_table.entries.deinit(gpa); |
| 1157 | 1163 | coff.symbol_table.strings.deinit(gpa); |
| 1164 | coff.symbol_table.pending.deinit(gpa); |
| 1158 | 1165 | coff.strings.deinit(gpa); |
| 1159 | 1166 | coff.string_bytes.deinit(gpa); |
| 1160 | 1167 | coff.section_table.deinit(gpa); |
| ... | ... | @@ -1222,14 +1229,21 @@ fn initHeaders( |
| 1222 | 1229 | |
| 1223 | 1230 | var expected_nodes_len: usize = Node.known_count; |
| 1224 | 1231 | if (comp.zcu != null) { |
| 1225 | | // Section nodes |
| 1232 | // Sections |
| 1226 | 1233 | expected_nodes_len += 3; |
| 1227 | | // // Symbol table nodes |
| 1228 | | // if (is_archive) expected_nodes_len += 6; |
| 1229 | | // Pseudo-sections and import / export table nodes |
| 1230 | | if (is_image) expected_nodes_len += 9; |
| 1231 | | // TLS section nodes |
| 1232 | | expected_nodes_len += @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2; |
| 1234 | |
| 1235 | if (is_image) |
| 1236 | // Pseudo-sections and import / export table |
| 1237 | expected_nodes_len += 9 |
| 1238 | else |
| 1239 | // Symbol table |
| 1240 | expected_nodes_len += 2; |
| 1241 | |
| 1242 | // TLS section |
| 1243 | if (comp.config.any_non_single_threaded) { |
| 1244 | if (!is_image) expected_nodes_len += 1; |
| 1245 | expected_nodes_len += 2; |
| 1246 | } |
| 1233 | 1247 | } |
| 1234 | 1248 | defer assert(coff.nodes.len == expected_nodes_len); |
| 1235 | 1249 | |
| ... | ... | @@ -1486,25 +1500,25 @@ fn initHeaders( |
| 1486 | 1500 | })); |
| 1487 | 1501 | coff.nodes.appendAssumeCapacity(.section_table); |
| 1488 | 1502 | |
| 1489 | | // TODO: These two nodes could be inside one movable node? |
| 1490 | | const symbol_table_ni = Node.known.symbol_table; |
| 1491 | | assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{ |
| 1492 | | .alignment = .@"2", |
| 1493 | | .fixed = true, |
| 1494 | | .moved = true, |
| 1495 | | })); |
| 1496 | | coff.nodes.appendAssumeCapacity(.symbol_table); |
| 1503 | assert(coff.nodes.len == Node.known_count); |
| 1497 | 1504 | |
| 1498 | | const string_table_ni = Node.known.string_table; |
| 1499 | | assert(string_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{ |
| 1500 | | .alignment = .@"2", |
| 1501 | | .size = if (!is_image) @sizeOf(u32) else 0, |
| 1502 | | .fixed = true, |
| 1503 | | .resized = true, |
| 1504 | | })); |
| 1505 | | coff.nodes.appendAssumeCapacity(.string_table); |
| 1505 | if (!is_image) { |
| 1506 | // TODO: These two nodes could be inside one movable node? |
| 1507 | coff.symbol_table.ni = try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{ |
| 1508 | .alignment = .@"2", |
| 1509 | .fixed = true, |
| 1510 | .moved = true, |
| 1511 | }); |
| 1512 | coff.nodes.appendAssumeCapacity(.symbol_table); |
| 1506 | 1513 | |
| 1507 | | assert(coff.nodes.len == Node.known_count); |
| 1514 | coff.symbol_table.strings_ni = try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{ |
| 1515 | .alignment = .@"2", |
| 1516 | .size = @sizeOf(u32), |
| 1517 | .fixed = true, |
| 1518 | .resized = true, |
| 1519 | }); |
| 1520 | coff.nodes.appendAssumeCapacity(.string_table); |
| 1521 | } |
| 1508 | 1522 | |
| 1509 | 1523 | try coff.symbols.ensureTotalCapacity(gpa, Symbol.Index.known_count); |
| 1510 | 1524 | coff.symbols.addOneAssumeCapacity().* = .{ |
| ... | ... | @@ -1618,12 +1632,23 @@ fn initHeaders( |
| 1618 | 1632 | std.mem.byteSwapAllFields(std.coff.ExportDirectoryTable, export_directory_table); |
| 1619 | 1633 | } |
| 1620 | 1634 | |
| 1621 | | // While tls variables allocated at runtime are writable, the template itself is not |
| 1622 | | if (comp.config.any_non_single_threaded) _ = try coff.objectSectionMapIndex( |
| 1623 | | .@".tls$", |
| 1624 | | if (is_image) coff.mf.flags.block_size else .@"1", |
| 1625 | | .{ .read = true }, |
| 1626 | | ); |
| 1635 | if (comp.config.any_non_single_threaded) { |
| 1636 | if (!is_image) |
| 1637 | coff.tls_si = try coff.addSection(".tls$", .{ |
| 1638 | .CNT_INITIALIZED_DATA = true, |
| 1639 | .MEM_READ = true, |
| 1640 | .MEM_WRITE = true, |
| 1641 | }); |
| 1642 | |
| 1643 | // While tls variables allocated at runtime are writable, the template itself is not. |
| 1644 | // In images, this call triggers the creation of a .tls pseudo section in .rdata. |
| 1645 | // In objects / archives, this section is part of the above .tls$ section. |
| 1646 | _ = try coff.objectSectionMapIndex( |
| 1647 | .@".tls$", |
| 1648 | coff.mf.flags.block_size, |
| 1649 | .{ .read = true, .write = !is_image, .tls = true }, |
| 1650 | ); |
| 1651 | } |
| 1627 | 1652 | } |
| 1628 | 1653 | |
| 1629 | 1654 | pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void { |
| ... | ... | @@ -1634,12 +1659,23 @@ pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void { |
| 1634 | 1659 | for (&coff.lazy.values) |*lazy| count += lazy.map.count() - lazy.pending_index; |
| 1635 | 1660 | break :count count; |
| 1636 | 1661 | }); |
| 1662 | if (!isImage(coff)) { |
| 1663 | prog_node.increaseEstimatedTotalItems(2); |
| 1664 | coff.symbol_prog_node = prog_node.start("Symbols", coff.symbol_table.pending.count()); |
| 1665 | coff.member_prog_node = prog_node.start("Members", coff.pending_members.count()); |
| 1666 | } |
| 1637 | 1667 | coff.mf.update_prog_node = prog_node.start("Relocations", coff.mf.updates.items.len); |
| 1638 | 1668 | } |
| 1639 | 1669 | |
| 1640 | 1670 | pub fn endProgress(coff: *Coff) void { |
| 1641 | 1671 | coff.mf.update_prog_node.end(); |
| 1642 | 1672 | coff.mf.update_prog_node = .none; |
| 1673 | if (!isImage(coff)) { |
| 1674 | coff.member_prog_node.end(); |
| 1675 | coff.member_prog_node = .none; |
| 1676 | coff.symbol_prog_node.end(); |
| 1677 | coff.symbol_prog_node = .none; |
| 1678 | } |
| 1643 | 1679 | coff.synth_prog_node.end(); |
| 1644 | 1680 | coff.synth_prog_node = .none; |
| 1645 | 1681 | coff.const_prog_node.end(); |
| ... | ... | @@ -1665,7 +1701,6 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1665 | 1701 | .placeholder, |
| 1666 | 1702 | |
| 1667 | 1703 | .symbol_table, |
| 1668 | | .symbol_table_entry, |
| 1669 | 1704 | .string_table, |
| 1670 | 1705 | .relocation_table, |
| 1671 | 1706 | .relocation_table_entry, |
| ... | ... | @@ -1858,7 +1893,7 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader { |
| 1858 | 1893 | pub fn symbolTableEntryStoragePtr(coff: *Coff, index: u32) *[std.coff.Symbol.sizeOf()]u8 { |
| 1859 | 1894 | assert(!coff.isImage()); |
| 1860 | 1895 | const offset = index * std.coff.Symbol.sizeOf(); |
| 1861 | | return @ptrCast(@alignCast(Node.known.symbol_table.slice(&coff.mf)[offset..][0..std.coff.Symbol.sizeOf()])); |
| 1896 | return @ptrCast(@alignCast(coff.symbol_table.ni.slice(&coff.mf)[offset..][0..std.coff.Symbol.sizeOf()])); |
| 1862 | 1897 | } |
| 1863 | 1898 | |
| 1864 | 1899 | pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.Symbol { |
| ... | ... | @@ -1876,7 +1911,7 @@ pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, si: Symbol.Index) *align(2) st |
| 1876 | 1911 | } |
| 1877 | 1912 | |
| 1878 | 1913 | pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 { |
| 1879 | | return @ptrCast(@alignCast(Node.known.string_table.slice(&coff.mf)[0..@sizeOf(u32)])); |
| 1914 | return @ptrCast(@alignCast(coff.symbol_table.strings_ni.slice(&coff.mf)[0..@sizeOf(u32)])); |
| 1880 | 1915 | } |
| 1881 | 1916 | |
| 1882 | 1917 | pub fn importDirectoryTableSlice(coff: *Coff) []std.coff.ImportDirectoryEntry { |
| ... | ... | @@ -1971,6 +2006,18 @@ pub fn globalSymbol(coff: *Coff, opts: struct { |
| 1971 | 2006 | return sym_gop.value_ptr.*; |
| 1972 | 2007 | } |
| 1973 | 2008 | |
| 2009 | pub fn pendingSymbolTableEntry(coff: *Coff, si: Symbol.Index) !void { |
| 2010 | assert(!coff.isImage()); |
| 2011 | const sym = si.get(coff); |
| 2012 | assert(sym.ni != .none or sym.gmi != .none); |
| 2013 | |
| 2014 | const gpa = coff.base.comp.gpa; |
| 2015 | const pending_gop = try coff.symbol_table.pending.getOrPut(gpa, si); |
| 2016 | if (!pending_gop.found_existing) { |
| 2017 | coff.symbol_prog_node.increaseEstimatedTotalItems(1); |
| 2018 | } |
| 2019 | } |
| 2020 | |
| 1974 | 2021 | fn navSection( |
| 1975 | 2022 | coff: *Coff, |
| 1976 | 2023 | zcu: *Zcu, |
| ... | ... | @@ -1979,7 +2026,7 @@ fn navSection( |
| 1979 | 2026 | const ip = &zcu.intern_pool; |
| 1980 | 2027 | const default: String, const attributes: ObjectSectionAttributes = |
| 1981 | 2028 | if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{ |
| 1982 | | .@".tls$", .{ .read = true, .write = true }, |
| 2029 | .@".tls$", .{ .read = true, .write = true, .tls = true }, |
| 1983 | 2030 | } else if (ip.isFunctionType(nav_resolved.type)) .{ |
| 1984 | 2031 | .@".text", .{ .read = true, .execute = true }, |
| 1985 | 2032 | } else if (nav_resolved.@"const") .{ |
| ... | ... | @@ -2149,6 +2196,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member. |
| 2149 | 2196 | gpa, |
| 2150 | 2197 | coff.pending_members.capacity() + 1, |
| 2151 | 2198 | ); |
| 2199 | coff.member_prog_node.increaseEstimatedTotalItems(1); |
| 2152 | 2200 | }, |
| 2153 | 2201 | } |
| 2154 | 2202 | |
| ... | ... | @@ -2249,16 +2297,15 @@ fn ensureMemberSymbol( |
| 2249 | 2297 | } |
| 2250 | 2298 | |
| 2251 | 2299 | coff.pending_members.putAssumeCapacity(mi, {}); |
| 2300 | coff.member_prog_node.increaseEstimatedTotalItems(1); |
| 2252 | 2301 | } |
| 2253 | 2302 | |
| 2254 | | // TODO: -> flushSymbolTableEntry, and push all call sites onto a pending list instead? |
| 2255 | | fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2303 | fn flushSymbolTableEntry(coff: *Coff, si: Symbol.Index, pt: Zcu.PerThread) !void { |
| 2256 | 2304 | assert(!coff.isImage()); |
| 2257 | 2305 | const gpa = coff.base.comp.gpa; |
| 2258 | 2306 | |
| 2259 | 2307 | const sym = si.get(coff); |
| 2260 | | const has_node = sym.ni != .none; |
| 2261 | | assert(has_node or sym.gmi != .none); |
| 2308 | assert(sym.ni != .none or sym.gmi != .none); |
| 2262 | 2309 | |
| 2263 | 2310 | const entry = coff.symbolTableEntryPtr(sym.sti) orelse entry: { |
| 2264 | 2311 | var buf: [15]u8 = undefined; |
| ... | ... | @@ -2274,14 +2321,14 @@ fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2274 | 2321 | else |
| 2275 | 2322 | .NULL, |
| 2276 | 2323 | }; |
| 2277 | | } else switch (coff.getNode(sym.ni)) { |
| 2324 | } else blk: switch (coff.getNode(sym.ni)) { |
| 2278 | 2325 | .image_section => .{ |
| 2279 | 2326 | &sym.section_number.header(coff).name, |
| 2280 | 2327 | null, |
| 2281 | 2328 | 1, |
| 2282 | 2329 | .NULL, |
| 2283 | 2330 | }, |
| 2284 | | .nav => |nmi| blk: { |
| 2331 | .nav => |nmi| { |
| 2285 | 2332 | const zcu = coff.base.comp.zcu.?; |
| 2286 | 2333 | const ip = &zcu.intern_pool; |
| 2287 | 2334 | const nav = ip.getNav(nmi.navIndex(coff)); |
| ... | ... | @@ -2292,14 +2339,25 @@ fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2292 | 2339 | if (ip.isFunctionType(nav.resolved.?.type)) .FUNCTION else .NULL, |
| 2293 | 2340 | }; |
| 2294 | 2341 | }, |
| 2295 | | .uav => |umi| blk: { |
| 2342 | .uav => |umi| { |
| 2296 | 2343 | var w = Io.Writer.fixed(&buf); |
| 2297 | 2344 | w.print("__anon_{x}", .{umi.uavValue(coff)}) catch unreachable; |
| 2298 | 2345 | break :blk .{ w.buffered(), null, 0, .NULL }; |
| 2299 | 2346 | }, |
| 2347 | inline .lazy_code, .lazy_const_data => |mi, tag| { |
| 2348 | const lazy_sym = mi.lazySymbol(coff); |
| 2349 | const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{ |
| 2350 | @tagName(lazy_sym.kind), |
| 2351 | Type.fromInterned(lazy_sym.ty).fmt(pt), |
| 2352 | }); |
| 2353 | defer gpa.free(name); |
| 2354 | |
| 2355 | const string = try coff.getOrPutString(name); |
| 2356 | break :blk .{ string.toSlice(coff), string, 0, if (tag == .lazy_code) .FUNCTION else .NULL }; |
| 2357 | }, |
| 2300 | 2358 | else => { |
| 2301 | | log.err("TODO implement symbol table init for {s}", .{@tagName(coff.getNode(sym.ni))}); |
| 2302 | | return .none; |
| 2359 | log.err("TODO implement symbol table init for {s} ({d})", .{ @tagName(coff.getNode(sym.ni)), si }); |
| 2360 | unreachable; |
| 2303 | 2361 | }, |
| 2304 | 2362 | }; |
| 2305 | 2363 | |
| ... | ... | @@ -2307,11 +2365,11 @@ fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2307 | 2365 | const string = opt_name_string orelse try coff.getOrPutString(name_slice); |
| 2308 | 2366 | const string_gop = try coff.symbol_table.strings.getOrPut(gpa, string); |
| 2309 | 2367 | if (!string_gop.found_existing) { |
| 2310 | | const string_index = Node.known.string_table.location(&coff.mf).resolve(&coff.mf)[1]; |
| 2368 | const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1]; |
| 2311 | 2369 | string_gop.value_ptr.* = @enumFromInt(string_index); |
| 2312 | 2370 | |
| 2313 | | try Node.known.string_table.resize(&coff.mf, gpa, string_index + name_slice.len + 1); |
| 2314 | | const slice = Node.known.string_table.slice(&coff.mf); |
| 2371 | try coff.symbol_table.strings_ni.resize(&coff.mf, gpa, string_index + name_slice.len + 1); |
| 2372 | const slice = coff.symbol_table.strings_ni.slice(&coff.mf); |
| 2315 | 2373 | @memcpy(slice[string_index..][0..name_slice.len], name_slice); |
| 2316 | 2374 | slice[string_index + name_slice.len] = 0; |
| 2317 | 2375 | } |
| ... | ... | @@ -2322,11 +2380,7 @@ fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2322 | 2380 | const old_num_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); |
| 2323 | 2381 | const new_num_symbols = old_num_symbols + 1 + num_aux_symbols; |
| 2324 | 2382 | |
| 2325 | | try Node.known.symbol_table.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf()); |
| 2326 | | |
| 2327 | | const symbol_table_loc = Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf); |
| 2328 | | const string_table_loc = Node.known.string_table.location(&coff.mf).resolve(&coff.mf); |
| 2329 | | coff.symbol_table.pending_shrink = string_table_loc[0] - (symbol_table_loc[0] + symbol_table_loc[1]) > 0; |
| 2383 | try coff.symbol_table.ni.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf()); |
| 2330 | 2384 | |
| 2331 | 2385 | coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols); |
| 2332 | 2386 | sym.sti = .wrap(old_num_symbols); |
| ... | ... | @@ -2373,8 +2427,6 @@ fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index { |
| 2373 | 2427 | }); |
| 2374 | 2428 | |
| 2375 | 2429 | log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti }); |
| 2376 | | |
| 2377 | | return sym.sti; |
| 2378 | 2430 | } |
| 2379 | 2431 | |
| 2380 | 2432 | fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index { |
| ... | ... | @@ -2384,6 +2436,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags |
| 2384 | 2436 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2385 | 2437 | try coff.section_table.ensureUnusedCapacity(gpa, 1); |
| 2386 | 2438 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 2439 | if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1); |
| 2387 | 2440 | |
| 2388 | 2441 | const coff_header = coff.headerPtr(); |
| 2389 | 2442 | const section_index = coff.targetLoad(&coff_header.number_of_sections); |
| ... | ... | @@ -2457,7 +2510,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags |
| 2457 | 2510 | ), |
| 2458 | 2511 | } |
| 2459 | 2512 | } else { |
| 2460 | | assert(try coff.updateSymbolTableEntry(si) != .none); |
| 2513 | try coff.pendingSymbolTableEntry(si); |
| 2461 | 2514 | } |
| 2462 | 2515 | |
| 2463 | 2516 | return si; |
| ... | ... | @@ -2472,7 +2525,9 @@ const ObjectSectionAttributes = packed struct { |
| 2472 | 2525 | nocache: bool = false, |
| 2473 | 2526 | discard: bool = false, |
| 2474 | 2527 | remove: bool = false, |
| 2528 | tls: bool = false, |
| 2475 | 2529 | }; |
| 2530 | |
| 2476 | 2531 | fn pseudoSectionMapIndex( |
| 2477 | 2532 | coff: *Coff, |
| 2478 | 2533 | name: String, |
| ... | ... | @@ -2485,6 +2540,8 @@ fn pseudoSectionMapIndex( |
| 2485 | 2540 | if (!pseudo_section_gop.found_existing) { |
| 2486 | 2541 | const parent: Symbol.Index = if (attributes.execute) |
| 2487 | 2542 | .text |
| 2543 | else if (attributes.tls and coff.tls_si != .null) |
| 2544 | coff.tls_si |
| 2488 | 2545 | else if (attributes.write) |
| 2489 | 2546 | .data |
| 2490 | 2547 | else |
| ... | ... | @@ -2556,35 +2613,6 @@ fn objectSectionMapIndex( |
| 2556 | 2613 | return osmi; |
| 2557 | 2614 | } |
| 2558 | 2615 | |
| 2559 | | fn ensureUnusedRelocCapacity(coff: *Coff, loc_si: Symbol.Index, len: usize) !void { |
| 2560 | | const gpa = coff.base.comp.gpa; |
| 2561 | | |
| 2562 | | try coff.relocs.ensureUnusedCapacity(gpa, len); |
| 2563 | | if (isImage(coff)) return; |
| 2564 | | |
| 2565 | | switch (loc_si.get(coff).section_number) { |
| 2566 | | .UNDEFINED, .ABSOLUTE, .DEBUG => {}, |
| 2567 | | else => |sn| { |
| 2568 | | const section = sn.section(coff); |
| 2569 | | const header = sn.header(coff); |
| 2570 | | const new_size = (len + coff.targetLoad(&header.number_of_relocations)) * std.coff.Relocation.sizeOf(); |
| 2571 | | if (section.relocation_table_ni == .none) { |
| 2572 | | // The entry's length in the file is shorter than its @sizeOf |
| 2573 | | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2574 | | section.relocation_table_ni = try coff.mf.addLastChildNode(gpa, Node.known.zcu_member, .{ |
| 2575 | | .size = new_size, |
| 2576 | | .alignment = .@"2", |
| 2577 | | .moved = true, |
| 2578 | | .resized = true, |
| 2579 | | }); |
| 2580 | | coff.nodes.appendAssumeCapacity(.{ .relocation_table = sn }); |
| 2581 | | } else { |
| 2582 | | try section.relocation_table_ni.resize(&coff.mf, gpa, new_size); |
| 2583 | | } |
| 2584 | | }, |
| 2585 | | } |
| 2586 | | } |
| 2587 | | |
| 2588 | 2616 | pub fn addReloc( |
| 2589 | 2617 | coff: *Coff, |
| 2590 | 2618 | loc_si: Symbol.Index, |
| ... | ... | @@ -2612,10 +2640,10 @@ pub fn addReloc( |
| 2612 | 2640 | // have a node. In that case, flushGlobal will create the symbol table entry. |
| 2613 | 2641 | const sti: SymbolTable.Index = if (target.sti != .none) |
| 2614 | 2642 | target.sti |
| 2615 | | else if (target.ni != .none) |
| 2616 | | try updateSymbolTableEntry(coff, target_si) |
| 2617 | | else |
| 2618 | | .none; |
| 2643 | else if (target.ni != .none) sti: { |
| 2644 | try coff.pendingSymbolTableEntry(target_si); |
| 2645 | break :sti .none; |
| 2646 | } else .none; |
| 2619 | 2647 | |
| 2620 | 2648 | const section = loc_sn.section(coff); |
| 2621 | 2649 | const header = loc_sn.header(coff); |
| ... | ... | @@ -2714,6 +2742,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 2714 | 2742 | .none => { |
| 2715 | 2743 | const sec_si = try coff.navSection(zcu, nav.resolved.?); |
| 2716 | 2744 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2745 | if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1); |
| 2717 | 2746 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 2718 | 2747 | .alignment = zcu.navAlignment(nav_index).toStdMem(), |
| 2719 | 2748 | .moved = true, |
| ... | ... | @@ -2728,8 +2757,8 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 2728 | 2757 | const sym = si.get(coff); |
| 2729 | 2758 | assert(sym.loc_relocs == .none); |
| 2730 | 2759 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 2731 | | if (sym.target_relocs != .none) |
| 2732 | | _ = try coff.updateSymbolTableEntry(si); |
| 2760 | if (!isImage(coff) and sym.target_relocs != .none) |
| 2761 | try coff.pendingSymbolTableEntry(si); |
| 2733 | 2762 | |
| 2734 | 2763 | break :ni sym.ni; |
| 2735 | 2764 | }; |
| ... | ... | @@ -2836,6 +2865,7 @@ fn updateFuncInner( |
| 2836 | 2865 | .none => { |
| 2837 | 2866 | const sec_si = try coff.navSection(zcu, nav.resolved.?); |
| 2838 | 2867 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2868 | if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1); |
| 2839 | 2869 | const mod = zcu.navFileScope(func.owner_nav).mod.?; |
| 2840 | 2870 | const target = &mod.resolved_target.result; |
| 2841 | 2871 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| ... | ... | @@ -2861,8 +2891,8 @@ fn updateFuncInner( |
| 2861 | 2891 | const sym = si.get(coff); |
| 2862 | 2892 | assert(sym.loc_relocs == .none); |
| 2863 | 2893 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 2864 | | if (sym.target_relocs != .none) |
| 2865 | | _ = try coff.updateSymbolTableEntry(si); |
| 2894 | if (!isImage(coff) and sym.target_relocs != .none) |
| 2895 | try coff.pendingSymbolTableEntry(si); |
| 2866 | 2896 | break :ni sym.ni; |
| 2867 | 2897 | }; |
| 2868 | 2898 | |
| ... | ... | @@ -3015,8 +3045,9 @@ pub fn flush( |
| 3015 | 3045 | else => |e| return comp.link_diags.fail("flush write failed: {t}", .{e}), |
| 3016 | 3046 | }; |
| 3017 | 3047 | |
| 3018 | | coff.dumpStderr(tid) catch |err| |
| 3019 | | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); |
| 3048 | if (coff.dump_snapshot) |
| 3049 | coff.dumpStderr(tid) catch |err| |
| 3050 | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); |
| 3020 | 3051 | } |
| 3021 | 3052 | |
| 3022 | 3053 | pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| ... | ... | @@ -3083,6 +3114,29 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3083 | 3114 | }; |
| 3084 | 3115 | break :task; |
| 3085 | 3116 | }; |
| 3117 | while (coff.symbol_table.pending.pop()) |pending_si| { |
| 3118 | const sym = pending_si.key.get(coff); |
| 3119 | const sub_prog_node = coff.idleProgNode( |
| 3120 | tid, |
| 3121 | coff.symbol_prog_node, |
| 3122 | if (sym.ni != .none) |
| 3123 | coff.getNode(sym.ni) |
| 3124 | else |
| 3125 | .{ .global = pending_si.key.get(coff).gmi }, |
| 3126 | ); |
| 3127 | defer sub_prog_node.end(); |
| 3128 | coff.flushSymbolTableEntry( |
| 3129 | pending_si.key, |
| 3130 | .{ .zcu = comp.zcu.?, .tid = tid }, |
| 3131 | ) catch |err| switch (err) { |
| 3132 | error.OutOfMemory => return error.OutOfMemory, |
| 3133 | else => |e| return comp.link_diags.fail( |
| 3134 | "linker failed to flush symbol table entry: {t}", |
| 3135 | .{e}, |
| 3136 | ), |
| 3137 | }; |
| 3138 | break :task; |
| 3139 | } |
| 3086 | 3140 | while (coff.mf.updates.pop()) |ni| { |
| 3087 | 3141 | const clean_moved = ni.cleanMoved(&coff.mf); |
| 3088 | 3142 | const clean_resized = ni.cleanResized(&coff.mf); |
| ... | ... | @@ -3096,22 +3150,39 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3096 | 3150 | } else coff.mf.update_prog_node.completeOne(); |
| 3097 | 3151 | } |
| 3098 | 3152 | while (coff.pending_members.pop()) |pending_mi| { |
| 3099 | | // TODO: Prog node |
| 3153 | const sub_prog_node = coff.idleProgNode( |
| 3154 | tid, |
| 3155 | coff.symbol_prog_node, |
| 3156 | coff.getNode(pending_mi.key.get(coff).content_ni), |
| 3157 | ); |
| 3158 | defer sub_prog_node.end(); |
| 3100 | 3159 | try coff.flushMember(pending_mi.key); |
| 3101 | 3160 | break :task; |
| 3102 | 3161 | } |
| 3162 | // TODO: This and the next task ideally only run once, as it's wasteful otherwise |
| 3103 | 3163 | if (coff.export_table.pending_sort) { |
| 3104 | | // TODO: Prog node |
| 3105 | | coff.export_table.pending_sort = false; |
| 3164 | defer coff.export_table.pending_sort = false; |
| 3165 | const sub_prog_node = coff.idleProgNode( |
| 3166 | tid, |
| 3167 | coff.synth_prog_node, |
| 3168 | coff.getNode(coff.export_table.ni), |
| 3169 | ); |
| 3170 | defer sub_prog_node.end(); |
| 3171 | |
| 3106 | 3172 | coff.flushExportsSort(); |
| 3107 | 3173 | break :task; |
| 3108 | 3174 | } |
| 3109 | | // TODO: This and the above task ideally run only once, as it's wasteful otherwise |
| 3110 | 3175 | if (coff.symbol_table.pending_shrink) { |
| 3111 | | coff.symbol_table.pending_shrink = false; |
| 3112 | | // TODO: Prog node |
| 3176 | defer coff.symbol_table.pending_shrink = false; |
| 3177 | const sub_prog_node = coff.idleProgNode( |
| 3178 | tid, |
| 3179 | coff.symbol_prog_node, |
| 3180 | coff.getNode(coff.symbol_table.ni), |
| 3181 | ); |
| 3182 | defer sub_prog_node.end(); |
| 3183 | |
| 3113 | 3184 | const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols); |
| 3114 | | Node.known.symbol_table.shrink( |
| 3185 | coff.symbol_table.ni.shrink( |
| 3115 | 3186 | &coff.mf, |
| 3116 | 3187 | comp.gpa, |
| 3117 | 3188 | number_of_symbols * std.coff.Symbol.sizeOf(), |
| ... | ... | @@ -3119,7 +3190,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3119 | 3190 | ) catch |err| switch (err) { |
| 3120 | 3191 | error.OutOfMemory => return error.OutOfMemory, |
| 3121 | 3192 | else => |e| return comp.link_diags.fail( |
| 3122 | | "linker failed to shrink symbol table: {t}", |
| 3193 | "linker failed to compact symbol table: {t}", |
| 3123 | 3194 | .{e}, |
| 3124 | 3195 | ), |
| 3125 | 3196 | }; |
| ... | ... | @@ -3129,6 +3200,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool { |
| 3129 | 3200 | } |
| 3130 | 3201 | if (coff.pending_uavs.count() > 0) return true; |
| 3131 | 3202 | if (coff.globals.count() > coff.global_pending_index) return true; |
| 3203 | if (coff.symbol_table.pending.count() > 0) return true; |
| 3132 | 3204 | for (&coff.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; |
| 3133 | 3205 | if (coff.mf.updates.items.len > 0) return true; |
| 3134 | 3206 | if (coff.pending_members.count() > 0) return true; |
| ... | ... | @@ -3159,6 +3231,7 @@ fn idleProgNode( |
| 3159 | 3231 | .tid = tid, |
| 3160 | 3232 | }), |
| 3161 | 3233 | }) catch &name, |
| 3234 | .archive_member => |mi| &mi.get(coff).headerPtr(coff).name, |
| 3162 | 3235 | }, 0); |
| 3163 | 3236 | } |
| 3164 | 3237 | |
| ... | ... | @@ -3182,6 +3255,7 @@ fn flushUav( |
| 3182 | 3255 | .{ .read = true }, |
| 3183 | 3256 | )).symbol(coff); |
| 3184 | 3257 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 3258 | if (!isImage(coff)) try coff.symbol_table.pending.ensureUnusedCapacity(gpa, 1); |
| 3185 | 3259 | const sym = si.get(coff); |
| 3186 | 3260 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 3187 | 3261 | .alignment = uav_align.toStdMem(), |
| ... | ... | @@ -3200,8 +3274,8 @@ fn flushUav( |
| 3200 | 3274 | const sym = si.get(coff); |
| 3201 | 3275 | assert(sym.loc_relocs == .none); |
| 3202 | 3276 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 3203 | | if (sym.target_relocs != .none) |
| 3204 | | _ = try coff.updateSymbolTableEntry(si); |
| 3277 | if (!isImage(coff) and sym.target_relocs != .none) |
| 3278 | try coff.pendingSymbolTableEntry(si); |
| 3205 | 3279 | |
| 3206 | 3280 | break :ni sym.ni; |
| 3207 | 3281 | }; |
| ... | ... | @@ -3232,7 +3306,8 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void { |
| 3232 | 3306 | |
| 3233 | 3307 | if (!coff.isImage()) { |
| 3234 | 3308 | const si = gmi.symbol(coff); |
| 3235 | | assert(try coff.updateSymbolTableEntry(si) != .none); |
| 3309 | try coff.pendingSymbolTableEntry(si); |
| 3310 | |
| 3236 | 3311 | if (si.get(coff).ni != .none) |
| 3237 | 3312 | try coff.ensureMemberSymbol( |
| 3238 | 3313 | gn.name, |
| ... | ... | @@ -3429,6 +3504,9 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void { |
| 3429 | 3504 | } |
| 3430 | 3505 | assert(sym.loc_relocs == .none); |
| 3431 | 3506 | sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 3507 | if (!isImage(coff) and sym.target_relocs != .none) |
| 3508 | try coff.pendingSymbolTableEntry(si); |
| 3509 | |
| 3432 | 3510 | break :ni sym.ni; |
| 3433 | 3511 | }; |
| 3434 | 3512 | |
| ... | ... | @@ -3464,15 +3542,20 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3464 | 3542 | .data_directories, |
| 3465 | 3543 | .section_table, |
| 3466 | 3544 | .placeholder, |
| 3467 | | .symbol_table_entry, // TODO: Need to impl this for symbol table updates to work? |
| 3468 | | .string_table, |
| 3469 | | => if (!coff.isArchive()) unreachable, |
| 3545 | => if (coff.isImage()) unreachable, |
| 3470 | 3546 | .symbol_table => { |
| 3471 | 3547 | coff.targetStore( |
| 3472 | 3548 | &coff.headerPtr().pointer_to_symbol_table, |
| 3473 | 3549 | @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]), |
| 3474 | 3550 | ); |
| 3475 | 3551 | }, |
| 3552 | .string_table => { |
| 3553 | if (!coff.symbol_table.pending_shrink) { |
| 3554 | const symbol_table_loc, const symbol_table_size = coff.symbol_table.ni.location(&coff.mf).resolve(&coff.mf); |
| 3555 | const string_table_offset, _ = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf); |
| 3556 | coff.symbol_table.pending_shrink = string_table_offset - (symbol_table_loc + symbol_table_size) > 0; |
| 3557 | } |
| 3558 | }, |
| 3476 | 3559 | .relocation_table => |sn| { |
| 3477 | 3560 | coff.targetStore( |
| 3478 | 3561 | &sn.header(coff).pointer_to_relocations, |
| ... | ... | @@ -3621,7 +3704,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3621 | 3704 | } |
| 3622 | 3705 | |
| 3623 | 3706 | fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3624 | | _, const size = ni.location(&coff.mf).resolve(&coff.mf); |
| 3707 | const offset, const size = ni.location(&coff.mf).resolve(&coff.mf); |
| 3625 | 3708 | log.debug("flushResized({s}, 0x{x})", .{ @tagName(coff.getNode(ni)), size }); |
| 3626 | 3709 | |
| 3627 | 3710 | switch (coff.getNode(ni)) { |
| ... | ... | @@ -3657,7 +3740,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3657 | 3740 | .archive_member => |mi| { |
| 3658 | 3741 | const content_ni = mi.get(coff).content_ni; |
| 3659 | 3742 | const next_ni = content_ni.next(&coff.mf); |
| 3660 | | const offset, _ = content_ni.location(&coff.mf).resolve(&coff.mf); |
| 3743 | const content_offset, _ = content_ni.location(&coff.mf).resolve(&coff.mf); |
| 3661 | 3744 | const next_offset = switch (next_ni) { |
| 3662 | 3745 | .none => offset: { |
| 3663 | 3746 | assert(content_ni.parent(&coff.mf) == Node.known.file); |
| ... | ... | @@ -3672,15 +3755,22 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3672 | 3755 | }; |
| 3673 | 3756 | |
| 3674 | 3757 | // Not inserting IMAGE_ARCHIVE_PAD `\n` byte here, because we are expanding to full size |
| 3675 | | Member.storeHeaderDecimalStr(&mi.get(coff).headerPtr(coff).size, next_offset - offset); |
| 3758 | Member.storeHeaderDecimalStr(&mi.get(coff).headerPtr(coff).size, next_offset - content_offset); |
| 3676 | 3759 | }, |
| 3677 | 3760 | .coff_header, |
| 3678 | 3761 | .optional_header, |
| 3679 | 3762 | .data_directories, |
| 3680 | 3763 | => unreachable, |
| 3681 | 3764 | .section_table => {}, |
| 3682 | | .symbol_table => assert(!coff.isImage()), |
| 3683 | | .symbol_table_entry => unreachable, |
| 3765 | .symbol_table => { |
| 3766 | assert(!coff.isImage()); |
| 3767 | if (!coff.symbol_table.pending_shrink) { |
| 3768 | const string_table_offset, _ = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf); |
| 3769 | coff.symbol_table.pending_shrink = |
| 3770 | size > coff.targetLoad(&coff.headerPtr().number_of_symbols) * std.coff.Symbol.sizeOf() or |
| 3771 | string_table_offset - (offset + size) > 0; |
| 3772 | } |
| 3773 | }, |
| 3684 | 3774 | .string_table => { |
| 3685 | 3775 | assert(!coff.isImage()); |
| 3686 | 3776 | coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size)); |
| ... | ... | @@ -3904,17 +3994,18 @@ fn updateExportsInner( |
| 3904 | 3994 | export_sym.rva = exported_sym.rva; |
| 3905 | 3995 | export_sym.size = exported_sym.size; |
| 3906 | 3996 | export_sym.section_number = exported_sym.section_number; |
| 3907 | | export_si.applyTargetRelocs(coff); |
| 3908 | | if (@"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) { |
| 3909 | | coff.optionalHeaderStandardPtr().address_of_entry_point = exported_sym.rva; |
| 3910 | | } else if (@"export".opts.name.eqlSlice("_tls_used", ip)) { |
| 3911 | | const tls_directory = coff.dataDirectoryPtr(.TLS); |
| 3912 | | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.size }; |
| 3913 | | if (coff.targetEndian() != native_endian) |
| 3914 | | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| 3915 | | } |
| 3916 | | |
| 3917 | | if (coff.export_table.ni == .none) continue; |
| 3997 | defer export_si.applyTargetRelocs(coff); |
| 3998 | |
| 3999 | if (isImage(coff)) { |
| 4000 | if (@"export".opts.name.eqlSlice("wWinMainCRTStartup", ip)) { |
| 4001 | coff.optionalHeaderStandardPtr().address_of_entry_point = exported_sym.rva; |
| 4002 | } else if (@"export".opts.name.eqlSlice("_tls_used", ip)) { |
| 4003 | const tls_directory = coff.dataDirectoryPtr(.TLS); |
| 4004 | tls_directory.* = .{ .virtual_address = exported_sym.rva, .size = exported_sym.size }; |
| 4005 | if (coff.targetEndian() != native_endian) |
| 4006 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| 4007 | } |
| 4008 | } else continue; |
| 3918 | 4009 | |
| 3919 | 4010 | const entries_ctx = ExportTable.Adapter{ .coff = coff }; |
| 3920 | 4011 | const gop = try coff.export_table.entries.getOrPutAdapted( |
| ... | ... | @@ -4002,7 +4093,6 @@ fn updateExportsInner( |
| 4002 | 4093 | gop.value_ptr.si = export_si; |
| 4003 | 4094 | const reloc = gop.value_ptr.*.export_address_table_ri.get(coff); |
| 4004 | 4095 | reloc.target = export_si; |
| 4005 | | export_si.applyTargetRelocs(coff); // TODO: Potentially doing this twice, defer first one? |
| 4006 | 4096 | } |
| 4007 | 4097 | } |
| 4008 | 4098 | } |