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
log647fe54ef0843018bfc8416ae5f5f46e6bf2d78c
tree1c2b351c5d8ca1a6ba95be263b2f8e6bba6336a9
parent8c2737fd95f46d43a13a69a0a2cdedecb61a1157

Coff: Writing relocations and symbol table


3 files changed, 321 insertions(+), 321 deletions(-)

lib/std/coff.zig+4
...@@ -1392,6 +1392,10 @@ pub const Relocation = extern struct {...@@ -1392,6 +1392,10 @@ pub const Relocation = extern struct {
1392 virtual_address: u32,1392 virtual_address: u32,
1393 symbol_table_index: u32,1393 symbol_table_index: u32,
1394 type: u16,1394 type: u16,
1395
1396 pub fn sizeOf() usize {
1397 return 10;
1398 }
1395};1399};
13961400
1397pub const IMAGE = struct {1401pub const IMAGE = struct {
src/link/Coff.zig+314-318
...@@ -216,14 +216,26 @@ pub const Node = union(enum) {...@@ -216,14 +216,26 @@ pub const Node = union(enum) {
216 };216 };
217217
218 pub const GlobalMapIndex = enum(u32) {218 pub const GlobalMapIndex = enum(u32) {
219 none,
219 _,220 _,
220221
222 pub fn wrap(i: ?u32) GlobalMapIndex {
223 return @enumFromInt((i orelse return .none) + 1);
224 }
225
226 pub fn unwrap(gmi: GlobalMapIndex) ?u32 {
227 return switch (gmi) {
228 .none => null,
229 _ => @intFromEnum(gmi) - 1,
230 };
231 }
232
221 pub fn globalName(gmi: GlobalMapIndex, coff: *const Coff) GlobalName {233 pub fn globalName(gmi: GlobalMapIndex, coff: *const Coff) GlobalName {
222 return coff.globals.keys()[@intFromEnum(gmi)];234 return coff.globals.keys()[gmi.unwrap().?];
223 }235 }
224236
225 pub fn symbol(gmi: GlobalMapIndex, coff: *const Coff) Symbol.Index {237 pub fn symbol(gmi: GlobalMapIndex, coff: *const Coff) Symbol.Index {
226 return coff.globals.values()[@intFromEnum(gmi)];238 return coff.globals.values()[gmi.unwrap().?];
227 }239 }
228 };240 };
229241
...@@ -452,32 +464,32 @@ pub const LongNamesTable = struct {...@@ -452,32 +464,32 @@ pub const LongNamesTable = struct {
452};464};
453465
454pub const SymbolTable = struct {466pub const SymbolTable = struct {
455 string_offsets: std.AutoArrayHashMapUnmanaged(String, StringIndex),467 strings: std.AutoArrayHashMapUnmanaged(String, StringIndex),
456 entries: std.AutoArrayHashMapUnmanaged(Symbol.Index, Entry),
457468
458 // Adding nodes to the symbol table has the result of accumulating padding469 // Adding nodes to the symbol table has the result of accumulating padding
459 // between the last symbol and the string table, due to the growth factor470 // between the last symbol in the symbol table node and the start of the
460 // in MappedFile. The spec requires the string table begin immediately471 // string table node, due to the growth factor in MappedFile.
461 // after the last symbol, so we compact the symbol table node if needed.472 // The spec requires the string table begin immediately after the last symbol,
473 // so we compact the symbol table node if needed.
462 pending_shrink: bool,474 pending_shrink: bool,
463475
464 pub const Entry = struct {
465 entry_si: Symbol.Index,
466 sti: Index, // TODO: Is this redundant now that we store it on symbol?
467 };
468
469 pub const Add = union(enum) {476 pub const Add = union(enum) {
470 section,477 section,
471 global,478 global,
472 };479 };
473480
481 pub const StringIndex = enum(u32) {
482 _,
483 };
484
474 pub const SymbolName = union(enum) {485 pub const SymbolName = union(enum) {
475 short: []const u8,486 short: []const u8,
476 long: StringIndex,487 long: StringIndex,
477 };488 };
478489
479 // Symbol.Index does not map 1:1 with SymbolTable.Index due to490 // Symbol.Index does not map 1:1 with SymbolTable.Index:
480 // variable number of auxiliary entries that may trail each symbol491 // - Not all symbols need a symbol table entry
492 // - A variable number of auxiliary entries may trail each symbol
481 pub const Index = enum(u32) {493 pub const Index = enum(u32) {
482 none,494 none,
483 _,495 _,
...@@ -492,14 +504,6 @@ pub const SymbolTable = struct {...@@ -492,14 +504,6 @@ pub const SymbolTable = struct {
492 _ => @intFromEnum(sti) - 1,504 _ => @intFromEnum(sti) - 1,
493 };505 };
494 }506 }
495
496 pub fn get(sti: SymbolTable.Index, coff: *Coff) *Entry {
497 return &coff.symbol_table.entries.values()[sti.unwrap().?];
498 }
499 };
500
501 pub const StringIndex = enum(u32) {
502 _,
503 };507 };
504};508};
505509
...@@ -666,7 +670,7 @@ pub const Symbol = struct {...@@ -666,7 +670,7 @@ pub const Symbol = struct {
666 target_relocs: Reloc.Index,670 target_relocs: Reloc.Index,
667 section_number: SectionNumber,671 section_number: SectionNumber,
668 sti: SymbolTable.Index,672 sti: SymbolTable.Index,
669 unused0: u32 = 0,673 gmi: Node.GlobalMapIndex,
670 unused1: u16 = 0,674 unused1: u16 = 0,
671675
672 pub const SectionNumber = enum(i16) {676 pub const SectionNumber = enum(i16) {
...@@ -718,9 +722,27 @@ pub const Symbol = struct {...@@ -718,9 +722,27 @@ pub const Symbol = struct {
718 si.applyTargetRelocs(coff);722 si.applyTargetRelocs(coff);
719 }723 }
720724
725 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
726 const sym = si.get(coff);
727 const index = sym.sti.unwrap() orelse return;
728 var ri = sym.target_relocs;
729 while (ri != .none) {
730 const reloc = ri.get(coff);
731 assert(reloc.target == si);
732 if (reloc.sri.entry(coff, reloc.loc.get(coff).section_number)) |entry|
733 coff.targetStore(&entry.symbol_table_index, index);
734 ri = reloc.next;
735 }
736 }
737
721 pub fn applyLocationRelocs(si: Symbol.Index, coff: *Coff) void {738 pub fn applyLocationRelocs(si: Symbol.Index, coff: *Coff) void {
722 for (coff.relocs.items[@intFromEnum(si.get(coff).loc_relocs)..]) |*reloc| {739 const sym = si.get(coff);
740 for (coff.relocs.items[@intFromEnum(sym.loc_relocs)..]) |*reloc| {
723 if (reloc.loc != si) break;741 if (reloc.loc != si) break;
742 if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore(
743 &entry.virtual_address,
744 @intCast(coff.computeNodeSectionOffset(sym.ni) + reloc.offset),
745 );
724 reloc.apply(coff);746 reloc.apply(coff);
725 }747 }
726 }748 }
...@@ -743,17 +765,6 @@ pub const Symbol = struct {...@@ -743,17 +765,6 @@ pub const Symbol = struct {
743 }765 }
744 sym.loc_relocs = .none;766 sym.loc_relocs = .none;
745 }767 }
746
747 pub fn updateRelocsSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
748 const sym = si.get(coff);
749 var ri = sym.target_relocs;
750 while (ri != .none) {
751 const reloc = ri.get(coff);
752 if (reloc.sri.entry(coff, reloc.loc.get(coff).section_number)) |entry|
753 coff.targetStore(&entry.symbol_table_index, sym.sti.unwrap().?);
754 ri = reloc.next;
755 }
756 }
757 };768 };
758769
759 comptime {770 comptime {
...@@ -798,20 +809,72 @@ pub const Reloc = extern struct {...@@ -798,20 +809,72 @@ pub const Reloc = extern struct {
798 .none => return,809 .none => return,
799 else => |ni| if (ni.hasMoved(&coff.mf)) return,810 else => |ni| if (ni.hasMoved(&coff.mf)) return,
800 }811 }
812
813 const loc_slice = loc_sym.ni.slice(&coff.mf)[@intCast(reloc.offset)..];
814 const target_endian = coff.targetEndian();
815
816 if (!coff.isImage()) {
817 switch (coff.targetLoad(&coff.headerPtr().machine)) {
818 else => |machine| @panic(@tagName(machine)),
819 .AMD64 => switch (reloc.type.AMD64) {
820 else => |kind| @panic(@tagName(kind)),
821 .ABSOLUTE => {},
822 .ADDR64 => std.mem.writeInt(
823 u64,
824 loc_slice[0..8],
825 @intCast(reloc.addend),
826 target_endian,
827 ),
828 .ADDR32,
829 .ADDR32NB,
830 .REL32,
831 .REL32_1,
832 .REL32_2,
833 .REL32_3,
834 .REL32_4,
835 .REL32_5,
836 .SECREL,
837 => std.mem.writeInt(
838 u32,
839 loc_slice[0..4],
840 @intCast(reloc.addend),
841 target_endian,
842 ),
843 },
844 .I386 => switch (reloc.type.I386) {
845 else => |kind| @panic(@tagName(kind)),
846 .ABSOLUTE => {},
847 .DIR16,
848 .REL16,
849 => std.mem.writeInt(
850 u16,
851 loc_slice[0..2],
852 @intCast(reloc.addend),
853 target_endian,
854 ),
855 .DIR32,
856 .DIR32NB,
857 .REL32,
858 .SECREL,
859 => std.mem.writeInt(
860 u32,
861 loc_slice[0..4],
862 @intCast(reloc.addend),
863 target_endian,
864 ),
865 },
866 }
867
868 return;
869 }
870
801 const target_sym = reloc.target.get(coff);871 const target_sym = reloc.target.get(coff);
802 switch (target_sym.ni) {872 switch (target_sym.ni) {
803 .none => return,873 .none => return,
804 else => |ni| if (ni.hasMoved(&coff.mf)) return,874 else => |ni| if (ni.hasMoved(&coff.mf)) return,
805 }875 }
806 const loc_slice = loc_sym.ni.slice(&coff.mf)[@intCast(reloc.offset)..];
807 const target_rva = target_sym.rva +% @as(u64, @bitCast(reloc.addend));
808 const target_endian = coff.targetEndian();
809876
810 // TODO: Is this right?877 const target_rva = target_sym.rva +% @as(u64, @bitCast(reloc.addend));
811 const base = if (coff.isImage())
812 coff.optionalHeaderField(.image_base)
813 else
814 0; // should be offset within section - take target_rva - section_rva (but section is 0!)
815878
816 switch (coff.targetLoad(&coff.headerPtr().machine)) {879 switch (coff.targetLoad(&coff.headerPtr().machine)) {
817 else => |machine| @panic(@tagName(machine)),880 else => |machine| @panic(@tagName(machine)),
...@@ -821,13 +884,13 @@ pub const Reloc = extern struct {...@@ -821,13 +884,13 @@ pub const Reloc = extern struct {
821 .ADDR64 => std.mem.writeInt(884 .ADDR64 => std.mem.writeInt(
822 u64,885 u64,
823 loc_slice[0..8],886 loc_slice[0..8],
824 base + target_rva,887 coff.optionalHeaderField(.image_base) + target_rva,
825 target_endian,888 target_endian,
826 ),889 ),
827 .ADDR32 => std.mem.writeInt(890 .ADDR32 => std.mem.writeInt(
828 u32,891 u32,
829 loc_slice[0..4],892 loc_slice[0..4],
830 @intCast(base + target_rva),893 @intCast(coff.optionalHeaderField(.image_base) + target_rva),
831 target_endian,894 target_endian,
832 ),895 ),
833 .ADDR32NB => std.mem.writeInt(896 .ADDR32NB => std.mem.writeInt(
...@@ -875,7 +938,7 @@ pub const Reloc = extern struct {...@@ -875,7 +938,7 @@ pub const Reloc = extern struct {
875 .SECREL => std.mem.writeInt(938 .SECREL => std.mem.writeInt(
876 u32,939 u32,
877 loc_slice[0..4],940 loc_slice[0..4],
878 coff.computeNodeSectionOffset(target_sym.ni),941 @intCast(coff.computeNodeSectionOffset(target_sym.ni) + reloc.addend),
879 target_endian,942 target_endian,
880 ),943 ),
881 },944 },
...@@ -885,7 +948,7 @@ pub const Reloc = extern struct {...@@ -885,7 +948,7 @@ pub const Reloc = extern struct {
885 .DIR16 => std.mem.writeInt(948 .DIR16 => std.mem.writeInt(
886 u16,949 u16,
887 loc_slice[0..2],950 loc_slice[0..2],
888 @intCast(base + target_rva),951 @intCast(coff.optionalHeaderField(.image_base) + target_rva),
889 target_endian,952 target_endian,
890 ),953 ),
891 .REL16 => std.mem.writeInt(954 .REL16 => std.mem.writeInt(
...@@ -897,7 +960,7 @@ pub const Reloc = extern struct {...@@ -897,7 +960,7 @@ pub const Reloc = extern struct {
897 .DIR32 => std.mem.writeInt(960 .DIR32 => std.mem.writeInt(
898 u32,961 u32,
899 loc_slice[0..4],962 loc_slice[0..4],
900 @intCast(base + target_rva),963 @intCast(coff.optionalHeaderField(.image_base) + target_rva),
901 target_endian,964 target_endian,
902 ),965 ),
903 .DIR32NB => std.mem.writeInt(966 .DIR32NB => std.mem.writeInt(
...@@ -915,7 +978,7 @@ pub const Reloc = extern struct {...@@ -915,7 +978,7 @@ pub const Reloc = extern struct {
915 .SECREL => std.mem.writeInt(978 .SECREL => std.mem.writeInt(
916 u32,979 u32,
917 loc_slice[0..4],980 loc_slice[0..4],
918 coff.computeNodeSectionOffset(target_sym.ni),981 @intCast(coff.computeNodeSectionOffset(target_sym.ni) + reloc.addend),
919 target_endian,982 target_endian,
920 ),983 ),
921 },984 },
...@@ -923,7 +986,11 @@ pub const Reloc = extern struct {...@@ -923,7 +986,11 @@ pub const Reloc = extern struct {
923 }986 }
924987
925 pub fn delete(reloc: *Reloc, coff: *Coff) void {988 pub fn delete(reloc: *Reloc, coff: *Coff) void {
926 // TODO: Need to remove this from the COFF relocation table (remove swap)989 if (reloc.sri != .none) {
990 // TODO: Need to remove this from the COFF relocation table (maybe removeswap?)
991 // TODO: If this was the last reloc causing something to be in the symbol table, we should remove the sti
992 // That will require flushSymbolTableIndex on the swapped symbol if we exchange indices
993 }
927994
928 switch (reloc.prev) {995 switch (reloc.prev) {
929 .none => {996 .none => {
...@@ -1036,8 +1103,7 @@ fn create(...@@ -1036,8 +1103,7 @@ fn create(
1036 .entries = .empty,1103 .entries = .empty,
1037 },1104 },
1038 .symbol_table = .{1105 .symbol_table = .{
1039 .string_offsets = .empty,1106 .strings = .empty,
1040 .entries = .empty,
1041 .pending_shrink = false,1107 .pending_shrink = false,
1042 },1108 },
1043 .strings = .empty,1109 .strings = .empty,
...@@ -1088,8 +1154,7 @@ pub fn deinit(coff: *Coff) void {...@@ -1088,8 +1154,7 @@ pub fn deinit(coff: *Coff) void {
1088 coff.long_names_table.entries.deinit(gpa);1154 coff.long_names_table.entries.deinit(gpa);
1089 coff.import_table.entries.deinit(gpa);1155 coff.import_table.entries.deinit(gpa);
1090 coff.export_table.entries.deinit(gpa);1156 coff.export_table.entries.deinit(gpa);
1091 coff.symbol_table.string_offsets.deinit(gpa);1157 coff.symbol_table.strings.deinit(gpa);
1092 coff.symbol_table.entries.deinit(gpa);
1093 coff.strings.deinit(gpa);1158 coff.strings.deinit(gpa);
1094 coff.string_bytes.deinit(gpa);1159 coff.string_bytes.deinit(gpa);
1095 coff.section_table.deinit(gpa);1160 coff.section_table.deinit(gpa);
...@@ -1159,8 +1224,8 @@ fn initHeaders(...@@ -1159,8 +1224,8 @@ fn initHeaders(
1159 if (comp.zcu != null) {1224 if (comp.zcu != null) {
1160 // Section nodes1225 // Section nodes
1161 expected_nodes_len += 3;1226 expected_nodes_len += 3;
1162 // Symbol table nodes1227 // // Symbol table nodes
1163 if (is_archive) expected_nodes_len += 6;1228 // if (is_archive) expected_nodes_len += 6;
1164 // Pseudo-sections and import / export table nodes1229 // Pseudo-sections and import / export table nodes
1165 if (is_image) expected_nodes_len += 9;1230 if (is_image) expected_nodes_len += 9;
1166 // TLS section nodes1231 // TLS section nodes
...@@ -1421,7 +1486,7 @@ fn initHeaders(...@@ -1421,7 +1486,7 @@ fn initHeaders(
1421 }));1486 }));
1422 coff.nodes.appendAssumeCapacity(.section_table);1487 coff.nodes.appendAssumeCapacity(.section_table);
14231488
1424 // TODO: These two nodes could be inside one movable node1489 // TODO: These two nodes could be inside one movable node?
1425 const symbol_table_ni = Node.known.symbol_table;1490 const symbol_table_ni = Node.known.symbol_table;
1426 assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{1491 assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{
1427 .alignment = .@"2",1492 .alignment = .@"2",
...@@ -1450,6 +1515,7 @@ fn initHeaders(...@@ -1450,6 +1515,7 @@ fn initHeaders(
1450 .target_relocs = .none,1515 .target_relocs = .none,
1451 .section_number = .UNDEFINED,1516 .section_number = .UNDEFINED,
1452 .sti = .none,1517 .sti = .none,
1518 .gmi = .none,
1453 };1519 };
1454 assert(try coff.addSection(".data", .{1520 assert(try coff.addSection(".data", .{
1455 .CNT_INITIALIZED_DATA = true,1521 .CNT_INITIALIZED_DATA = true,
...@@ -1789,20 +1855,24 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {...@@ -1789,20 +1855,24 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {
1789 ));1855 ));
1790}1856}
17911857
1792pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) *align(2) std.coff.Symbol {1858pub fn symbolTableEntryStoragePtr(coff: *Coff, index: u32) *[std.coff.Symbol.sizeOf()]u8 {
1793 return @ptrCast(@alignCast(1859 assert(!coff.isImage());
1794 &Node.known.symbol_table.slice(&coff.mf)[sti.unwrap().? * std.coff.Symbol.sizeOf()],1860 const offset = index * std.coff.Symbol.sizeOf();
1795 ));1861 return @ptrCast(@alignCast(Node.known.symbol_table.slice(&coff.mf)[offset..][0..std.coff.Symbol.sizeOf()]));
1796}1862}
17971863
1798pub fn symbolAuxSectionDefinitionPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition {1864pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) ?*align(2) std.coff.Symbol {
1799 const sti = coff.symbol_table.entries.get(si).?.sti;1865 if (sti.unwrap()) |index|
1800 const symbol = coff.symbolTableEntryPtr(sti);1866 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, index)))
1801 assert(symbol.storage_class == .STATIC and symbol.number_of_aux_symbols == 1);1867 else
1868 return null;
1869}
18021870
1803 return @ptrCast(@alignCast(1871pub fn symbolTableSectionAuxEntryPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition {
1804 &Node.known.symbol_table.slice(&coff.mf)[(sti.unwrap().? + 1) * std.coff.Symbol.sizeOf()],1872 const sti = si.get(coff).sti;
1805 ));1873 const entry = symbolTableEntryPtr(coff, sti).?;
1874 assert(entry.storage_class == .STATIC and entry.number_of_aux_symbols == 1);
1875 return @ptrCast(@alignCast(symbolTableEntryStoragePtr(coff, sti.unwrap().? + 1)));
1806}1876}
18071877
1808pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 {1878pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 {
...@@ -1844,6 +1914,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -1844,6 +1914,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
1844 .target_relocs = .none,1914 .target_relocs = .none,
1845 .section_number = .UNDEFINED,1915 .section_number = .UNDEFINED,
1846 .sti = .none,1916 .sti = .none,
1917 .gmi = .none,
1847 };1918 };
1848 return @enumFromInt(coff.symbols.items.len);1919 return @enumFromInt(coff.symbols.items.len);
1849}1920}
...@@ -1891,7 +1962,9 @@ pub fn globalSymbol(coff: *Coff, opts: struct {...@@ -1891,7 +1962,9 @@ pub fn globalSymbol(coff: *Coff, opts: struct {
1891 .lib_name = try coff.getOrPutOptionalString(opts.lib_name),1962 .lib_name = try coff.getOrPutOptionalString(opts.lib_name),
1892 });1963 });
1893 if (!sym_gop.found_existing) {1964 if (!sym_gop.found_existing) {
1894 sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();1965 const si = coff.addSymbolAssumeCapacity();
1966 si.get(coff).gmi = .wrap(@intCast(sym_gop.index));
1967 sym_gop.value_ptr.* = si;
1895 coff.synth_prog_node.increaseEstimatedTotalItems(1);1968 coff.synth_prog_node.increaseEstimatedTotalItems(1);
1896 }1969 }
18971970
...@@ -1993,7 +2066,7 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol....@@ -1993,7 +2066,7 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.
1993 reloc_info.addend,2066 reloc_info.addend,
1994 switch (coff.targetLoad(&coff.headerPtr().machine)) {2067 switch (coff.targetLoad(&coff.headerPtr().machine)) {
1995 else => unreachable,2068 else => unreachable,
1996 .AMD64 => .{ .AMD64 = .ADDR64 }, // TODO: Switch to REL32 for obj/archive2069 .AMD64 => .{ .AMD64 = .ADDR64 },
1997 .I386 => .{ .I386 = .DIR32 },2070 .I386 => .{ .I386 = .DIR32 },
1998 },2071 },
1999 );2072 );
...@@ -2097,7 +2170,7 @@ fn appendMemberSymbolString(...@@ -2097,7 +2170,7 @@ fn appendMemberSymbolString(
20972170
2098fn ensureMemberSymbol(2171fn ensureMemberSymbol(
2099 coff: *Coff,2172 coff: *Coff,
2100 name: []const u8,2173 name: String,
2101 mi: Member.Index,2174 mi: Member.Index,
2102 si: Symbol.Index,2175 si: Symbol.Index,
2103) !void {2176) !void {
...@@ -2105,7 +2178,6 @@ fn ensureMemberSymbol(...@@ -2105,7 +2178,6 @@ fn ensureMemberSymbol(
2105 const member = mi.get(coff);2178 const member = mi.get(coff);
2106 assert(member.kind == .coff);2179 assert(member.kind == .coff);
21072180
2108 const name_string = try coff.getOrPutString(name);
2109 const gop = try member.first_linker_indices.getOrPut(gpa, si);2181 const gop = try member.first_linker_indices.getOrPut(gpa, si);
2110 if (gop.found_existing) return;2182 if (gop.found_existing) return;
21112183
...@@ -2124,7 +2196,8 @@ fn ensureMemberSymbol(...@@ -2124,7 +2196,8 @@ fn ensureMemberSymbol(
2124 // Linker member fields are not modeled as nodes because MappedFile2196 // Linker member fields are not modeled as nodes because MappedFile
2125 // can't guarantee that they will be tightly packed after resizing2197 // can't guarantee that they will be tightly packed after resizing
21262198
2127 const new_string_table_size = coff.lib_string_len + name.len + 1;2199 const name_slice = name.toSlice(coff);
2200 const new_string_table_size = coff.lib_string_len + name_slice.len + 1;
2128 defer coff.lib_string_len = new_string_table_size;2201 defer coff.lib_string_len = new_string_table_size;
21292202
2130 {2203 {
...@@ -2134,8 +2207,8 @@ fn ensureMemberSymbol(...@@ -2134,8 +2207,8 @@ fn ensureMemberSymbol(
21342207
2135 const slice = Node.known.first_linker_member.slice(&coff.mf);2208 const slice = Node.known.first_linker_member.slice(&coff.mf);
2136 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);2209 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
2137 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name.len], name[0..name.len]);2210 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice[0..name_slice.len]);
2138 slice[new_header_size + coff.lib_string_len + name.len] = 0;2211 slice[new_header_size + coff.lib_string_len + name_slice.len] = 0;
21392212
2140 // New offset entry is written in flushMember2213 // New offset entry is written in flushMember
2141 }2214 }
...@@ -2149,13 +2222,13 @@ fn ensureMemberSymbol(...@@ -2149,13 +2222,13 @@ fn ensureMemberSymbol(
2149 const needs_sort = if (coff.lib_string_table.items.len > 0)2222 const needs_sort = if (coff.lib_string_table.items.len > 0)
2150 std.mem.lessThan(2223 std.mem.lessThan(
2151 u8,2224 u8,
2152 name,2225 name_slice,
2153 coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff),2226 coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff),
2154 )2227 )
2155 else2228 else
2156 false;2229 false;
21572230
2158 try coff.lib_string_table.append(gpa, name_string);2231 try coff.lib_string_table.append(gpa, name);
21592232
2160 const slice = Node.known.second_linker_member.slice(&coff.mf);2233 const slice = Node.known.second_linker_member.slice(&coff.mf);
2161 const num_symbols_ptr: *u32 = @ptrCast(@alignCast(slice[@sizeOf(u32) + num_members * @sizeOf(u32) ..]));2234 const num_symbols_ptr: *u32 = @ptrCast(@alignCast(slice[@sizeOf(u32) + num_members * @sizeOf(u32) ..]));
...@@ -2166,8 +2239,8 @@ fn ensureMemberSymbol(...@@ -2166,8 +2239,8 @@ fn ensureMemberSymbol(
2166 coff.pending_members.putAssumeCapacity(Member.Index.second, {});2239 coff.pending_members.putAssumeCapacity(Member.Index.second, {});
2167 } else {2240 } else {
2168 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);2241 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
2169 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name.len], name[0..name.len]);2242 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name_slice.len], name_slice[0..name_slice.len]);
2170 slice[new_header_size + coff.lib_string_len + name.len] = 0;2243 slice[new_header_size + coff.lib_string_len + name_slice.len] = 0;
2171 }2244 }
21722245
2173 // Indices in this table are 1-based2246 // Indices in this table are 1-based
...@@ -2178,189 +2251,130 @@ fn ensureMemberSymbol(...@@ -2178,189 +2251,130 @@ fn ensureMemberSymbol(
2178 coff.pending_members.putAssumeCapacity(mi, {});2251 coff.pending_members.putAssumeCapacity(mi, {});
2179}2252}
21802253
2181fn addSymbolTableEntry(2254// TODO: -> flushSymbolTableEntry, and push all call sites onto a pending list instead?
2182 coff: *Coff,2255fn updateSymbolTableEntry(coff: *Coff, si: Symbol.Index) !SymbolTable.Index {
2183 name: union(enum) {
2184 bytes: []const u8,
2185 string: String,
2186 },
2187 si: Symbol.Index,
2188 add: SymbolTable.Add,
2189) !void {
2190 assert(!coff.isImage());2256 assert(!coff.isImage());
2191 const gpa = coff.base.comp.gpa;2257 const gpa = coff.base.comp.gpa;
21922258
2193 // TODO: Avoid geOrPutString if it fits (only need to actually make the String for adding member symbol)
2194 const string, const name_slice = switch (name) {
2195 .bytes => |bytes| .{ try coff.getOrPutString(bytes), bytes },
2196 .string => |s| .{ s, s.toSlice(coff) },
2197 };
2198
2199 const symbol_name: SymbolTable.SymbolName = if (name_slice.len > 8) index: {
2200 const string_gop = try coff.symbol_table.string_offsets.getOrPut(gpa, string);
2201 if (!string_gop.found_existing) {
2202 const string_index = Node.known.string_table.location(&coff.mf).resolve(&coff.mf)[1];
2203 string_gop.value_ptr.* = @enumFromInt(string_index);
2204
2205 try Node.known.string_table.resize(&coff.mf, gpa, string_index + name_slice.len + 1);
2206 const slice = Node.known.string_table.slice(&coff.mf);
2207 @memcpy(slice[string_index..][0..name_slice.len], name_slice);
2208 slice[string_index + name_slice.len] = 0;
2209 }
2210
2211 break :index .{ .long = string_gop.value_ptr.* };
2212 } else .{ .short = name_slice };
2213
2214 const old_num_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
2215
2216 const sym = si.get(coff);2259 const sym = si.get(coff);
2217 sym.sti = .wrap(old_num_symbols);2260 const has_node = sym.ni != .none;
2218 si.updateRelocsSymbolTableIndex(coff);2261 assert(has_node or sym.gmi != .none);
22192262
2220 log.debug("addSymbolTableEntry({s}, {d}) = {d}", .{ name_slice, si, sym.sti.unwrap().? });2263 const entry = coff.symbolTableEntryPtr(sym.sti) orelse entry: {
22212264 var buf: [15]u8 = undefined;
2222 // TODO: Can look at sym.ni to know what kind this is2265 const name_slice, const opt_name_string, const num_aux_symbols: u8, const complex_type: std.coff.ComplexType =
22232266 if (sym.gmi != .none) blk: {
2224 const symbols_added: u8 = switch (add) {2267 const gn = sym.gmi.globalName(coff);
2225 .section => count: {2268 break :blk .{
2226 try coff.nodes.ensureUnusedCapacity(gpa, 2);2269 gn.name.toSlice(coff),
2227 _ = try coff.addSymbolTableEntryAssumeCapacity(2270 gn.name,
2228 symbol_name,2271 0,
2229 0,2272 if (Symbol.Index.text.get(coff).section_number == sym.section_number)
2230 sym.section_number,
2231 .{
2232 .complex_type = .NULL,
2233 .base_type = .NULL,
2234 },
2235 .STATIC,
2236 1,
2237 );
2238
2239 // Aux entry ields are updated by flushMoved / flushResized
2240 try coff.symbol_table.entries.put(gpa, si, .{
2241 .entry_si = .null,
2242 .sti = sym.sti,
2243 });
2244
2245 break :count 2;
2246 },
2247 .global => count: {
2248 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2249 try coff.symbols.ensureUnusedCapacity(gpa, 1);
2250
2251 if (sym.ni != .none) {
2252 try coff.ensureMemberSymbol(
2253 name_slice, // TODO: Swap to string?
2254 coff.getNode(Node.known.zcu_member).archive_member,
2255 si,
2256 );
2257 }
2258
2259 const entry_ni = try coff.addSymbolTableEntryAssumeCapacity(
2260 symbol_name,
2261 if (sym.ni == .none) 0 else coff.computeNodeSectionOffset(sym.ni),
2262 sym.section_number,
2263 .{
2264 .base_type = .NULL,
2265 .complex_type = if (Symbol.Index.text.get(coff).section_number == sym.section_number)
2266 .FUNCTION2273 .FUNCTION
2267 else2274 else
2268 .NULL,2275 .NULL,
2276 };
2277 } else switch (coff.getNode(sym.ni)) {
2278 .image_section => .{
2279 &sym.section_number.header(coff).name,
2280 null,
2281 1,
2282 .NULL,
2269 },2283 },
2270 .EXTERNAL,2284 .nav => |nmi| blk: {
2271 0,2285 const zcu = coff.base.comp.zcu.?;
2272 );2286 const ip = &zcu.intern_pool;
2287 const nav = ip.getNav(nmi.navIndex(coff));
2288 break :blk .{
2289 nav.fqn.toSlice(ip),
2290 null,
2291 0,
2292 if (ip.isFunctionType(nav.resolved.?.type)) .FUNCTION else .NULL,
2293 };
2294 },
2295 .uav => |umi| blk: {
2296 var w = Io.Writer.fixed(&buf);
2297 w.print("__anon_{x}", .{umi.uavValue(coff)}) catch unreachable;
2298 break :blk .{ w.buffered(), null, 0, .NULL };
2299 },
2300 else => {
2301 log.err("TODO implement symbol table init for {s}", .{@tagName(coff.getNode(sym.ni))});
2302 return .none;
2303 },
2304 };
22732305
2274 const entry_si = coff.addSymbolAssumeCapacity();2306 const symbol_name: SymbolTable.SymbolName = if (name_slice.len > 8) name: {
2275 {2307 const string = opt_name_string orelse try coff.getOrPutString(name_slice);
2276 const entry_sym = entry_si.get(coff);2308 const string_gop = try coff.symbol_table.strings.getOrPut(gpa, string);
2277 entry_sym.ni = entry_ni;2309 if (!string_gop.found_existing) {
2278 assert(entry_sym.loc_relocs == .none);2310 const string_index = Node.known.string_table.location(&coff.mf).resolve(&coff.mf)[1];
2279 entry_sym.loc_relocs = @enumFromInt(coff.relocs.items.len);2311 string_gop.value_ptr.* = @enumFromInt(string_index);
2280 entry_sym.section_number = .UNDEFINED;2312
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);
2315 @memcpy(slice[string_index..][0..name_slice.len], name_slice);
2316 slice[string_index + name_slice.len] = 0;
2281 }2317 }
22822318
2283 if (sym.ni != .none) {2319 break :name .{ .long = string_gop.value_ptr.* };
2284 // TODO: This serves to update the std.coff.Symbol.value (to VA of si), is this working?2320 } else .{ .short = name_slice };
2285 try coff.addReloc(
2286 entry_si,
2287 @offsetOf(std.coff.Symbol, "value"),
2288 si,
2289 0,
2290 .{ .AMD64 = .SECREL }, // TODO: x86 too
2291 );
2292 }
22932321
2294 try coff.symbol_table.entries.put(gpa, si, .{2322 const old_num_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
2295 .entry_si = entry_si,2323 const new_num_symbols = old_num_symbols + 1 + num_aux_symbols;
2296 .sti = sym.sti,
2297 });
22982324
2299 break :count 1;2325 try Node.known.symbol_table.resize(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf());
2300 },
2301 };
23022326
2303 const new_num_symbols = old_num_symbols + symbols_added;2327 const symbol_table_loc = Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf);
2304 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);2328 const string_table_loc = Node.known.string_table.location(&coff.mf).resolve(&coff.mf);
2305 coff.symbol_table.pending_shrink =2329 coff.symbol_table.pending_shrink = string_table_loc[0] - (symbol_table_loc[0] + symbol_table_loc[1]) > 0;
2306 Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf)[1] >
2307 new_num_symbols * std.coff.Symbol.sizeOf();
2308}
23092330
2310/// Caller guarantees there is capacity for 1 + number_of_aux_symbols nodes.2331 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);
2311/// Auxiliary nodes are zero-initialized.2332 sym.sti = .wrap(old_num_symbols);
2312fn addSymbolTableEntryAssumeCapacity(2333 si.flushSymbolTableIndex(coff);
2313 coff: *Coff,
2314 name: SymbolTable.SymbolName,
2315 value: u32,
2316 section_number: Symbol.SectionNumber,
2317 @"type": std.coff.SymType,
2318 storage_class: std.coff.StorageClass,
2319 number_of_aux_symbols: u8,
2320) !MappedFile.Node.Index {
2321 const gpa = coff.base.comp.gpa;
23222334
2323 const entry_ni = try coff.mf.addLastChildNode(gpa, Node.known.symbol_table, .{2335 const entry = coff.symbolTableEntryPtr(sym.sti).?;
2324 .alignment = .@"2",2336 switch (symbol_name) {
2325 .size = std.coff.Symbol.sizeOf(),2337 .short => |s| {
2326 .fixed = true,2338 @memcpy(entry.name[0..s.len], s);
2327 });2339 @memset(entry.name[s.len..], 0);
2328 coff.nodes.appendAssumeCapacity(.symbol_table_entry);2340 },
2341 .long => |l| {
2342 @memset(entry.name[0..4], 0);
2343 const offset_ptr: *align(2) u32 = @ptrCast(entry.name[4..]);
2344 coff.targetStore(offset_ptr, @intFromEnum(l));
2345 },
2346 }
23292347
2330 const entry: *align(2) std.coff.Symbol = @ptrCast(@alignCast(entry_ni.slice(&coff.mf)));2348 entry.section_number = @enumFromInt(@intFromEnum(sym.section_number));
2331 switch (name) {2349 entry.type = .{
2332 .short => |s| {2350 .complex_type = complex_type,
2333 @memcpy(entry.name[0..s.len], s);2351 .base_type = .NULL,
2334 @memset(entry.name[s.len..], 0);2352 };
2335 },2353 entry.storage_class = if (sym.gmi == .none) .STATIC else .EXTERNAL;
2336 .long => |l| {2354 entry.number_of_aux_symbols = num_aux_symbols;
2337 @memset(entry.name[0..4], 0);2355 if (coff.targetEndian() != native_endian)
2338 const offset_ptr: *align(2) u32 = @ptrCast(entry.name[4..]);2356 std.mem.byteSwapAllFieldsAligned(std.coff.Symbol, .@"2", entry);
2339 coff.targetStore(offset_ptr, @intFromEnum(l));
2340 },
2341 }
23422357
2343 // TODO: Would be ideal to assign entry.*, but given @sizeOf() > entry.sizeOf(), is that valid?2358 for (1..num_aux_symbols + 1) |aux_index|
2344 entry.value = value;2359 @memset(coff.symbolTableEntryStoragePtr(@intCast(old_num_symbols + aux_index)), 0);
2345 entry.section_number = @enumFromInt(@intFromEnum(section_number));
2346 entry.type = @"type";
2347 entry.storage_class = storage_class;
2348 entry.number_of_aux_symbols = number_of_aux_symbols;
23492360
2350 if (coff.targetEndian() != native_endian)2361 break :entry entry;
2351 std.mem.byteSwapAllFields(std.coff.SectionHeader, entry.*);2362 };
23522363
2353 for (0..number_of_aux_symbols) |_| {2364 coff.targetStore(&entry.value, switch (sym.section_number) {
2354 const aux_ni = try coff.mf.addLastChildNode(gpa, Node.known.symbol_table, .{2365 .UNDEFINED => sym.size,
2355 .alignment = .@"2",2366 .ABSOLUTE,
2356 .size = std.coff.Symbol.sizeOf(),2367 .DEBUG,
2357 .fixed = true,2368 => unreachable,
2358 });2369 else => switch (coff.getNode(sym.ni)) {
2359 coff.nodes.appendAssumeCapacity(.symbol_table_entry);2370 .image_section => 0,
2360 @memset(aux_ni.slice(&coff.mf), 0);2371 else => coff.computeNodeSectionOffset(sym.ni),
2361 }2372 },
2373 });
23622374
2363 return entry_ni;2375 log.debug("updateSymbolTableEntry({d}) = {d}", .{ si, sym.sti });
2376
2377 return sym.sti;
2364}2378}
23652379
2366fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index {2380fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags) !Symbol.Index {
...@@ -2443,7 +2457,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2443,7 +2457,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2443 ),2457 ),
2444 }2458 }
2445 } else {2459 } else {
2446 try coff.addSymbolTableEntry(.{ .bytes = name }, si, .section);2460 assert(try coff.updateSymbolTableEntry(si) != .none);
2447 }2461 }
24482462
2449 return si;2463 return si;
...@@ -2579,67 +2593,66 @@ pub fn addReloc(...@@ -2579,67 +2593,66 @@ pub fn addReloc(
2579 addend: i64,2593 addend: i64,
2580 @"type": Reloc.Type,2594 @"type": Reloc.Type,
2581) !void {2595) !void {
2596 const gpa = coff.base.comp.gpa;
2582 const target = target_si.get(coff);2597 const target = target_si.get(coff);
2583 log.debug("addReloc({d}@{d} + {d} -> {d}@{d} + {d})", .{ loc_si, loc_si.get(coff).section_number, offset, target_si, target_si.get(coff).section_number, addend });
25842598
2585 try ensureUnusedRelocCapacity(coff, loc_si, 1);2599 log.debug("addReloc({d}@{d}+{d} -> {d}@{d}+{d})", .{ loc_si, loc_si.get(coff).section_number, offset, target_si, target_si.get(coff).section_number, addend });
25862600
2587 // TODO: The switch should be in an ensure capacity for reloc fn2601 try coff.relocs.ensureUnusedCapacity(gpa, 1);
25882602
2589 const sri: Section.RelocationIndex = if (isImage(coff))2603 const sri: Section.RelocationIndex = if (isImage(coff))
2590 .none2604 .none
2591 else switch (loc_si.get(coff).section_number) {2605 else switch (loc_si.get(coff).section_number) {
2592 .UNDEFINED, .ABSOLUTE, .DEBUG => .none,2606 .UNDEFINED,
2607 .ABSOLUTE,
2608 .DEBUG,
2609 => .none,
2593 else => |loc_sn| sri: {2610 else => |loc_sn| sri: {
2611 // The target may not have a node yet, or it could be an extern that will never
2612 // have a node. In that case, flushGlobal will create the symbol table entry.
2613 const sti: SymbolTable.Index = if (target.sti != .none)
2614 target.sti
2615 else if (target.ni != .none)
2616 try updateSymbolTableEntry(coff, target_si)
2617 else
2618 .none;
2619
2620 const section = loc_sn.section(coff);
2594 const header = loc_sn.header(coff);2621 const header = loc_sn.header(coff);
2595 const old_num_relocations = coff.targetLoad(&header.number_of_relocations);2622 const old_num_relocations = coff.targetLoad(&header.number_of_relocations);
2596 const new_num_relocations = old_num_relocations + 1;2623 const new_num_relocations = old_num_relocations + 1;
2624 const new_size = new_num_relocations * std.coff.Relocation.sizeOf();
2625 if (section.relocation_table_ni == .none) {
2626 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2627 section.relocation_table_ni = try coff.mf.addLastChildNode(gpa, Node.known.zcu_member, .{
2628 .size = new_size,
2629 .alignment = .@"2",
2630 .moved = true,
2631 .resized = true,
2632 });
2633 coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn });
2634 } else {
2635 try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
2636 }
2637
2597 coff.targetStore(2638 coff.targetStore(
2598 &header.number_of_relocations,2639 &header.number_of_relocations,
2599 new_num_relocations,2640 new_num_relocations,
2600 );2641 );
2601 coff.targetStore(2642 coff.targetStore(
2602 &coff.symbolAuxSectionDefinitionPtr(loc_sn.symbol(coff)).number_of_relocations,2643 &coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff)).number_of_relocations,
2603 new_num_relocations,2644 new_num_relocations,
2604 );2645 );
26052646
2647 // TODO: These need to allocate from a free list (once deleting relocs is supported) (or can we just remove swap?)
2648
2606 const sri: Section.RelocationIndex = .wrap(old_num_relocations);2649 const sri: Section.RelocationIndex = .wrap(old_num_relocations);
2607 const entry = sri.entry(coff, loc_sn).?;2650 const entry = sri.entry(coff, loc_sn).?;
2651 if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index);
26082652
2609 entry.virtual_address = @intCast(offset);2653 // applyLocationRelocs updates `virtual_address`
2610 switch (target.sti) {2654 // flushSymbolTableIndex updates `symbol_table_index`
2611 .none => {2655 coff.targetStore(&entry.type, @bitCast(@"type"));
2612 // TODO: Now is the moment when we know we need to add this to the symbol table
2613
2614 // DEBUG
2615 var iter = coff.globals.iterator();
2616 while (iter.next()) |kv| {
2617 if (kv.value_ptr.* == target_si) {
2618 log.warn("creating reloc but there is no symbol table entry yet `{s}` {d}!", .{ kv.key_ptr.name.toSlice(coff), target_si });
2619 break;
2620 }
2621 } else {
2622 log.warn("creating reloc but there is no symbol table entry yet (not global) {d}!", .{target_si});
2623 }
2624 // DEBUG
2625
2626 // TODO: Check all relocs at the end and assert if some of sri == .none
2627 entry.symbol_table_index = 0;
2628 },
2629 else => |sti| {
2630 entry.symbol_table_index = sti.unwrap().?;
2631 },
2632 }
2633
2634 // const reloc_type: Reloc.Type = switch (coff.targetLoad(&coff.headerPtr().machine)) {
2635 // else => unreachableaddrelo,
2636 // .AMD64 => .{ .AMD64 = .REL32 },
2637 // .I386 => .{ .I386 = .REL32 },
2638 // };
2639
2640 entry.type = @bitCast(@"type"); //@bitCast(reloc_type);
2641 if (coff.targetEndian() != native_endian)
2642 std.mem.byteSwapAllFieldsAligned(std.coff.Relocation, .@"2", entry);
26432656
2644 break :sri sri;2657 break :sri sri;
2645 },2658 },
...@@ -2709,20 +2722,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -2709,20 +2722,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
2709 const sym = si.get(coff);2722 const sym = si.get(coff);
2710 sym.ni = ni;2723 sym.ni = ni;
2711 sym.section_number = sec_si.get(coff).section_number;2724 sym.section_number = sec_si.get(coff).section_number;
2712
2713 // if (!isImage(coff)) {
2714 // try coff.addSymbolTableEntry(
2715 // .{ .bytes = nav.fqn.toSlice(ip) },
2716 // si,
2717 // .{ .global = .{ .external = false, .import = false } },
2718 // );
2719 // }
2720 },2725 },
2721 else => si.deleteLocationRelocs(coff),2726 else => si.deleteLocationRelocs(coff),
2722 }2727 }
2723 const sym = si.get(coff);2728 const sym = si.get(coff);
2724 assert(sym.loc_relocs == .none);2729 assert(sym.loc_relocs == .none);
2725 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);2730 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
2731 if (sym.target_relocs != .none)
2732 _ = try coff.updateSymbolTableEntry(si);
2733
2726 break :ni sym.ni;2734 break :ni sym.ni;
2727 };2735 };
27282736
...@@ -2744,6 +2752,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -2744,6 +2752,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
2744 si.applyLocationRelocs(coff);2752 si.applyLocationRelocs(coff);
2745 }2753 }
27462754
2755 // TODO: Did my MappedFile resize change affect this?
2747 if (nav.resolved.?.@"linksection".unwrap()) |_| {2756 if (nav.resolved.?.@"linksection".unwrap()) |_| {
2748 try ni.resize(&coff.mf, gpa, si.get(coff).size);2757 try ni.resize(&coff.mf, gpa, si.get(coff).size);
2749 var parent_ni = ni;2758 var parent_ni = ni;
...@@ -2846,20 +2855,14 @@ fn updateFuncInner(...@@ -2846,20 +2855,14 @@ fn updateFuncInner(
2846 const sym = si.get(coff);2855 const sym = si.get(coff);
2847 sym.ni = ni;2856 sym.ni = ni;
2848 sym.section_number = sec_si.get(coff).section_number;2857 sym.section_number = sec_si.get(coff).section_number;
2849 //
2850 // if (!isImage(coff)) {
2851 // try coff.addSymbolTableEntry(
2852 // .{ .bytes = nav.fqn.toSlice(ip) },
2853 // si,
2854 // .{ .global = .{ .external = false, .import = false } },
2855 // );
2856 // }
2857 },2858 },
2858 else => si.deleteLocationRelocs(coff),2859 else => si.deleteLocationRelocs(coff),
2859 }2860 }
2860 const sym = si.get(coff);2861 const sym = si.get(coff);
2861 assert(sym.loc_relocs == .none);2862 assert(sym.loc_relocs == .none);
2862 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);2863 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
2864 if (sym.target_relocs != .none)
2865 _ = try coff.updateSymbolTableEntry(si);
2863 break :ni sym.ni;2866 break :ni sym.ni;
2864 };2867 };
28652868
...@@ -3037,7 +3040,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -3037,7 +3040,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
3037 }3040 }
3038 if (coff.global_pending_index < coff.globals.count()) {3041 if (coff.global_pending_index < coff.globals.count()) {
3039 const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid };3042 const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid };
3040 const gmi: Node.GlobalMapIndex = @enumFromInt(coff.global_pending_index);3043 const gmi: Node.GlobalMapIndex = .wrap(coff.global_pending_index);
3041 coff.global_pending_index += 1;3044 coff.global_pending_index += 1;
3042 const sub_prog_node = coff.synth_prog_node.start(3045 const sub_prog_node = coff.synth_prog_node.start(
3043 gmi.globalName(coff).name.toSlice(coff),3046 gmi.globalName(coff).name.toSlice(coff),
...@@ -3187,19 +3190,6 @@ fn flushUav(...@@ -3187,19 +3190,6 @@ fn flushUav(
3187 coff.nodes.appendAssumeCapacity(.{ .uav = umi });3190 coff.nodes.appendAssumeCapacity(.{ .uav = umi });
3188 sym.ni = ni;3191 sym.ni = ni;
3189 sym.section_number = sec_si.get(coff).section_number;3192 sym.section_number = sec_si.get(coff).section_number;
3190
3191 // if (!isImage(coff)) {
3192 // var name: [12]u8 = undefined;
3193 // var w = std.Io.Writer.fixed(&name);
3194 // w.print("uav.{x}", .{umi}) catch unreachable;
3195 // // TODO: This is a bit awkward, the symbol table requires a name, and we
3196 // // need to be in the sym table to be the target of relocs
3197 // try coff.addSymbolTableEntry(
3198 // .{ .bytes = w.buffered() },
3199 // si,
3200 // .{ .global = .{ .external = false, .import = false } },
3201 // );
3202 // }
3203 },3193 },
3204 else => {3194 else => {
3205 if (si.get(coff).ni.alignment(&coff.mf).order(uav_align.toStdMem()).compare(.gte))3195 if (si.get(coff).ni.alignment(&coff.mf).order(uav_align.toStdMem()).compare(.gte))
...@@ -3210,6 +3200,9 @@ fn flushUav(...@@ -3210,6 +3200,9 @@ fn flushUav(
3210 const sym = si.get(coff);3200 const sym = si.get(coff);
3211 assert(sym.loc_relocs == .none);3201 assert(sym.loc_relocs == .none);
3212 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);3202 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
3203 if (sym.target_relocs != .none)
3204 _ = try coff.updateSymbolTableEntry(si);
3205
3213 break :ni sym.ni;3206 break :ni sym.ni;
3214 };3207 };
32153208
...@@ -3238,11 +3231,14 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {...@@ -3238,11 +3231,14 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {
3238 log.debug("flushGlobal({s}, {?s}) = {d}", .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), gmi.symbol(coff) });3231 log.debug("flushGlobal({s}, {?s}) = {d}", .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), gmi.symbol(coff) });
32393232
3240 if (!coff.isImage()) {3233 if (!coff.isImage()) {
3241 try coff.addSymbolTableEntry(3234 const si = gmi.symbol(coff);
3242 .{ .string = gn.name },3235 assert(try coff.updateSymbolTableEntry(si) != .none);
3243 gmi.symbol(coff),3236 if (si.get(coff).ni != .none)
3244 .global,3237 try coff.ensureMemberSymbol(
3245 );3238 gn.name,
3239 coff.getNode(Node.known.zcu_member).archive_member,
3240 si,
3241 );
32463242
3247 return;3243 return;
3248 }3244 }
...@@ -3707,9 +3703,9 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3707,9 +3703,9 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3707 try coff.virtualSlide(section_index + 1, sym.rva + virtual_size);3703 try coff.virtualSlide(section_index + 1, sym.rva + virtual_size);
3708 }3704 }
37093705
3710 if (coff.isArchive()) {3706 if (!coff.isImage()) {
3711 coff.targetStore(3707 coff.targetStore(
3712 &coff.symbolAuxSectionDefinitionPtr(si).length,3708 &coff.symbolTableSectionAuxEntryPtr(si).length,
3713 @intCast(size),3709 @intCast(size),
3714 );3710 );
3715 }3711 }
src/link/MappedFile.zig+3-3
...@@ -696,7 +696,7 @@ fn shrinkNode(...@@ -696,7 +696,7 @@ fn shrinkNode(
696 gpa: std.mem.Allocator,696 gpa: std.mem.Allocator,
697 ni: Node.Index,697 ni: Node.Index,
698 size: u64,698 size: u64,
699 shrink_next: bool,699 shift_next: bool,
700) !void {700) !void {
701 const node = ni.get(mf);701 const node = ni.get(mf);
702 const old_offset, _ = node.location().resolve(mf);702 const old_offset, _ = node.location().resolve(mf);
...@@ -714,7 +714,7 @@ fn shrinkNode(...@@ -714,7 +714,7 @@ fn shrinkNode(
714 try mf.updates.ensureUnusedCapacity(gpa, 2);714 try mf.updates.ensureUnusedCapacity(gpa, 2);
715715
716 ni.setLocationAssumeCapacity(mf, old_offset, size);716 ni.setLocationAssumeCapacity(mf, old_offset, size);
717 if (!shrink_next or node.next == .none) return;717 if (!shift_next or node.next == .none) return;
718718
719 const next = node.next.get(mf);719 const next = node.next.get(mf);
720 const old_next_offset, const next_size = next.location().resolve(mf);720 const old_next_offset, const next_size = next.location().resolve(mf);
...@@ -738,7 +738,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -738,7 +738,7 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
738 const node = ni.get(mf);738 const node = ni.get(mf);
739 const old_offset, const old_size = node.location().resolve(mf);739 const old_offset, const old_size = node.location().resolve(mf);
740 const new_size = node.flags.alignment.forward(@intCast(requested_size));740 const new_size = node.flags.alignment.forward(@intCast(requested_size));
741 if (new_size <= old_size) return;741 //if (new_size <= old_size) return;
742742
743 // Resize the entire file743 // Resize the entire file
744 if (ni == Node.Index.root) {744 if (ni == Node.Index.root) {