authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:34-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:22:41-04:00
logf81bd30057d6a1d1d50851b65a644aa86296cd4c
tree0837dfb5cf66bfbc0e7af3d5a2bed7a172bcc871
parente7d452338c07fd1c8469ae78ed28451ee43089dc

Coff: Symbol table output


3 files changed, 393 insertions(+), 56 deletions(-)

lib/std/coff.zig+9-9
...@@ -658,7 +658,7 @@ pub const SectionHeader = extern struct {...@@ -658,7 +658,7 @@ pub const SectionHeader = extern struct {
658 };658 };
659};659};
660660
661pub const Symbol = struct {661pub const Symbol = extern struct {
662 name: [8]u8,662 name: [8]u8,
663 value: u32,663 value: u32,
664 section_number: SectionNumber,664 section_number: SectionNumber,
...@@ -683,18 +683,18 @@ pub const Symbol = struct {...@@ -683,18 +683,18 @@ pub const Symbol = struct {
683 }683 }
684};684};
685685
686pub const SectionNumber = enum(u16) {686pub const SectionNumber = enum(i16) {
687 /// The symbol record is not yet assigned a section.687 /// The symbol record is not yet assigned a section.
688 /// A value of zero indicates that a reference to an external symbol is defined elsewhere.688 /// A value of zero indicates that a reference to an external symbol is defined elsewhere.
689 /// A value of non-zero is a common symbol with a size that is specified by the value.689 /// A value of non-zero is a common symbol with a size that is specified by the value.
690 UNDEFINED = 0,690 UNDEFINED = 0,
691691
692 /// The symbol has an absolute (non-relocatable) value and is not an address.692 /// The symbol has an absolute (non-relocatable) value and is not an address.
693 ABSOLUTE = 0xffff,693 ABSOLUTE = -1,
694694
695 /// The symbol provides general type or debugging information but does not correspond to a section.695 /// The symbol provides general type or debugging information but does not correspond to a section.
696 /// Microsoft tools use this setting along with .file records (storage class FILE).696 /// Microsoft tools use this setting along with .file records (storage class FILE).
697 DEBUG = 0xfffe,697 DEBUG = -2,
698 _,698 _,
699};699};
700700
...@@ -866,7 +866,7 @@ pub const StorageClass = enum(u8) {...@@ -866,7 +866,7 @@ pub const StorageClass = enum(u8) {
866 _,866 _,
867};867};
868868
869pub const FunctionDefinition = struct {869pub const FunctionDefinition = extern struct {
870 /// The symbol-table index of the corresponding .bf (begin function) symbol record.870 /// The symbol-table index of the corresponding .bf (begin function) symbol record.
871 tag_index: u32,871 tag_index: u32,
872872
...@@ -885,7 +885,7 @@ pub const FunctionDefinition = struct {...@@ -885,7 +885,7 @@ pub const FunctionDefinition = struct {
885 unused: [2]u8,885 unused: [2]u8,
886};886};
887887
888pub const SectionDefinition = struct {888pub const SectionDefinition = extern struct {
889 /// The size of section data; the same as SizeOfRawData in the section header.889 /// The size of section data; the same as SizeOfRawData in the section header.
890 length: u32,890 length: u32,
891891
...@@ -907,7 +907,7 @@ pub const SectionDefinition = struct {...@@ -907,7 +907,7 @@ pub const SectionDefinition = struct {
907 unused: [3]u8,907 unused: [3]u8,
908};908};
909909
910pub const FileDefinition = struct {910pub const FileDefinition = extern struct {
911 /// An ANSI string that gives the name of the source file.911 /// An ANSI string that gives the name of the source file.
912 /// This is padded with nulls if it is less than the maximum length.912 /// This is padded with nulls if it is less than the maximum length.
913 file_name: [18]u8,913 file_name: [18]u8,
...@@ -918,7 +918,7 @@ pub const FileDefinition = struct {...@@ -918,7 +918,7 @@ pub const FileDefinition = struct {
918 }918 }
919};919};
920920
921pub const WeakExternalDefinition = struct {921pub const WeakExternalDefinition = extern struct {
922 /// The symbol-table index of sym2, the symbol to be linked if sym1 is not found.922 /// The symbol-table index of sym2, the symbol to be linked if sym1 is not found.
923 tag_index: u32,923 tag_index: u32,
924924
...@@ -977,7 +977,7 @@ pub const ComdatSelection = enum(u8) {...@@ -977,7 +977,7 @@ pub const ComdatSelection = enum(u8) {
977 _,977 _,
978};978};
979979
980pub const DebugInfoDefinition = struct {980pub const DebugInfoDefinition = extern struct {
981 unused_1: [4]u8,981 unused_1: [4]u8,
982982
983 /// The actual ordinal line number (1, 2, 3, and so on) within the source file, corresponding to the .bf or .ef record.983 /// The actual ordinal line number (1, 2, 3, and so on) within the source file, corresponding to the .bf or .ef record.
src/libs/mingw/implib.zig+1-1
...@@ -1012,7 +1012,7 @@ fn getShortImport(...@@ -1012,7 +1012,7 @@ fn getShortImport(
1012fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void {1012fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void {
1013 try writer.writeAll(&symbol.name);1013 try writer.writeAll(&symbol.name);
1014 try writer.writeInt(u32, symbol.value, .little);1014 try writer.writeInt(u32, symbol.value, .little);
1015 try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little);1015 try writer.writeInt(i16, @intFromEnum(symbol.section_number), .little);
1016 try writer.writeInt(u8, @intFromEnum(symbol.type.base_type), .little);1016 try writer.writeInt(u8, @intFromEnum(symbol.type.base_type), .little);
1017 try writer.writeInt(u8, @intFromEnum(symbol.type.complex_type), .little);1017 try writer.writeInt(u8, @intFromEnum(symbol.type.complex_type), .little);
1018 try writer.writeInt(u8, @intFromEnum(symbol.storage_class), .little);1018 try writer.writeInt(u8, @intFromEnum(symbol.storage_class), .little);
src/link/Coff.zig+383-46
...@@ -30,6 +30,7 @@ lib_string_len: u64,...@@ -30,6 +30,7 @@ lib_string_len: u64,
30long_names_table: LongNamesTable,30long_names_table: LongNamesTable,
31import_table: ImportTable,31import_table: ImportTable,
32export_table: ExportTable,32export_table: ExportTable,
33symbol_table: SymbolTable,
33strings: std.HashMapUnmanaged(34strings: std.HashMapUnmanaged(
34 u32,35 u32,
35 void,36 void,
...@@ -37,10 +38,10 @@ strings: std.HashMapUnmanaged(...@@ -37,10 +38,10 @@ strings: std.HashMapUnmanaged(
37 std.hash_map.default_max_load_percentage,38 std.hash_map.default_max_load_percentage,
38),39),
39string_bytes: std.ArrayList(u8),40string_bytes: std.ArrayList(u8),
40image_section_table: std.ArrayList(Symbol.Index),41section_table: std.ArrayList(Symbol.Index),
41pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index),42pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index),
42object_section_table: std.array_hash_map.Auto(String, Symbol.Index),43object_section_table: std.array_hash_map.Auto(String, Symbol.Index),
43symbol_table: std.ArrayList(Symbol),44symbols: std.ArrayList(Symbol),
44globals: std.array_hash_map.Auto(GlobalName, Symbol.Index),45globals: std.array_hash_map.Auto(GlobalName, Symbol.Index),
45global_pending_index: u32,46global_pending_index: u32,
46navs: std.array_hash_map.Auto(InternPool.Nav.Index, Symbol.Index),47navs: std.array_hash_map.Auto(InternPool.Nav.Index, Symbol.Index),
...@@ -144,6 +145,7 @@ pub const Node = union(enum) {...@@ -144,6 +145,7 @@ pub const Node = union(enum) {
144 header,145 header,
145 /// Images and archives only.146 /// Images and archives only.
146 signature,147 signature,
148
147 /// Archives only.149 /// Archives only.
148 archive_member_header: Member.Index,150 archive_member_header: Member.Index,
149 archive_member: Member.Index,151 archive_member: Member.Index,
...@@ -154,15 +156,21 @@ pub const Node = union(enum) {...@@ -154,15 +156,21 @@ pub const Node = union(enum) {
154 /// Image only156 /// Image only
155 data_directories,157 data_directories,
156 section_table,158 section_table,
157 image_section: Symbol.Index,159 // Archives and objects only
160 symbol_table,
161 symbol_table_entry,
162 // Archives and objects only
163 string_table,
164
165 image_section: Symbol.Index, // TODO: image_section -> section
158166
159 /// Only images contain imports167 /// Images only
160 import_directory_table,168 import_directory_table,
161 import_lookup_table: ImportTable.Index,169 import_lookup_table: ImportTable.Index,
162 import_address_table: ImportTable.Index,170 import_address_table: ImportTable.Index,
163 import_hint_name_table: ImportTable.Index,171 import_hint_name_table: ImportTable.Index,
164172
165 /// Only images contain exports173 /// Images only
166 export_directory_table,174 export_directory_table,
167 export_address_table,175 export_address_table,
168 export_name_pointer_table,176 export_name_pointer_table,
...@@ -291,6 +299,8 @@ pub const Node = union(enum) {...@@ -291,6 +299,8 @@ pub const Node = union(enum) {
291 optional_header,299 optional_header,
292 data_directories,300 data_directories,
293 section_table,301 section_table,
302 symbol_table,
303 string_table,
294 };304 };
295 var mut_known: std.enums.EnumFieldStruct(Known, MappedFile.Node.Index, null) = undefined;305 var mut_known: std.enums.EnumFieldStruct(Known, MappedFile.Node.Index, null) = undefined;
296 const info = @typeInfo(Known).@"enum";306 const info = @typeInfo(Known).@"enum";
...@@ -436,6 +446,47 @@ pub const LongNamesTable = struct {...@@ -436,6 +446,47 @@ pub const LongNamesTable = struct {
436 };446 };
437};447};
438448
449pub const SymbolTable = struct {
450 string_offsets: std.AutoArrayHashMapUnmanaged(String, StringIndex),
451 entries: std.AutoArrayHashMapUnmanaged(Symbol.Index, Entry),
452
453 // Adding nodes to the symbol table has the result of accumulating padding
454 // between the last symbol and the string table, due to the growth factor
455 // in MappedFile. The spec requires the string table begin immediately
456 // after the last symbol, so we compact the symbol table node if needed.
457 pending_shrink: bool,
458
459 pub const Entry = struct {
460 entry_si: Symbol.Index,
461 index: Index,
462 };
463
464 pub const Add = union(enum) {
465 section,
466 global: struct {
467 import: bool,
468 },
469 };
470
471 pub const SymbolName = union(enum) {
472 short: []const u8,
473 long: StringIndex,
474 };
475
476 // Symbol.Index does not map 1:1 with SymbolTable.Index due to auxiliary entries
477 pub const Index = enum(u32) {
478 _,
479
480 pub fn get(sti: SymbolTable.Index, coff: *Coff) *Entry {
481 return &coff.symbol_table.entries.values()[@intFromEnum(sti)];
482 }
483 };
484
485 pub const StringIndex = enum(u32) {
486 _,
487 };
488};
489
439pub const ExportTable = struct {490pub const ExportTable = struct {
440 ni: MappedFile.Node.Index,491 ni: MappedFile.Node.Index,
441 export_directory_table_ni: MappedFile.Node.Index,492 export_directory_table_ni: MappedFile.Node.Index,
...@@ -582,7 +633,7 @@ pub const Symbol = struct {...@@ -582,7 +633,7 @@ pub const Symbol = struct {
582 }633 }
583634
584 pub fn symbol(sn: SectionNumber, coff: *const Coff) Symbol.Index {635 pub fn symbol(sn: SectionNumber, coff: *const Coff) Symbol.Index {
585 return coff.image_section_table.items[sn.toIndex()];636 return coff.section_table.items[sn.toIndex()];
586 }637 }
587638
588 pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader {639 pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader {
...@@ -600,7 +651,7 @@ pub const Symbol = struct {...@@ -600,7 +651,7 @@ pub const Symbol = struct {
600 const known_count = @typeInfo(Index).@"enum".field_names.len;651 const known_count = @typeInfo(Index).@"enum".field_names.len;
601652
602 pub fn get(si: Symbol.Index, coff: *Coff) *Symbol {653 pub fn get(si: Symbol.Index, coff: *Coff) *Symbol {
603 return &coff.symbol_table.items[@intFromEnum(si)];654 return &coff.symbols.items[@intFromEnum(si)];
604 }655 }
605656
606 pub fn node(si: Symbol.Index, coff: *Coff) MappedFile.Node.Index {657 pub fn node(si: Symbol.Index, coff: *Coff) MappedFile.Node.Index {
...@@ -920,12 +971,17 @@ fn create(...@@ -920,12 +971,17 @@ fn create(
920 .name_table_ni = .none,971 .name_table_ni = .none,
921 .entries = .empty,972 .entries = .empty,
922 },973 },
974 .symbol_table = .{
975 .string_offsets = .empty,
976 .entries = .empty,
977 .pending_shrink = false,
978 },
923 .strings = .empty,979 .strings = .empty,
924 .string_bytes = .empty,980 .string_bytes = .empty,
925 .image_section_table = .empty,981 .section_table = .empty,
926 .pseudo_section_table = .empty,982 .pseudo_section_table = .empty,
927 .object_section_table = .empty,983 .object_section_table = .empty,
928 .symbol_table = .empty,984 .symbols = .empty,
929 .globals = .empty,985 .globals = .empty,
930 .global_pending_index = 0,986 .global_pending_index = 0,
931 .navs = .empty,987 .navs = .empty,
...@@ -965,15 +1021,16 @@ pub fn deinit(coff: *Coff) void {...@@ -965,15 +1021,16 @@ pub fn deinit(coff: *Coff) void {
965 const gpa = coff.base.comp.gpa;1021 const gpa = coff.base.comp.gpa;
966 coff.mf.deinit(gpa);1022 coff.mf.deinit(gpa);
967 coff.nodes.deinit(gpa);1023 coff.nodes.deinit(gpa);
1024 // TODO: Update this
968 coff.long_names_table.entries.deinit(gpa);1025 coff.long_names_table.entries.deinit(gpa);
969 coff.import_table.entries.deinit(gpa);1026 coff.import_table.entries.deinit(gpa);
970 coff.export_table.entries.deinit(gpa);1027 coff.export_table.entries.deinit(gpa);
971 coff.strings.deinit(gpa);1028 coff.strings.deinit(gpa);
972 coff.string_bytes.deinit(gpa);1029 coff.string_bytes.deinit(gpa);
973 coff.image_section_table.deinit(gpa);1030 coff.section_table.deinit(gpa);
974 coff.pseudo_section_table.deinit(gpa);1031 coff.pseudo_section_table.deinit(gpa);
975 coff.object_section_table.deinit(gpa);1032 coff.object_section_table.deinit(gpa);
976 coff.symbol_table.deinit(gpa);1033 coff.symbols.deinit(gpa);
977 coff.globals.deinit(gpa);1034 coff.globals.deinit(gpa);
978 coff.navs.deinit(gpa);1035 coff.navs.deinit(gpa);
979 coff.uavs.deinit(gpa);1036 coff.uavs.deinit(gpa);
...@@ -1035,8 +1092,13 @@ fn initHeaders(...@@ -1035,8 +1092,13 @@ fn initHeaders(
10351092
1036 var expected_nodes_len: usize = Node.known_count;1093 var expected_nodes_len: usize = Node.known_count;
1037 if (comp.zcu != null) {1094 if (comp.zcu != null) {
1095 // Section nodes
1038 expected_nodes_len += 3;1096 expected_nodes_len += 3;
1097 // Symbol table nodes
1098 if (is_archive) expected_nodes_len += 6;
1099 // Pseudo-sections and import / export table nodes
1039 if (is_image) expected_nodes_len += 9;1100 if (is_image) expected_nodes_len += 9;
1101 // TLS section nodes
1040 expected_nodes_len += @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2;1102 expected_nodes_len += @as(usize, @intFromBool(comp.config.any_non_single_threaded)) * 2;
1041 }1103 }
1042 defer assert(coff.nodes.len == expected_nodes_len);1104 defer assert(coff.nodes.len == expected_nodes_len);
...@@ -1294,10 +1356,26 @@ fn initHeaders(...@@ -1294,10 +1356,26 @@ fn initHeaders(
1294 }));1356 }));
1295 coff.nodes.appendAssumeCapacity(.section_table);1357 coff.nodes.appendAssumeCapacity(.section_table);
12961358
1359 const symbol_table_ni = Node.known.symbol_table;
1360 assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{
1361 .alignment = .@"4",
1362 .fixed = true,
1363 .moved = true,
1364 }));
1365 coff.nodes.appendAssumeCapacity(.symbol_table);
1366
1367 const string_table_ni = Node.known.string_table;
1368 assert(string_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{
1369 .size = @sizeOf(u32),
1370 .fixed = true,
1371 .resized = true,
1372 }));
1373 coff.nodes.appendAssumeCapacity(.string_table);
1374
1297 assert(coff.nodes.len == Node.known_count);1375 assert(coff.nodes.len == Node.known_count);
12981376
1299 try coff.symbol_table.ensureTotalCapacity(gpa, Symbol.Index.known_count);1377 try coff.symbols.ensureTotalCapacity(gpa, Symbol.Index.known_count);
1300 coff.symbol_table.addOneAssumeCapacity().* = .{1378 coff.symbols.addOneAssumeCapacity().* = .{
1301 .ni = .none,1379 .ni = .none,
1302 .rva = 0,1380 .rva = 0,
1303 .size = 0,1381 .size = 0,
...@@ -1360,7 +1438,7 @@ fn initHeaders(...@@ -1360,7 +1438,7 @@ fn initHeaders(
1360 });1438 });
1361 coff.nodes.appendAssumeCapacity(.export_address_table);1439 coff.nodes.appendAssumeCapacity(.export_address_table);
13621440
1363 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);1441 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1364 coff.export_table.export_address_table_si = coff.addSymbolAssumeCapacity();1442 coff.export_table.export_address_table_si = coff.addSymbolAssumeCapacity();
13651443
1366 const export_address_table_sym = coff.export_table.export_address_table_si.get(coff);1444 const export_address_table_sym = coff.export_table.export_address_table_si.get(coff);
...@@ -1451,6 +1529,10 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {...@@ -1451,6 +1529,10 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
1451 .section_table,1529 .section_table,
1452 .export_name_table,1530 .export_name_table,
1453 .placeholder,1531 .placeholder,
1532
1533 .symbol_table,
1534 .symbol_table_entry,
1535 .string_table,
1454 => unreachable,1536 => unreachable,
1455 .image_section => |si| si,1537 .image_section => |si| si,
1456 .import_directory_table => break :parent_rva coff.targetLoad(1538 .import_directory_table => break :parent_rva coff.targetLoad(
...@@ -1632,7 +1714,28 @@ pub fn dataDirectoryPtr(...@@ -1632,7 +1714,28 @@ pub fn dataDirectoryPtr(
1632}1714}
16331715
1634pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {1716pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {
1635 return @ptrCast(@alignCast(Node.known.section_table.slice(&coff.mf)));1717 return @ptrCast(@alignCast(
1718 Node.known.section_table.slice(&coff.mf)[0 .. coff.section_table.items.len * @sizeOf(std.coff.SectionHeader)],
1719 ));
1720}
1721
1722pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) *align(2) std.coff.Symbol {
1723 return @ptrCast(@alignCast(
1724 &Node.known.symbol_table.slice(&coff.mf)[@intFromEnum(sti) * std.coff.Symbol.sizeOf()],
1725 ));
1726}
1727
1728pub fn symbolAuxSectionDefinitionPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition {
1729 const sti = coff.symbol_table.entries.get(si).?.index;
1730
1731 const symbol = coff.symbolTableEntryPtr(sti);
1732 assert(symbol.storage_class == .STATIC and symbol.number_of_aux_symbols == 1);
1733
1734 return @ptrCast(symbolTableEntryPtr(coff, @enumFromInt(@intFromEnum(sti) + 1)));
1735}
1736
1737pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 {
1738 return @ptrCast(@alignCast(Node.known.string_table.slice(&coff.mf)[0..@sizeOf(u32)]));
1636}1739}
16371740
1638pub fn importDirectoryTableSlice(coff: *Coff) []std.coff.ImportDirectoryEntry {1741pub fn importDirectoryTableSlice(coff: *Coff) []std.coff.ImportDirectoryEntry {
...@@ -1662,7 +1765,7 @@ pub fn exportOrdinalTableSlice(coff: *Coff) []std.coff.ExportOrdinalTableEntry {...@@ -1662,7 +1765,7 @@ pub fn exportOrdinalTableSlice(coff: *Coff) []std.coff.ExportOrdinalTableEntry {
1662}1765}
16631766
1664fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {1767fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
1665 defer coff.symbol_table.addOneAssumeCapacity().* = .{1768 defer coff.symbols.addOneAssumeCapacity().* = .{
1666 .ni = .none,1769 .ni = .none,
1667 .rva = 0,1770 .rva = 0,
1668 .size = 0,1771 .size = 0,
...@@ -1670,7 +1773,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -1670,7 +1773,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
1670 .target_relocs = .none,1773 .target_relocs = .none,
1671 .section_number = .UNDEFINED,1774 .section_number = .UNDEFINED,
1672 };1775 };
1673 return @enumFromInt(coff.symbol_table.items.len);1776 return @enumFromInt(coff.symbols.items.len);
1674}1777}
16751778
1676fn initSymbolAssumeCapacity(coff: *Coff) !Symbol.Index {1779fn initSymbolAssumeCapacity(coff: *Coff) !Symbol.Index {
...@@ -1715,7 +1818,7 @@ fn getOrPutGlobalSymbol(...@@ -1715,7 +1818,7 @@ fn getOrPutGlobalSymbol(
1715 lib_name: ?[]const u8,1818 lib_name: ?[]const u8,
1716) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult {1819) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult {
1717 const gpa = coff.base.comp.gpa;1820 const gpa = coff.base.comp.gpa;
1718 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);1821 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1719 const sym_gop = try coff.globals.getOrPut(gpa, .{1822 const sym_gop = try coff.globals.getOrPut(gpa, .{
1720 .name = try coff.getOrPutString(name),1823 .name = try coff.getOrPutString(name),
1721 .lib_name = try coff.getOrPutOptionalString(lib_name),1824 .lib_name = try coff.getOrPutOptionalString(lib_name),
...@@ -1724,6 +1827,7 @@ fn getOrPutGlobalSymbol(...@@ -1724,6 +1827,7 @@ fn getOrPutGlobalSymbol(
1724 sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();1827 sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
1725 coff.synth_prog_node.increaseEstimatedTotalItems(1);1828 coff.synth_prog_node.increaseEstimatedTotalItems(1);
1726 }1829 }
1830
1727 return sym_gop;1831 return sym_gop;
1728}1832}
17291833
...@@ -1758,7 +1862,7 @@ fn navSection(...@@ -1758,7 +1862,7 @@ fn navSection(
1758}1862}
1759fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {1863fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {
1760 const gpa = zcu.gpa;1864 const gpa = zcu.gpa;
1761 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);1865 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1762 const sym_gop = try coff.navs.getOrPut(gpa, nav_index);1866 const sym_gop = try coff.navs.getOrPut(gpa, nav_index);
1763 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();1867 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
1764 return @enumFromInt(sym_gop.index);1868 return @enumFromInt(sym_gop.index);
...@@ -1776,7 +1880,7 @@ pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbo...@@ -1776,7 +1880,7 @@ pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbo
17761880
1777fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {1881fn uavMapIndex(coff: *Coff, uav_val: InternPool.Index) !Node.UavMapIndex {
1778 const gpa = coff.base.comp.gpa;1882 const gpa = coff.base.comp.gpa;
1779 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);1883 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1780 const sym_gop = try coff.uavs.getOrPut(gpa, uav_val);1884 const sym_gop = try coff.uavs.getOrPut(gpa, uav_val);
1781 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();1885 if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
1782 return @enumFromInt(sym_gop.index);1886 return @enumFromInt(sym_gop.index);
...@@ -1788,7 +1892,7 @@ pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {...@@ -1788,7 +1892,7 @@ pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {
17881892
1789pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {1893pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
1790 const gpa = coff.base.comp.gpa;1894 const gpa = coff.base.comp.gpa;
1791 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);1895 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1792 const sym_gop = try coff.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);1896 const sym_gop = try coff.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
1793 if (!sym_gop.found_existing) {1897 if (!sym_gop.found_existing) {
1794 sym_gop.value_ptr.* = try coff.initSymbolAssumeCapacity();1898 sym_gop.value_ptr.* = try coff.initSymbolAssumeCapacity();
...@@ -2004,13 +2108,185 @@ fn addMemberSymbol(...@@ -2004,13 +2108,185 @@ fn addMemberSymbol(
2004 coff.pending_members.putAssumeCapacity(mi, {});2108 coff.pending_members.putAssumeCapacity(mi, {});
2005}2109}
20062110
2111fn addSymbolTableEntry(
2112 coff: *Coff,
2113 name: union(enum) {
2114 bytes: []const u8,
2115 string: String,
2116 },
2117 si: Symbol.Index,
2118 add: SymbolTable.Add,
2119) !void {
2120 assert(!coff.isImage());
2121 const gpa = coff.base.comp.gpa;
2122
2123 const string, const name_slice = switch (name) {
2124 .bytes => |bytes| .{ try coff.getOrPutString(bytes), bytes },
2125 .string => |s| .{ s, s.toSlice(coff) },
2126 };
2127
2128 const symbol_name: SymbolTable.SymbolName = if (name_slice.len > 8) index: {
2129 const string_gop = try coff.symbol_table.string_offsets.getOrPut(gpa, string);
2130 if (!string_gop.found_existing) {
2131 const string_index = Node.known.string_table.location(&coff.mf).resolve(&coff.mf)[1];
2132 string_gop.value_ptr.* = @enumFromInt(string_index);
2133
2134 try Node.known.string_table.resize(&coff.mf, gpa, string_index + name_slice.len + 1);
2135 const slice = Node.known.string_table.slice(&coff.mf);
2136 @memcpy(slice[string_index..][0..name_slice.len], name_slice);
2137 slice[string_index + name_slice.len] = 0;
2138 }
2139
2140 break :index .{ .long = string_gop.value_ptr.* };
2141 } else .{ .short = name_slice };
2142
2143 const symbol_index = coff.targetLoad(&coff.headerPtr().number_of_symbols);
2144 const symbols_added: u8 = switch (add) {
2145 .section => count: {
2146 const sym = si.get(coff);
2147
2148 try coff.nodes.ensureUnusedCapacity(gpa, 2);
2149 _ = try coff.addSymbolTableEntryAssumeCapacity(
2150 symbol_name,
2151 0,
2152 sym.section_number,
2153 .{
2154 .complex_type = .NULL,
2155 .base_type = .NULL,
2156 },
2157 .STATIC,
2158 1,
2159 );
2160
2161 // Aux entry ields are updated by flushMoved / flushResized
2162
2163 try coff.symbol_table.entries.put(gpa, si, .{
2164 .entry_si = .null,
2165 .index = @enumFromInt(symbol_index),
2166 });
2167
2168 break :count 2;
2169 },
2170 .global => |global| count: {
2171 const sym = si.get(coff);
2172
2173 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2174 try coff.symbols.ensureUnusedCapacity(gpa, 1);
2175
2176 const entry_ni = try coff.addSymbolTableEntryAssumeCapacity(
2177 symbol_name,
2178 if (global.import) 0 else coff.computeNodeSectionOffset(sym.ni),
2179 if (global.import) .UNDEFINED else sym.section_number,
2180 .{
2181 .base_type = .NULL,
2182 .complex_type = if (global.import or
2183 Symbol.Index.text.get(coff).section_number == sym.section_number)
2184 .FUNCTION
2185 else
2186 .NULL,
2187 },
2188 .EXTERNAL,
2189 0,
2190 );
2191
2192 const entry_si = coff.addSymbolAssumeCapacity();
2193 {
2194 const entry_sym = entry_si.get(coff);
2195 entry_sym.ni = entry_ni;
2196 assert(entry_sym.loc_relocs == .none);
2197 entry_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
2198 entry_sym.section_number = .UNDEFINED;
2199 }
2200
2201 try coff.addReloc(
2202 entry_si,
2203 @offsetOf(std.coff.Symbol, "value"),
2204 si,
2205 0,
2206 .{ .AMD64 = .SECREL },
2207 );
2208
2209 try coff.symbol_table.entries.put(gpa, si, .{
2210 .entry_si = entry_si,
2211 .index = @enumFromInt(symbol_index),
2212 });
2213
2214 break :count 1;
2215 },
2216 };
2217
2218 const new_num_symbols = symbol_index + symbols_added;
2219 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);
2220 coff.symbol_table.pending_shrink =
2221 Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf)[1] >
2222 new_num_symbols * std.coff.Symbol.sizeOf();
2223}
2224
2225/// Caller guarantees there is capacity for 1 + number_of_aux_symbols nodes.
2226/// Auxiliary nodes are zero-initialized.
2227fn addSymbolTableEntryAssumeCapacity(
2228 coff: *Coff,
2229 name: SymbolTable.SymbolName,
2230 value: u32,
2231 section_number: Symbol.SectionNumber,
2232 @"type": std.coff.SymType,
2233 storage_class: std.coff.StorageClass,
2234 number_of_aux_symbols: u8,
2235) !MappedFile.Node.Index {
2236 const gpa = coff.base.comp.gpa;
2237
2238 const entry_ni = try coff.mf.addLastChildNode(gpa, Node.known.symbol_table, .{
2239 .alignment = .@"2",
2240 .size = std.coff.Symbol.sizeOf(),
2241 .fixed = true,
2242 });
2243 coff.nodes.appendAssumeCapacity(.symbol_table_entry);
2244
2245 const entry: *align(2) std.coff.Symbol = @ptrCast(@alignCast(entry_ni.slice(&coff.mf)));
2246 entry.* = .{
2247 .name = undefined,
2248 .value = value,
2249 .section_number = @enumFromInt(@intFromEnum(section_number)),
2250 .type = @"type",
2251 .storage_class = storage_class,
2252 .number_of_aux_symbols = number_of_aux_symbols,
2253 };
2254
2255 switch (name) {
2256 .short => |s| {
2257 @memcpy(entry.name[0..s.len], s);
2258 @memset(entry.name[s.len..], 0);
2259 },
2260 .long => |l| {
2261 @memset(entry.name[0..4], 0);
2262 const offset_ptr: *align(2) u32 = @ptrCast(entry.name[4..]);
2263 coff.targetStore(offset_ptr, @intFromEnum(l));
2264 },
2265 }
2266
2267 if (coff.targetEndian() != native_endian)
2268 std.mem.byteSwapAllFields(std.coff.SectionHeader, entry.*);
2269
2270 for (0..number_of_aux_symbols) |_| {
2271 const aux_ni = try coff.mf.addLastChildNode(gpa, Node.known.symbol_table, .{
2272 .alignment = .@"2",
2273 .size = std.coff.Symbol.sizeOf(),
2274 .fixed = true,
2275 });
2276 coff.nodes.appendAssumeCapacity(.symbol_table_entry);
2277 @memset(aux_ni.slice(&coff.mf), 0);
2278 }
2279
2280 return entry_ni;
2281}
2282
2007fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index {2283fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index {
2008 assert(coff.base.comp.zcu != null);2284 assert(coff.base.comp.zcu != null);
20092285
2010 const gpa = coff.base.comp.gpa;2286 const gpa = coff.base.comp.gpa;
2011 try coff.nodes.ensureUnusedCapacity(gpa, 1);2287 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2012 try coff.image_section_table.ensureUnusedCapacity(gpa, 1);2288 try coff.section_table.ensureUnusedCapacity(gpa, 1);
2013 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);2289 try coff.symbols.ensureUnusedCapacity(gpa, 1);
20142290
2015 const coff_header = coff.headerPtr();2291 const coff_header = coff.headerPtr();
2016 const section_index = coff.targetLoad(&coff_header.number_of_sections);2292 const section_index = coff.targetLoad(&coff_header.number_of_sections);
...@@ -2022,19 +2298,19 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2022,19 +2298,19 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2022 @sizeOf(std.coff.SectionHeader) * section_table_len,2298 @sizeOf(std.coff.SectionHeader) * section_table_len,
2023 );2299 );
20242300
2025 const parent_ni, const alignment = if (coff.isArchive())2301 const parent_ni = if (coff.isArchive())
2026 .{ Node.known.zcu_member, .@"1" }2302 Node.known.zcu_member
2027 else2303 else
2028 .{ Node.known.file, coff.mf.flags.block_size };2304 Node.known.file;
20292305
2030 const ni = try coff.mf.addLastChildNode(gpa, parent_ni, .{2306 const ni = try coff.mf.addLastChildNode(gpa, parent_ni, .{
2031 .alignment = alignment,2307 .alignment = coff.mf.flags.block_size,
2032 .moved = true,2308 .moved = true,
2033 .bubbles_moved = false,2309 .bubbles_moved = false,
2034 });2310 });
20352311
2036 const si = coff.addSymbolAssumeCapacity();2312 const si = coff.addSymbolAssumeCapacity();
2037 coff.image_section_table.appendAssumeCapacity(si);2313 coff.section_table.appendAssumeCapacity(si);
2038 coff.nodes.appendAssumeCapacity(.{ .image_section = si });2314 coff.nodes.appendAssumeCapacity(.{ .image_section = si });
2039 const section_table = coff.sectionTableSlice();2315 const section_table = coff.sectionTableSlice();
20402316
...@@ -2042,7 +2318,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2042,7 +2318,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2042 const virtual_size = coff.optionalHeaderField(.section_alignment);2318 const virtual_size = coff.optionalHeaderField(.section_alignment);
2043 const rva: u32 = switch (section_index) {2319 const rva: u32 = switch (section_index) {
2044 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),2320 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),
2045 else => coff.image_section_table.items[section_index - 1].get(coff).rva +2321 else => coff.section_table.items[section_index - 1].get(coff).rva +
2046 coff.targetLoad(&section_table[section_index - 1].virtual_size),2322 coff.targetLoad(&section_table[section_index - 1].virtual_size),
2047 };2323 };
20482324
...@@ -2080,6 +2356,8 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2080,6 +2356,8 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2080 @intCast(rva + virtual_size),2356 @intCast(rva + virtual_size),
2081 ),2357 ),
2082 }2358 }
2359 } else {
2360 try coff.addSymbolTableEntry(.{ .bytes = name }, si, .section);
2083 }2361 }
20842362
2085 return si;2363 return si;
...@@ -2112,7 +2390,7 @@ fn pseudoSectionMapIndex(...@@ -2112,7 +2390,7 @@ fn pseudoSectionMapIndex(
2112 else2390 else
2113 .rdata;2391 .rdata;
2114 try coff.nodes.ensureUnusedCapacity(gpa, 1);2392 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2115 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);2393 try coff.symbols.ensureUnusedCapacity(gpa, 1);
2116 const ni = try coff.mf.addLastChildNode(gpa, parent.node(coff), .{ .alignment = alignment });2394 const ni = try coff.mf.addLastChildNode(gpa, parent.node(coff), .{ .alignment = alignment });
2117 const si = coff.addSymbolAssumeCapacity();2395 const si = coff.addSymbolAssumeCapacity();
2118 pseudo_section_gop.value_ptr.* = si;2396 pseudo_section_gop.value_ptr.* = si;
...@@ -2142,7 +2420,7 @@ fn objectSectionMapIndex(...@@ -2142,7 +2420,7 @@ fn objectSectionMapIndex(
2142 name_slice[0 .. std.mem.indexOfScalar(u8, name_slice, '$') orelse name_slice.len],2420 name_slice[0 .. std.mem.indexOfScalar(u8, name_slice, '$') orelse name_slice.len],
2143 ), alignment, attributes)).symbol(coff);2421 ), alignment, attributes)).symbol(coff);
2144 try coff.nodes.ensureUnusedCapacity(gpa, 1);2422 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2145 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);2423 try coff.symbols.ensureUnusedCapacity(gpa, 1);
2146 const parent_ni = parent.node(coff);2424 const parent_ni = parent.node(coff);
2147 var prev_ni: MappedFile.Node.Index = .none;2425 var prev_ni: MappedFile.Node.Index = .none;
2148 var next_it = parent_ni.children(&coff.mf);2426 var next_it = parent_ni.children(&coff.mf);
...@@ -2251,6 +2529,8 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -2251,6 +2529,8 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
2251 const sym = si.get(coff);2529 const sym = si.get(coff);
2252 sym.ni = ni;2530 sym.ni = ni;
2253 sym.section_number = sec_si.get(coff).section_number;2531 sym.section_number = sec_si.get(coff).section_number;
2532
2533 // TODO: Add symbol table entry
2254 },2534 },
2255 else => si.deleteLocationRelocs(coff),2535 else => si.deleteLocationRelocs(coff),
2256 }2536 }
...@@ -2506,11 +2786,6 @@ pub fn flush(...@@ -2506,11 +2786,6 @@ pub fn flush(
2506 _ = prog_node;2786 _ = prog_node;
2507 while (try coff.idle(tid)) {}2787 while (try coff.idle(tid)) {}
25082788
2509 // TODO: Second linker member symbol tables are built here
2510 if (isArchive(coff)) {
2511 //Member.Index.second.get(coff).content_ni;
2512 }
2513
2514 const comp = coff.base.comp;2789 const comp = coff.base.comp;
25152790
2516 // Implib generation should instead be done via building a MappedFile progressively2791 // Implib generation should instead be done via building a MappedFile progressively
...@@ -2634,6 +2909,26 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -2634,6 +2909,26 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
2634 coff.flushExportsSort();2909 coff.flushExportsSort();
2635 break :task;2910 break :task;
2636 }2911 }
2912 // TODO: This and the above task ideally run only once, as it's wasteful otherwise
2913 if (coff.symbol_table.pending_shrink) {
2914 coff.symbol_table.pending_shrink = false;
2915 // TODO: Prog node
2916 const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
2917 Node.known.symbol_table.shrink(
2918 &coff.mf,
2919 comp.gpa,
2920 number_of_symbols * std.coff.Symbol.sizeOf(),
2921 true,
2922 ) catch |err| switch (err) {
2923 error.OutOfMemory => return error.OutOfMemory,
2924 else => |e| return comp.link_diags.fail(
2925 "linker failed to shrink symbol table: {t}",
2926 .{e},
2927 ),
2928 };
2929
2930 break :task;
2931 }
2637 }2932 }
2638 if (coff.pending_uavs.count() > 0) return true;2933 if (coff.pending_uavs.count() > 0) return true;
2639 if (coff.globals.count() > coff.global_pending_index) return true;2934 if (coff.globals.count() > coff.global_pending_index) return true;
...@@ -2641,6 +2936,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -2641,6 +2936,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
2641 if (coff.mf.updates.items.len > 0) return true;2936 if (coff.mf.updates.items.len > 0) return true;
2642 if (coff.pending_members.count() > 0) return true;2937 if (coff.pending_members.count() > 0) return true;
2643 if (coff.export_table.pending_sort) return true;2938 if (coff.export_table.pending_sort) return true;
2939 if (coff.symbol_table.pending_shrink) return true;
2644 return false;2940 return false;
2645}2941}
26462942
...@@ -2733,14 +3029,28 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {...@@ -2733,14 +3029,28 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {
2733 const gpa = zcu.gpa;3029 const gpa = zcu.gpa;
2734 const gn = gmi.globalName(coff);3030 const gn = gmi.globalName(coff);
27353031
2736 // TODO: We still need to emit a reloc for the __imp_Name symbol?3032 if (!coff.isImage()) {
3033 // TODO: What about data imports?
3034
3035 // const si = gmi.symbol(coff);
3036 // const sym = si.get(coff);
3037 // sym.section_number = Symbol.Index.text.get(coff).section_number;
3038 // assert(sym.loc_relocs == .none);
3039 // sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
3040 //
3041 // try coff.addSymbolTableEntry(
3042 // .{ .bytes = gn.name.toSlice(coff) },
3043 // si,
3044 // .{ .global = .{ .import = true } },
3045 // );
27373046
2738 if (!coff.isImage()) return;3047 return;
3048 }
27393049
2740 if (gn.lib_name.toSlice(coff)) |lib_name| {3050 if (gn.lib_name.toSlice(coff)) |lib_name| {
2741 const name = gn.name.toSlice(coff);3051 const name = gn.name.toSlice(coff);
2742 try coff.nodes.ensureUnusedCapacity(gpa, 4);3052 try coff.nodes.ensureUnusedCapacity(gpa, 4);
2743 try coff.symbol_table.ensureUnusedCapacity(gpa, 1);3053 try coff.symbols.ensureUnusedCapacity(gpa, 1);
27443054
2745 const target_endian = coff.targetEndian();3055 const target_endian = coff.targetEndian();
2746 const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic);3056 const magic = coff.targetLoad(&coff.optionalHeaderStandardPtr().magic);
...@@ -2749,7 +3059,6 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {...@@ -2749,7 +3059,6 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {
2749 .PE32 => .{ 4, .@"4" },3059 .PE32 => .{ 4, .@"4" },
2750 .@"PE32+" => .{ 8, .@"8" },3060 .@"PE32+" => .{ 8, .@"8" },
2751 };3061 };
2752
2753 const gop = try coff.import_table.entries.getOrPutAdapted(3062 const gop = try coff.import_table.entries.getOrPutAdapted(
2754 gpa,3063 gpa,
2755 lib_name,3064 lib_name,
...@@ -2959,7 +3268,16 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -2959,7 +3268,16 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
2959 .data_directories,3268 .data_directories,
2960 .section_table,3269 .section_table,
2961 .placeholder,3270 .placeholder,
3271
3272 .symbol_table_entry,
3273 .string_table,
2962 => if (!coff.isArchive()) unreachable,3274 => if (!coff.isArchive()) unreachable,
3275 .symbol_table => {
3276 coff.targetStore(
3277 &coff.headerPtr().pointer_to_symbol_table,
3278 @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),
3279 );
3280 },
2963 .archive_member_header => |mi| {3281 .archive_member_header => |mi| {
2964 const member = mi.get(coff);3282 const member = mi.get(coff);
2965 switch (member.kind) {3283 switch (member.kind) {
...@@ -3121,7 +3439,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3121,7 +3439,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3121 ),3439 ),
3122 }3440 }
31233441
3124 if (size > coff.image_section_table.items[0].get(coff).rva) try coff.virtualSlide(3442 if (size > coff.section_table.items[0].get(coff).rva) try coff.virtualSlide(
3125 0,3443 0,
3126 std.mem.alignForward(3444 std.mem.alignForward(
3127 u32,3445 u32,
...@@ -3159,6 +3477,12 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3159,6 +3477,12 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3159 .data_directories,3477 .data_directories,
3160 => unreachable,3478 => unreachable,
3161 .section_table => {},3479 .section_table => {},
3480 .symbol_table => assert(!coff.isImage()),
3481 .symbol_table_entry => unreachable,
3482 .string_table => {
3483 assert(!coff.isImage());
3484 coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size));
3485 },
3162 .image_section => |si| {3486 .image_section => |si| {
3163 const sym = si.get(coff);3487 const sym = si.get(coff);
3164 const section_index = sym.section_number.toIndex();3488 const section_index = sym.section_number.toIndex();
...@@ -3173,6 +3497,13 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3173,6 +3497,13 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3173 coff.targetStore(&section.virtual_size, virtual_size);3497 coff.targetStore(&section.virtual_size, virtual_size);
3174 try coff.virtualSlide(section_index + 1, sym.rva + virtual_size);3498 try coff.virtualSlide(section_index + 1, sym.rva + virtual_size);
3175 }3499 }
3500
3501 if (coff.isArchive()) {
3502 coff.targetStore(
3503 &coff.symbolAuxSectionDefinitionPtr(si).length,
3504 @intCast(size),
3505 );
3506 }
3176 },3507 },
3177 .import_directory_table => coff.targetStore(3508 .import_directory_table => coff.targetStore(
3178 &coff.dataDirectoryPtr(.IMPORT).size,3509 &coff.dataDirectoryPtr(.IMPORT).size,
...@@ -3298,7 +3629,7 @@ fn flushExportsSort(coff: *Coff) void {...@@ -3298,7 +3629,7 @@ fn flushExportsSort(coff: *Coff) void {
3298fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {3629fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {
3299 var rva = start_rva;3630 var rva = start_rva;
3300 for (3631 for (
3301 coff.image_section_table.items[start_section_index..],3632 coff.section_table.items[start_section_index..],
3302 coff.sectionTableSlice()[start_section_index..],3633 coff.sectionTableSlice()[start_section_index..],
3303 ) |section_si, *section| {3634 ) |section_si, *section| {
3304 const section_sym = section_si.get(coff);3635 const section_sym = section_si.get(coff);
...@@ -3343,7 +3674,7 @@ fn updateExportsInner(...@@ -3343,7 +3674,7 @@ fn updateExportsInner(
3343 Value.fromInterned(uav).fmtValue(pt),3674 Value.fromInterned(uav).fmtValue(pt),
3344 }),3675 }),
3345 }3676 }
3346 try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);3677 try coff.symbols.ensureUnusedCapacity(gpa, export_indices.len);
3347 const exported_si: Symbol.Index = switch (exported) {3678 const exported_si: Symbol.Index = switch (exported) {
3348 .nav => |nav| try coff.navSymbol(zcu, nav),3679 .nav => |nav| try coff.navSymbol(zcu, nav),
3349 .uav => |uav| @enumFromInt(@intFromEnum(try coff.lowerUav(3680 .uav => |uav| @enumFromInt(@intFromEnum(try coff.lowerUav(
...@@ -3376,13 +3707,20 @@ fn updateExportsInner(...@@ -3376,13 +3707,20 @@ fn updateExportsInner(
3376 std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);3707 std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);
3377 }3708 }
33783709
3379 if (coff.isArchive())3710 if (coff.isArchive()) {
3380 try coff.addMemberSymbol(3711 try coff.addMemberSymbol(
3381 symbol_gop.key_ptr.*.name,3712 symbol_gop.key_ptr.*.name,
3382 coff.getNode(Node.known.zcu_member).archive_member,3713 coff.getNode(Node.known.zcu_member).archive_member,
3383 export_si,3714 export_si,
3384 );3715 );
33853716
3717 try coff.addSymbolTableEntry(
3718 .{ .bytes = name },
3719 export_si,
3720 .{ .global = .{ .import = false } },
3721 );
3722 }
3723
3386 if (coff.export_table.ni == .none) continue;3724 if (coff.export_table.ni == .none) continue;
33873725
3388 const entries_ctx = ExportTable.Adapter{ .coff = coff };3726 const entries_ctx = ExportTable.Adapter{ .coff = coff };
...@@ -3425,8 +3763,7 @@ fn updateExportsInner(...@@ -3425,8 +3763,7 @@ fn updateExportsInner(
3425 coff.targetStore(&edt.number_of_names, @intCast(export_count));3763 coff.targetStore(&edt.number_of_names, @intCast(export_count));
3426 edt.number_of_entries = edt.number_of_names;3764 edt.number_of_entries = edt.number_of_names;
34273765
3428 // TODO: If we had an estimate of the total number of exports this could be a lot more efficient3766 // TODO: These should all be resized ahead of time to fit all exports (after https://github.com/ziglang/zig/issues/23616)
3429
3430 try coff.export_table.export_address_table_si.node(coff).resize(3767 try coff.export_table.export_address_table_si.node(coff).resize(
3431 &coff.mf,3768 &coff.mf,
3432 gpa,3769 gpa,