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
log8c2737fd95f46d43a13a69a0a2cdedecb61a1157
treed446834156daff8b047d6f7096871abd835430c5
parentf81bd30057d6a1d1d50851b65a644aa86296cd4c

Coff: Start working on symbol and relocation tables


2 files changed, 339 insertions(+), 139 deletions(-)

src/codegen/x86_64/Emit.zig+6-6
...@@ -161,13 +161,13 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -161,13 +161,13 @@ pub fn emitMir(emit: *Emit) Error!void {
161 .type = .FUNC,161 .type = .FUNC,
162 }) else if (emit.bin_file.cast(.macho)) |macho_file|162 }) else if (emit.bin_file.cast(.macho)) |macho_file|
163 @enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))163 @enumFromInt(try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null))
164 else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(164 else if (emit.bin_file.cast(.coff2)) |coff| @enumFromInt(@intFromEnum(try coff.globalSymbol(.{
165 extern_func.toSlice(&emit.lower.mir).?,165 .name = extern_func.toSlice(&emit.lower.mir).?,
166 switch (comp.compiler_rt_strat) {166 .lib_name = switch (comp.compiler_rt_strat) {
167 .none, .lib, .obj, .zcu => null,167 .none, .lib, .obj, .zcu => null,
168 .dyn_lib => "compiler_rt",168 .dyn_lib => "compiler_rt",
169 },169 },
170 ))) else return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),170 }))) else return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
171 .is_extern = true,171 .is_extern = true,
172 } },172 } },
173 },173 },
...@@ -374,7 +374,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -374,7 +374,7 @@ pub fn emitMir(emit: *Emit) Error!void {
374 .op_index = 1,374 .op_index = 1,
375 .target = .{ .symbol = .{375 .target = .{ .symbol = .{
376 .symbol = @enumFromInt(@intFromEnum(376 .symbol = @enumFromInt(@intFromEnum(
377 try coff.globalSymbol("__tls_index", null),377 try coff.globalSymbol(.{ .name = "__tls_index" }),
378 )),378 )),
379 .is_extern = false,379 .is_extern = false,
380 } },380 } },
...@@ -409,7 +409,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -409,7 +409,7 @@ pub fn emitMir(emit: *Emit) Error!void {
409 .op_index = 1,409 .op_index = 1,
410 .target = .{ .symbol = .{410 .target = .{ .symbol = .{
411 .symbol = @enumFromInt(@intFromEnum(411 .symbol = @enumFromInt(@intFromEnum(
412 try coff.globalSymbol("_tls_index", null),412 try coff.globalSymbol(.{ .name = "_tls_index" }),
413 )),413 )),
414 .is_extern = false,414 .is_extern = false,
415 } },415 } },
src/link/Coff.zig+333-133
...@@ -38,7 +38,7 @@ strings: std.HashMapUnmanaged(...@@ -38,7 +38,7 @@ strings: std.HashMapUnmanaged(
38 std.hash_map.default_max_load_percentage,38 std.hash_map.default_max_load_percentage,
39),39),
40string_bytes: std.ArrayList(u8),40string_bytes: std.ArrayList(u8),
41section_table: std.ArrayList(Symbol.Index),41section_table: std.ArrayList(Section),
42pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index),42pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index),
43object_section_table: std.array_hash_map.Auto(String, Symbol.Index),43object_section_table: std.array_hash_map.Auto(String, Symbol.Index),
44symbols: std.ArrayList(Symbol),44symbols: std.ArrayList(Symbol),
...@@ -161,8 +161,11 @@ pub const Node = union(enum) {...@@ -161,8 +161,11 @@ pub const Node = union(enum) {
161 symbol_table_entry,161 symbol_table_entry,
162 // Archives and objects only162 // Archives and objects only
163 string_table,163 string_table,
164 // Archives and objects only
165 relocation_table: Symbol.SectionNumber,
166 relocation_table_entry: Reloc.Index,
164167
165 image_section: Symbol.Index, // TODO: image_section -> section168 image_section: Symbol.Index, // TODO: rename image_section -> section
166169
167 /// Images only170 /// Images only
168 import_directory_table,171 import_directory_table,
...@@ -318,9 +321,7 @@ pub const Member = struct {...@@ -318,9 +321,7 @@ pub const Member = struct {
318 kind: Kind,321 kind: Kind,
319 header_ni: MappedFile.Node.Index,322 header_ni: MappedFile.Node.Index,
320 content_ni: MappedFile.Node.Index,323 content_ni: MappedFile.Node.Index,
321 // Maps symbols contained in this member to their index in the first linker member's symbol table324 first_linker_indices: std.AutoArrayHashMapUnmanaged(Symbol.Index, FirstLinkerIndex),
322 // TODO: This could contain information about the name string if we need
323 symbol_offsets: std.AutoArrayHashMapUnmanaged(Symbol.Index, u33),
324325
325 pub const Kind = enum {326 pub const Kind = enum {
326 first_linker,327 first_linker,
...@@ -343,6 +344,10 @@ pub const Member = struct {...@@ -343,6 +344,10 @@ pub const Member = struct {
343 }344 }
344 };345 };
345346
347 pub const FirstLinkerIndex = enum(u32) {
348 _,
349 };
350
346 pub fn headerPtr(member: *Member, coff: *Coff) *std.coff.ArchiveMemberHeader {351 pub fn headerPtr(member: *Member, coff: *Coff) *std.coff.ArchiveMemberHeader {
347 return @ptrCast(@alignCast(member.header_ni.slice(&coff.mf)));352 return @ptrCast(@alignCast(member.header_ni.slice(&coff.mf)));
348 }353 }
...@@ -458,14 +463,12 @@ pub const SymbolTable = struct {...@@ -458,14 +463,12 @@ pub const SymbolTable = struct {
458463
459 pub const Entry = struct {464 pub const Entry = struct {
460 entry_si: Symbol.Index,465 entry_si: Symbol.Index,
461 index: Index,466 sti: Index, // TODO: Is this redundant now that we store it on symbol?
462 };467 };
463468
464 pub const Add = union(enum) {469 pub const Add = union(enum) {
465 section,470 section,
466 global: struct {471 global,
467 import: bool,
468 },
469 };472 };
470473
471 pub const SymbolName = union(enum) {474 pub const SymbolName = union(enum) {
...@@ -473,12 +476,25 @@ pub const SymbolTable = struct {...@@ -473,12 +476,25 @@ pub const SymbolTable = struct {
473 long: StringIndex,476 long: StringIndex,
474 };477 };
475478
476 // Symbol.Index does not map 1:1 with SymbolTable.Index due to auxiliary entries479 // Symbol.Index does not map 1:1 with SymbolTable.Index due to
480 // variable number of auxiliary entries that may trail each symbol
477 pub const Index = enum(u32) {481 pub const Index = enum(u32) {
482 none,
478 _,483 _,
479484
485 pub fn wrap(i: ?u32) Index {
486 return @enumFromInt((i orelse return .none) + 1);
487 }
488
489 pub fn unwrap(sti: Index) ?u32 {
490 return switch (sti) {
491 .none => null,
492 _ => @intFromEnum(sti) - 1,
493 };
494 }
495
480 pub fn get(sti: SymbolTable.Index, coff: *Coff) *Entry {496 pub fn get(sti: SymbolTable.Index, coff: *Coff) *Entry {
481 return &coff.symbol_table.entries.values()[@intFromEnum(sti)];497 return &coff.symbol_table.entries.values()[sti.unwrap().?];
482 }498 }
483 };499 };
484500
...@@ -607,6 +623,37 @@ pub const String = enum(u32) {...@@ -607,6 +623,37 @@ pub const String = enum(u32) {
607 }623 }
608};624};
609625
626pub const Section = struct {
627 si: Symbol.Index,
628 relocation_table_ni: MappedFile.Node.Index,
629
630 pub const RelocationIndex = enum(u32) {
631 none,
632 _,
633
634 pub fn wrap(i: ?u32) RelocationIndex {
635 return @enumFromInt((i orelse return .none) + 1);
636 }
637
638 pub fn unwrap(sri: RelocationIndex) ?u32 {
639 return switch (sri) {
640 .none => null,
641 _ => @intFromEnum(sri) - 1,
642 };
643 }
644
645 pub fn entry(
646 sri: RelocationIndex,
647 coff: *Coff,
648 sn: Symbol.SectionNumber,
649 ) ?*align(2) std.coff.Relocation {
650 if (sri == .none) return null;
651 const table_slice = sn.section(coff).relocation_table_ni.slice(&coff.mf);
652 return @ptrCast(@alignCast(&table_slice[sri.unwrap().? * std.coff.Relocation.sizeOf()]));
653 }
654 };
655};
656
610pub const GlobalName = struct { name: String, lib_name: String.Optional };657pub const GlobalName = struct { name: String, lib_name: String.Optional };
611658
612pub const Symbol = struct {659pub const Symbol = struct {
...@@ -618,9 +665,9 @@ pub const Symbol = struct {...@@ -618,9 +665,9 @@ pub const Symbol = struct {
618 /// Relocations targeting this symbol665 /// Relocations targeting this symbol
619 target_relocs: Reloc.Index,666 target_relocs: Reloc.Index,
620 section_number: SectionNumber,667 section_number: SectionNumber,
668 sti: SymbolTable.Index,
621 unused0: u32 = 0,669 unused0: u32 = 0,
622 unused1: u32 = 0,670 unused1: u16 = 0,
623 unused2: u16 = 0,
624671
625 pub const SectionNumber = enum(i16) {672 pub const SectionNumber = enum(i16) {
626 UNDEFINED = 0,673 UNDEFINED = 0,
...@@ -633,7 +680,11 @@ pub const Symbol = struct {...@@ -633,7 +680,11 @@ pub const Symbol = struct {
633 }680 }
634681
635 pub fn symbol(sn: SectionNumber, coff: *const Coff) Symbol.Index {682 pub fn symbol(sn: SectionNumber, coff: *const Coff) Symbol.Index {
636 return coff.section_table.items[sn.toIndex()];683 return sn.section(coff).si;
684 }
685
686 pub fn section(sn: SectionNumber, coff: *const Coff) *Section {
687 return &coff.section_table.items[sn.toIndex()];
637 }688 }
638689
639 pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader {690 pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader {
...@@ -692,6 +743,17 @@ pub const Symbol = struct {...@@ -692,6 +743,17 @@ pub const Symbol = struct {
692 }743 }
693 sym.loc_relocs = .none;744 sym.loc_relocs = .none;
694 }745 }
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 }
695 };757 };
696758
697 comptime {759 comptime {
...@@ -705,7 +767,7 @@ pub const Reloc = extern struct {...@@ -705,7 +767,7 @@ pub const Reloc = extern struct {
705 next: Reloc.Index,767 next: Reloc.Index,
706 loc: Symbol.Index,768 loc: Symbol.Index,
707 target: Symbol.Index,769 target: Symbol.Index,
708 unused: u32,770 sri: Section.RelocationIndex,
709 offset: u64,771 offset: u64,
710 addend: i64,772 addend: i64,
711773
...@@ -725,8 +787,8 @@ pub const Reloc = extern struct {...@@ -725,8 +787,8 @@ pub const Reloc = extern struct {
725 none = std.math.maxInt(u32),787 none = std.math.maxInt(u32),
726 _,788 _,
727789
728 pub fn get(si: Reloc.Index, coff: *Coff) *Reloc {790 pub fn get(ri: Reloc.Index, coff: *Coff) *Reloc {
729 return &coff.relocs.items[@intFromEnum(si)];791 return &coff.relocs.items[@intFromEnum(ri)];
730 }792 }
731 };793 };
732794
...@@ -861,6 +923,8 @@ pub const Reloc = extern struct {...@@ -861,6 +923,8 @@ pub const Reloc = extern struct {
861 }923 }
862924
863 pub fn delete(reloc: *Reloc, coff: *Coff) void {925 pub fn delete(reloc: *Reloc, coff: *Coff) void {
926 // TODO: Need to remove this from the COFF relocation table (remove swap)
927
864 switch (reloc.prev) {928 switch (reloc.prev) {
865 .none => {929 .none => {
866 const target = reloc.target.get(coff);930 const target = reloc.target.get(coff);
...@@ -1021,10 +1085,11 @@ pub fn deinit(coff: *Coff) void {...@@ -1021,10 +1085,11 @@ pub fn deinit(coff: *Coff) void {
1021 const gpa = coff.base.comp.gpa;1085 const gpa = coff.base.comp.gpa;
1022 coff.mf.deinit(gpa);1086 coff.mf.deinit(gpa);
1023 coff.nodes.deinit(gpa);1087 coff.nodes.deinit(gpa);
1024 // TODO: Update this
1025 coff.long_names_table.entries.deinit(gpa);1088 coff.long_names_table.entries.deinit(gpa);
1026 coff.import_table.entries.deinit(gpa);1089 coff.import_table.entries.deinit(gpa);
1027 coff.export_table.entries.deinit(gpa);1090 coff.export_table.entries.deinit(gpa);
1091 coff.symbol_table.string_offsets.deinit(gpa);
1092 coff.symbol_table.entries.deinit(gpa);
1028 coff.strings.deinit(gpa);1093 coff.strings.deinit(gpa);
1029 coff.string_bytes.deinit(gpa);1094 coff.string_bytes.deinit(gpa);
1030 coff.section_table.deinit(gpa);1095 coff.section_table.deinit(gpa);
...@@ -1356,9 +1421,10 @@ fn initHeaders(...@@ -1356,9 +1421,10 @@ fn initHeaders(
1356 }));1421 }));
1357 coff.nodes.appendAssumeCapacity(.section_table);1422 coff.nodes.appendAssumeCapacity(.section_table);
13581423
1424 // TODO: These two nodes could be inside one movable node
1359 const symbol_table_ni = Node.known.symbol_table;1425 const symbol_table_ni = Node.known.symbol_table;
1360 assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{1426 assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{
1361 .alignment = .@"4",1427 .alignment = .@"2",
1362 .fixed = true,1428 .fixed = true,
1363 .moved = true,1429 .moved = true,
1364 }));1430 }));
...@@ -1366,7 +1432,8 @@ fn initHeaders(...@@ -1366,7 +1432,8 @@ fn initHeaders(
13661432
1367 const string_table_ni = Node.known.string_table;1433 const string_table_ni = Node.known.string_table;
1368 assert(string_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{1434 assert(string_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{
1369 .size = @sizeOf(u32),1435 .alignment = .@"2",
1436 .size = if (!is_image) @sizeOf(u32) else 0,
1370 .fixed = true,1437 .fixed = true,
1371 .resized = true,1438 .resized = true,
1372 }));1439 }));
...@@ -1382,6 +1449,7 @@ fn initHeaders(...@@ -1382,6 +1449,7 @@ fn initHeaders(
1382 .loc_relocs = .none,1449 .loc_relocs = .none,
1383 .target_relocs = .none,1450 .target_relocs = .none,
1384 .section_number = .UNDEFINED,1451 .section_number = .UNDEFINED,
1452 .sti = .none,
1385 };1453 };
1386 assert(try coff.addSection(".data", .{1454 assert(try coff.addSection(".data", .{
1387 .CNT_INITIALIZED_DATA = true,1455 .CNT_INITIALIZED_DATA = true,
...@@ -1533,6 +1601,8 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {...@@ -1533,6 +1601,8 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
1533 .symbol_table,1601 .symbol_table,
1534 .symbol_table_entry,1602 .symbol_table_entry,
1535 .string_table,1603 .string_table,
1604 .relocation_table,
1605 .relocation_table_entry,
1536 => unreachable,1606 => unreachable,
1537 .image_section => |si| si,1607 .image_section => |si| si,
1538 .import_directory_table => break :parent_rva coff.targetLoad(1608 .import_directory_table => break :parent_rva coff.targetLoad(
...@@ -1721,17 +1791,18 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {...@@ -1721,17 +1791,18 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader {
17211791
1722pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) *align(2) std.coff.Symbol {1792pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) *align(2) std.coff.Symbol {
1723 return @ptrCast(@alignCast(1793 return @ptrCast(@alignCast(
1724 &Node.known.symbol_table.slice(&coff.mf)[@intFromEnum(sti) * std.coff.Symbol.sizeOf()],1794 &Node.known.symbol_table.slice(&coff.mf)[sti.unwrap().? * std.coff.Symbol.sizeOf()],
1725 ));1795 ));
1726}1796}
17271797
1728pub fn symbolAuxSectionDefinitionPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition {1798pub fn symbolAuxSectionDefinitionPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition {
1729 const sti = coff.symbol_table.entries.get(si).?.index;1799 const sti = coff.symbol_table.entries.get(si).?.sti;
1730
1731 const symbol = coff.symbolTableEntryPtr(sti);1800 const symbol = coff.symbolTableEntryPtr(sti);
1732 assert(symbol.storage_class == .STATIC and symbol.number_of_aux_symbols == 1);1801 assert(symbol.storage_class == .STATIC and symbol.number_of_aux_symbols == 1);
17331802
1734 return @ptrCast(symbolTableEntryPtr(coff, @enumFromInt(@intFromEnum(sti) + 1)));1803 return @ptrCast(@alignCast(
1804 &Node.known.symbol_table.slice(&coff.mf)[(sti.unwrap().? + 1) * std.coff.Symbol.sizeOf()],
1805 ));
1735}1806}
17361807
1737pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 {1808pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 {
...@@ -1772,6 +1843,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -1772,6 +1843,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
1772 .loc_relocs = .none,1843 .loc_relocs = .none,
1773 .target_relocs = .none,1844 .target_relocs = .none,
1774 .section_number = .UNDEFINED,1845 .section_number = .UNDEFINED,
1846 .sti = .none,
1775 };1847 };
1776 return @enumFromInt(coff.symbols.items.len);1848 return @enumFromInt(coff.symbols.items.len);
1777}1849}
...@@ -1808,27 +1880,22 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {...@@ -1808,27 +1880,22 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String {
1808 return @enumFromInt(gop.key_ptr.*);1880 return @enumFromInt(gop.key_ptr.*);
1809}1881}
18101882
1811pub fn globalSymbol(coff: *Coff, name: []const u8, lib_name: ?[]const u8) !Symbol.Index {1883pub fn globalSymbol(coff: *Coff, opts: struct {
1812 return (try getOrPutGlobalSymbol(coff, name, lib_name)).value_ptr.*;
1813}
1814
1815fn getOrPutGlobalSymbol(
1816 coff: *Coff,
1817 name: []const u8,1884 name: []const u8,
1818 lib_name: ?[]const u8,1885 lib_name: ?[]const u8 = null,
1819) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult {1886}) !Symbol.Index {
1820 const gpa = coff.base.comp.gpa;1887 const gpa = coff.base.comp.gpa;
1821 try coff.symbols.ensureUnusedCapacity(gpa, 1);1888 try coff.symbols.ensureUnusedCapacity(gpa, 1);
1822 const sym_gop = try coff.globals.getOrPut(gpa, .{1889 const sym_gop = try coff.globals.getOrPut(gpa, .{
1823 .name = try coff.getOrPutString(name),1890 .name = try coff.getOrPutString(opts.name),
1824 .lib_name = try coff.getOrPutOptionalString(lib_name),1891 .lib_name = try coff.getOrPutOptionalString(opts.lib_name),
1825 });1892 });
1826 if (!sym_gop.found_existing) {1893 if (!sym_gop.found_existing) {
1827 sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();1894 sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
1828 coff.synth_prog_node.increaseEstimatedTotalItems(1);1895 coff.synth_prog_node.increaseEstimatedTotalItems(1);
1829 }1896 }
18301897
1831 return sym_gop;1898 return sym_gop.value_ptr.*;
1832}1899}
18331900
1834fn navSection(1901fn navSection(
...@@ -1870,10 +1937,10 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na...@@ -1870,10 +1937,10 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na
1870pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {1937pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
1871 const ip = &zcu.intern_pool;1938 const ip = &zcu.intern_pool;
1872 const nav = ip.getNav(nav_index);1939 const nav = ip.getNav(nav_index);
1873 if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(1940 if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(.{
1874 @"extern".name.toSlice(ip),1941 .name = @"extern".name.toSlice(ip),
1875 @"extern".lib_name.toSlice(ip),1942 .lib_name = @"extern".lib_name.toSlice(ip),
1876 );1943 });
1877 const nmi = try coff.navMapIndex(zcu, nav_index);1944 const nmi = try coff.navMapIndex(zcu, nav_index);
1878 return nmi.symbol(coff);1945 return nmi.symbol(coff);
1879}1946}
...@@ -1926,7 +1993,7 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol....@@ -1926,7 +1993,7 @@ pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.
1926 reloc_info.addend,1993 reloc_info.addend,
1927 switch (coff.targetLoad(&coff.headerPtr().machine)) {1994 switch (coff.targetLoad(&coff.headerPtr().machine)) {
1928 else => unreachable,1995 else => unreachable,
1929 .AMD64 => .{ .AMD64 = .ADDR64 },1996 .AMD64 => .{ .AMD64 = .ADDR64 }, // TODO: Switch to REL32 for obj/archive
1930 .I386 => .{ .I386 = .DIR32 },1997 .I386 => .{ .I386 = .DIR32 },
1931 },1998 },
1932 );1999 );
...@@ -1941,7 +2008,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member....@@ -1941,7 +2008,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member.
1941 const comp = coff.base.comp;2008 const comp = coff.base.comp;
1942 const gpa = comp.gpa;2009 const gpa = comp.gpa;
19432010
1944 // TODO: These two nodes could to be inside a movable node? Only if coff or import2011 // TODO: These two nodes could to be inside a movable node if kind == .coff|.import
19452012
1946 const header_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{2013 const header_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{
1947 .size = @sizeOf(std.coff.ArchiveMemberHeader),2014 .size = @sizeOf(std.coff.ArchiveMemberHeader),
...@@ -1967,7 +2034,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member....@@ -1967,7 +2034,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member.
1967 .kind = kind,2034 .kind = kind,
1968 .header_ni = header_ni,2035 .header_ni = header_ni,
1969 .content_ni = content_ni,2036 .content_ni = content_ni,
1970 .symbol_offsets = .empty,2037 .first_linker_indices = .empty,
1971 });2038 });
19722039
1973 coff.nodes.appendAssumeCapacity(.{ .archive_member_header = mi });2040 coff.nodes.appendAssumeCapacity(.{ .archive_member_header = mi });
...@@ -2028,9 +2095,9 @@ fn appendMemberSymbolString(...@@ -2028,9 +2095,9 @@ fn appendMemberSymbolString(
2028 name_slice[name.len] = 0;2095 name_slice[name.len] = 0;
2029}2096}
20302097
2031fn addMemberSymbol(2098fn ensureMemberSymbol(
2032 coff: *Coff,2099 coff: *Coff,
2033 name: String,2100 name: []const u8,
2034 mi: Member.Index,2101 mi: Member.Index,
2035 si: Symbol.Index,2102 si: Symbol.Index,
2036) !void {2103) !void {
...@@ -2038,66 +2105,69 @@ fn addMemberSymbol(...@@ -2038,66 +2105,69 @@ fn addMemberSymbol(
2038 const member = mi.get(coff);2105 const member = mi.get(coff);
2039 assert(member.kind == .coff);2106 assert(member.kind == .coff);
20402107
2041 const gop = try member.symbol_offsets.getOrPut(gpa, si);2108 const name_string = try coff.getOrPutString(name);
2109 const gop = try member.first_linker_indices.getOrPut(gpa, si);
2042 if (gop.found_existing) return;2110 if (gop.found_existing) return;
20432111
2044 // TODO: Detect duplicate names (ie. a name used by a symbol in another member, not the zcu since those already go through globals)2112 // TODO: Detect duplicate names (ie. a name used by a symbol in another member,
2113 // not the zcu since those already go through globals)
20452114
2046 const symbol_index = blk: {2115 const mfli: Member.FirstLinkerIndex = blk: {
2047 const num_symbols_ptr = coff.firstLinkerMemberNumSymbolsPtr();2116 const num_symbols_ptr = coff.firstLinkerMemberNumSymbolsPtr();
2048 const num_symbols = std.mem.toNative(u32, num_symbols_ptr.*, .big);2117 const num_symbols = std.mem.toNative(u32, num_symbols_ptr.*, .big);
2049 num_symbols_ptr.* = std.mem.nativeTo(u32, num_symbols + 1, .big);2118 num_symbols_ptr.* = std.mem.nativeTo(u32, num_symbols + 1, .big);
2050 break :blk num_symbols;2119 break :blk @enumFromInt(num_symbols);
2051 };2120 };
20522121
2053 gop.value_ptr.* = symbol_index;2122 gop.value_ptr.* = mfli;
2054 const name_slice = name.toSlice(coff);
20552123
2056 // Linker member fields are not modeled as nodes because MappedFile2124 // Linker member fields are not modeled as nodes because MappedFile
2057 // can't guarantee that they will be tightly packed after resizing2125 // can't guarantee that they will be tightly packed after resizing
20582126
2059 const new_string_table_size = coff.lib_string_len + name_slice.len + 1;2127 const new_string_table_size = coff.lib_string_len + name.len + 1;
2060 defer coff.lib_string_len = new_string_table_size;2128 defer coff.lib_string_len = new_string_table_size;
20612129
2062 {2130 {
2063 const old_header_size = @sizeOf(u32) + symbol_index * @sizeOf(u32);2131 const old_header_size = @sizeOf(u32) + @intFromEnum(mfli) * @sizeOf(u32);
2064 const new_header_size = old_header_size + @sizeOf(u32);2132 const new_header_size = old_header_size + @sizeOf(u32);
2065 try Node.known.first_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);2133 try Node.known.first_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);
20662134
2067 const slice = Node.known.first_linker_member.slice(&coff.mf);2135 const slice = Node.known.first_linker_member.slice(&coff.mf);
2068 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);2136 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
2069 @memcpy(slice[new_header_size + coff.lib_string_len ..][0 .. name_slice.len + 1], name_slice[0 .. name_slice.len + 1]);2137 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name.len], name[0..name.len]);
2138 slice[new_header_size + coff.lib_string_len + name.len] = 0;
20702139
2071 // New offset entry is written in flushMember2140 // New offset entry is written in flushMember
2072 }2141 }
20732142
2074 {2143 {
2075 const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());2144 const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
2076 const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + symbol_index * @sizeOf(u16);2145 const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @intFromEnum(mfli) * @sizeOf(u16);
2077 const new_header_size = old_header_size + @sizeOf(u16);2146 const new_header_size = old_header_size + @sizeOf(u16);
2078 try Node.known.second_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);2147 try Node.known.second_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size);
20792148
2080 const needs_sort = if (coff.lib_string_table.items.len > 0)2149 const needs_sort = if (coff.lib_string_table.items.len > 0)
2081 std.mem.lessThan(2150 std.mem.lessThan(
2082 u8,2151 u8,
2083 name_slice,2152 name,
2084 coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff),2153 coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff),
2085 )2154 )
2086 else2155 else
2087 false;2156 false;
20882157
2089 try coff.lib_string_table.append(gpa, name);2158 try coff.lib_string_table.append(gpa, name_string);
20902159
2091 const slice = Node.known.second_linker_member.slice(&coff.mf);2160 const slice = Node.known.second_linker_member.slice(&coff.mf);
2092 const num_symbols_ptr: *u32 = @ptrCast(@alignCast(slice[@sizeOf(u32) + num_members * @sizeOf(u32) ..]));2161 const num_symbols_ptr: *u32 = @ptrCast(@alignCast(slice[@sizeOf(u32) + num_members * @sizeOf(u32) ..]));
2093 coff.targetStore(num_symbols_ptr, symbol_index + 1);2162 coff.targetStore(num_symbols_ptr, @intFromEnum(mfli) + 1);
20942163
2095 if (needs_sort) {2164 if (needs_sort) {
2096 // The entire string table is rebuilt in flushMember after sorting2165 // The entire string table is rebuilt in flushMember after sorting
2097 coff.pending_members.putAssumeCapacity(Member.Index.second, {});2166 coff.pending_members.putAssumeCapacity(Member.Index.second, {});
2098 } else {2167 } else {
2099 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);2168 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
2100 @memcpy(slice[new_header_size + coff.lib_string_len ..][0 .. name_slice.len + 1], name_slice[0 .. name_slice.len + 1]);2169 @memcpy(slice[new_header_size + coff.lib_string_len ..][0..name.len], name[0..name.len]);
2170 slice[new_header_size + coff.lib_string_len + name.len] = 0;
2101 }2171 }
21022172
2103 // Indices in this table are 1-based2173 // Indices in this table are 1-based
...@@ -2120,6 +2190,7 @@ fn addSymbolTableEntry(...@@ -2120,6 +2190,7 @@ fn addSymbolTableEntry(
2120 assert(!coff.isImage());2190 assert(!coff.isImage());
2121 const gpa = coff.base.comp.gpa;2191 const gpa = coff.base.comp.gpa;
21222192
2193 // TODO: Avoid geOrPutString if it fits (only need to actually make the String for adding member symbol)
2123 const string, const name_slice = switch (name) {2194 const string, const name_slice = switch (name) {
2124 .bytes => |bytes| .{ try coff.getOrPutString(bytes), bytes },2195 .bytes => |bytes| .{ try coff.getOrPutString(bytes), bytes },
2125 .string => |s| .{ s, s.toSlice(coff) },2196 .string => |s| .{ s, s.toSlice(coff) },
...@@ -2140,11 +2211,18 @@ fn addSymbolTableEntry(...@@ -2140,11 +2211,18 @@ fn addSymbolTableEntry(
2140 break :index .{ .long = string_gop.value_ptr.* };2211 break :index .{ .long = string_gop.value_ptr.* };
2141 } else .{ .short = name_slice };2212 } else .{ .short = name_slice };
21422213
2143 const symbol_index = coff.targetLoad(&coff.headerPtr().number_of_symbols);2214 const old_num_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
2215
2216 const sym = si.get(coff);
2217 sym.sti = .wrap(old_num_symbols);
2218 si.updateRelocsSymbolTableIndex(coff);
2219
2220 log.debug("addSymbolTableEntry({s}, {d}) = {d}", .{ name_slice, si, sym.sti.unwrap().? });
2221
2222 // TODO: Can look at sym.ni to know what kind this is
2223
2144 const symbols_added: u8 = switch (add) {2224 const symbols_added: u8 = switch (add) {
2145 .section => count: {2225 .section => count: {
2146 const sym = si.get(coff);
2147
2148 try coff.nodes.ensureUnusedCapacity(gpa, 2);2226 try coff.nodes.ensureUnusedCapacity(gpa, 2);
2149 _ = try coff.addSymbolTableEntryAssumeCapacity(2227 _ = try coff.addSymbolTableEntryAssumeCapacity(
2150 symbol_name,2228 symbol_name,
...@@ -2159,28 +2237,32 @@ fn addSymbolTableEntry(...@@ -2159,28 +2237,32 @@ fn addSymbolTableEntry(
2159 );2237 );
21602238
2161 // Aux entry ields are updated by flushMoved / flushResized2239 // Aux entry ields are updated by flushMoved / flushResized
2162
2163 try coff.symbol_table.entries.put(gpa, si, .{2240 try coff.symbol_table.entries.put(gpa, si, .{
2164 .entry_si = .null,2241 .entry_si = .null,
2165 .index = @enumFromInt(symbol_index),2242 .sti = sym.sti,
2166 });2243 });
21672244
2168 break :count 2;2245 break :count 2;
2169 },2246 },
2170 .global => |global| count: {2247 .global => count: {
2171 const sym = si.get(coff);
2172
2173 try coff.nodes.ensureUnusedCapacity(gpa, 1);2248 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2174 try coff.symbols.ensureUnusedCapacity(gpa, 1);2249 try coff.symbols.ensureUnusedCapacity(gpa, 1);
21752250
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
2176 const entry_ni = try coff.addSymbolTableEntryAssumeCapacity(2259 const entry_ni = try coff.addSymbolTableEntryAssumeCapacity(
2177 symbol_name,2260 symbol_name,
2178 if (global.import) 0 else coff.computeNodeSectionOffset(sym.ni),2261 if (sym.ni == .none) 0 else coff.computeNodeSectionOffset(sym.ni),
2179 if (global.import) .UNDEFINED else sym.section_number,2262 sym.section_number,
2180 .{2263 .{
2181 .base_type = .NULL,2264 .base_type = .NULL,
2182 .complex_type = if (global.import or2265 .complex_type = if (Symbol.Index.text.get(coff).section_number == sym.section_number)
2183 Symbol.Index.text.get(coff).section_number == sym.section_number)
2184 .FUNCTION2266 .FUNCTION
2185 else2267 else
2186 .NULL,2268 .NULL,
...@@ -2198,24 +2280,27 @@ fn addSymbolTableEntry(...@@ -2198,24 +2280,27 @@ fn addSymbolTableEntry(
2198 entry_sym.section_number = .UNDEFINED;2280 entry_sym.section_number = .UNDEFINED;
2199 }2281 }
22002282
2201 try coff.addReloc(2283 if (sym.ni != .none) {
2202 entry_si,2284 // TODO: This serves to update the std.coff.Symbol.value (to VA of si), is this working?
2203 @offsetOf(std.coff.Symbol, "value"),2285 try coff.addReloc(
2204 si,2286 entry_si,
2205 0,2287 @offsetOf(std.coff.Symbol, "value"),
2206 .{ .AMD64 = .SECREL },2288 si,
2207 );2289 0,
2290 .{ .AMD64 = .SECREL }, // TODO: x86 too
2291 );
2292 }
22082293
2209 try coff.symbol_table.entries.put(gpa, si, .{2294 try coff.symbol_table.entries.put(gpa, si, .{
2210 .entry_si = entry_si,2295 .entry_si = entry_si,
2211 .index = @enumFromInt(symbol_index),2296 .sti = sym.sti,
2212 });2297 });
22132298
2214 break :count 1;2299 break :count 1;
2215 },2300 },
2216 };2301 };
22172302
2218 const new_num_symbols = symbol_index + symbols_added;2303 const new_num_symbols = old_num_symbols + symbols_added;
2219 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);2304 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);
2220 coff.symbol_table.pending_shrink =2305 coff.symbol_table.pending_shrink =
2221 Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf)[1] >2306 Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf)[1] >
...@@ -2243,15 +2328,6 @@ fn addSymbolTableEntryAssumeCapacity(...@@ -2243,15 +2328,6 @@ fn addSymbolTableEntryAssumeCapacity(
2243 coff.nodes.appendAssumeCapacity(.symbol_table_entry);2328 coff.nodes.appendAssumeCapacity(.symbol_table_entry);
22442329
2245 const entry: *align(2) std.coff.Symbol = @ptrCast(@alignCast(entry_ni.slice(&coff.mf)));2330 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) {2331 switch (name) {
2256 .short => |s| {2332 .short => |s| {
2257 @memcpy(entry.name[0..s.len], s);2333 @memcpy(entry.name[0..s.len], s);
...@@ -2264,6 +2340,13 @@ fn addSymbolTableEntryAssumeCapacity(...@@ -2264,6 +2340,13 @@ fn addSymbolTableEntryAssumeCapacity(
2264 },2340 },
2265 }2341 }
22662342
2343 // TODO: Would be ideal to assign entry.*, but given @sizeOf() > entry.sizeOf(), is that valid?
2344 entry.value = value;
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;
2349
2267 if (coff.targetEndian() != native_endian)2350 if (coff.targetEndian() != native_endian)
2268 std.mem.byteSwapAllFields(std.coff.SectionHeader, entry.*);2351 std.mem.byteSwapAllFields(std.coff.SectionHeader, entry.*);
22692352
...@@ -2310,7 +2393,10 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2310,7 +2393,10 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2310 });2393 });
23112394
2312 const si = coff.addSymbolAssumeCapacity();2395 const si = coff.addSymbolAssumeCapacity();
2313 coff.section_table.appendAssumeCapacity(si);2396 coff.section_table.appendAssumeCapacity(.{
2397 .si = si,
2398 .relocation_table_ni = .none,
2399 });
2314 coff.nodes.appendAssumeCapacity(.{ .image_section = si });2400 coff.nodes.appendAssumeCapacity(.{ .image_section = si });
2315 const section_table = coff.sectionTableSlice();2401 const section_table = coff.sectionTableSlice();
23162402
...@@ -2318,7 +2404,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags...@@ -2318,7 +2404,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags
2318 const virtual_size = coff.optionalHeaderField(.section_alignment);2404 const virtual_size = coff.optionalHeaderField(.section_alignment);
2319 const rva: u32 = switch (section_index) {2405 const rva: u32 = switch (section_index) {
2320 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),2406 0 => @intCast(Node.known.header.location(&coff.mf).resolve(&coff.mf)[1]),
2321 else => coff.section_table.items[section_index - 1].get(coff).rva +2407 else => coff.section_table.items[section_index - 1].si.get(coff).rva +
2322 coff.targetLoad(&section_table[section_index - 1].virtual_size),2408 coff.targetLoad(&section_table[section_index - 1].virtual_size),
2323 };2409 };
23242410
...@@ -2456,6 +2542,35 @@ fn objectSectionMapIndex(...@@ -2456,6 +2542,35 @@ fn objectSectionMapIndex(
2456 return osmi;2542 return osmi;
2457}2543}
24582544
2545fn ensureUnusedRelocCapacity(coff: *Coff, loc_si: Symbol.Index, len: usize) !void {
2546 const gpa = coff.base.comp.gpa;
2547
2548 try coff.relocs.ensureUnusedCapacity(gpa, len);
2549 if (isImage(coff)) return;
2550
2551 switch (loc_si.get(coff).section_number) {
2552 .UNDEFINED, .ABSOLUTE, .DEBUG => {},
2553 else => |sn| {
2554 const section = sn.section(coff);
2555 const header = sn.header(coff);
2556 const new_size = (len + coff.targetLoad(&header.number_of_relocations)) * std.coff.Relocation.sizeOf();
2557 if (section.relocation_table_ni == .none) {
2558 // The entry's length in the file is shorter than its @sizeOf
2559 try coff.nodes.ensureUnusedCapacity(gpa, 1);
2560 section.relocation_table_ni = try coff.mf.addLastChildNode(gpa, Node.known.zcu_member, .{
2561 .size = new_size,
2562 .alignment = .@"2",
2563 .moved = true,
2564 .resized = true,
2565 });
2566 coff.nodes.appendAssumeCapacity(.{ .relocation_table = sn });
2567 } else {
2568 try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
2569 }
2570 },
2571 }
2572}
2573
2459pub fn addReloc(2574pub fn addReloc(
2460 coff: *Coff,2575 coff: *Coff,
2461 loc_si: Symbol.Index,2576 loc_si: Symbol.Index,
...@@ -2464,16 +2579,80 @@ pub fn addReloc(...@@ -2464,16 +2579,80 @@ pub fn addReloc(
2464 addend: i64,2579 addend: i64,
2465 @"type": Reloc.Type,2580 @"type": Reloc.Type,
2466) !void {2581) !void {
2467 const gpa = coff.base.comp.gpa;
2468 const target = target_si.get(coff);2582 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 });
2584
2585 try ensureUnusedRelocCapacity(coff, loc_si, 1);
2586
2587 // TODO: The switch should be in an ensure capacity for reloc fn
2588
2589 const sri: Section.RelocationIndex = if (isImage(coff))
2590 .none
2591 else switch (loc_si.get(coff).section_number) {
2592 .UNDEFINED, .ABSOLUTE, .DEBUG => .none,
2593 else => |loc_sn| sri: {
2594 const header = loc_sn.header(coff);
2595 const old_num_relocations = coff.targetLoad(&header.number_of_relocations);
2596 const new_num_relocations = old_num_relocations + 1;
2597 coff.targetStore(
2598 &header.number_of_relocations,
2599 new_num_relocations,
2600 );
2601 coff.targetStore(
2602 &coff.symbolAuxSectionDefinitionPtr(loc_sn.symbol(coff)).number_of_relocations,
2603 new_num_relocations,
2604 );
2605
2606 const sri: Section.RelocationIndex = .wrap(old_num_relocations);
2607 const entry = sri.entry(coff, loc_sn).?;
2608
2609 entry.virtual_address = @intCast(offset);
2610 switch (target.sti) {
2611 .none => {
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);
2643
2644 break :sri sri;
2645 },
2646 };
2647
2469 const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len);2648 const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len);
2470 (try coff.relocs.addOne(gpa)).* = .{2649 coff.relocs.addOneAssumeCapacity().* = .{
2471 .type = @"type",2650 .type = @"type",
2472 .prev = .none,2651 .prev = .none,
2473 .next = target.target_relocs,2652 .next = target.target_relocs,
2474 .loc = loc_si,2653 .loc = loc_si,
2475 .target = target_si,2654 .target = target_si,
2476 .unused = 0,2655 .sri = sri,
2477 .offset = offset,2656 .offset = offset,
2478 .addend = addend,2657 .addend = addend,
2479 };2658 };
...@@ -2516,6 +2695,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -2516,6 +2695,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
25162695
2517 const nmi = try coff.navMapIndex(zcu, nav_index);2696 const nmi = try coff.navMapIndex(zcu, nav_index);
2518 const si = nmi.symbol(coff);2697 const si = nmi.symbol(coff);
2698 log.debug("updateNav({f}) = {d}", .{ nav.fqn.fmt(ip), si });
2519 const ni = ni: {2699 const ni = ni: {
2520 switch (si.get(coff).ni) {2700 switch (si.get(coff).ni) {
2521 .none => {2701 .none => {
...@@ -2530,7 +2710,13 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -2530,7 +2710,13 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
2530 sym.ni = ni;2710 sym.ni = ni;
2531 sym.section_number = sec_si.get(coff).section_number;2711 sym.section_number = sec_si.get(coff).section_number;
25322712
2533 // TODO: Add symbol table entry2713 // if (!isImage(coff)) {
2714 // try coff.addSymbolTableEntry(
2715 // .{ .bytes = nav.fqn.toSlice(ip) },
2716 // si,
2717 // .{ .global = .{ .external = false, .import = false } },
2718 // );
2719 // }
2534 },2720 },
2535 else => si.deleteLocationRelocs(coff),2721 else => si.deleteLocationRelocs(coff),
2536 }2722 }
...@@ -2660,6 +2846,14 @@ fn updateFuncInner(...@@ -2660,6 +2846,14 @@ fn updateFuncInner(
2660 const sym = si.get(coff);2846 const sym = si.get(coff);
2661 sym.ni = ni;2847 sym.ni = ni;
2662 sym.section_number = sec_si.get(coff).section_number;2848 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 // }
2663 },2857 },
2664 else => si.deleteLocationRelocs(coff),2858 else => si.deleteLocationRelocs(coff),
2665 }2859 }
...@@ -2993,6 +3187,19 @@ fn flushUav(...@@ -2993,6 +3187,19 @@ fn flushUav(
2993 coff.nodes.appendAssumeCapacity(.{ .uav = umi });3187 coff.nodes.appendAssumeCapacity(.{ .uav = umi });
2994 sym.ni = ni;3188 sym.ni = ni;
2995 sym.section_number = sec_si.get(coff).section_number;3189 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 // }
2996 },3203 },
2997 else => {3204 else => {
2998 if (si.get(coff).ni.alignment(&coff.mf).order(uav_align.toStdMem()).compare(.gte))3205 if (si.get(coff).ni.alignment(&coff.mf).order(uav_align.toStdMem()).compare(.gte))
...@@ -3028,21 +3235,14 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {...@@ -3028,21 +3235,14 @@ fn flushGlobal(coff: *Coff, pt: Zcu.PerThread, gmi: Node.GlobalMapIndex) !void {
3028 const comp = zcu.comp;3235 const comp = zcu.comp;
3029 const gpa = zcu.gpa;3236 const gpa = zcu.gpa;
3030 const gn = gmi.globalName(coff);3237 const gn = gmi.globalName(coff);
3238 log.debug("flushGlobal({s}, {?s}) = {d}", .{ gn.name.toSlice(coff), gn.lib_name.toSlice(coff), gmi.symbol(coff) });
30313239
3032 if (!coff.isImage()) {3240 if (!coff.isImage()) {
3033 // TODO: What about data imports?3241 try coff.addSymbolTableEntry(
30343242 .{ .string = gn.name },
3035 // const si = gmi.symbol(coff);3243 gmi.symbol(coff),
3036 // const sym = si.get(coff);3244 .global,
3037 // sym.section_number = Symbol.Index.text.get(coff).section_number;3245 );
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 // );
30463246
3047 return;3247 return;
3048 }3248 }
...@@ -3268,8 +3468,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3268,8 +3468,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
3268 .data_directories,3468 .data_directories,
3269 .section_table,3469 .section_table,
3270 .placeholder,3470 .placeholder,
32713471 .symbol_table_entry, // TODO: Need to impl this for symbol table updates to work?
3272 .symbol_table_entry,
3273 .string_table,3472 .string_table,
3274 => if (!coff.isArchive()) unreachable,3473 => if (!coff.isArchive()) unreachable,
3275 .symbol_table => {3474 .symbol_table => {
...@@ -3278,6 +3477,13 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3278,6 +3477,13 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
3278 @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),3477 @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),
3279 );3478 );
3280 },3479 },
3480 .relocation_table => |sn| {
3481 coff.targetStore(
3482 &sn.header(coff).pointer_to_relocations,
3483 @intCast(ni.location(&coff.mf).resolve(&coff.mf)[0]),
3484 );
3485 },
3486 .relocation_table_entry => {},
3281 .archive_member_header => |mi| {3487 .archive_member_header => |mi| {
3282 const member = mi.get(coff);3488 const member = mi.get(coff);
3283 switch (member.kind) {3489 switch (member.kind) {
...@@ -3439,7 +3645,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3439,7 +3645,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3439 ),3645 ),
3440 }3646 }
34413647
3442 if (size > coff.section_table.items[0].get(coff).rva) try coff.virtualSlide(3648 if (size > coff.section_table.items[0].si.get(coff).rva) try coff.virtualSlide(
3443 0,3649 0,
3444 std.mem.alignForward(3650 std.mem.alignForward(
3445 u32,3651 u32,
...@@ -3483,6 +3689,9 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {...@@ -3483,6 +3689,9 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
3483 assert(!coff.isImage());3689 assert(!coff.isImage());
3484 coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size));3690 coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size));
3485 },3691 },
3692 .relocation_table,
3693 .relocation_table_entry,
3694 => assert(!coff.isImage()),
3486 .image_section => |si| {3695 .image_section => |si| {
3487 const sym = si.get(coff);3696 const sym = si.get(coff);
3488 const section_index = sym.section_number.toIndex();3697 const section_index = sym.section_number.toIndex();
...@@ -3587,8 +3796,8 @@ fn flushMember(coff: *Coff, mi: Member.Index) !void {...@@ -3587,8 +3796,8 @@ fn flushMember(coff: *Coff, mi: Member.Index) !void {
3587 .coff => {3796 .coff => {
3588 const file_offset: u32 = @intCast(member.header_ni.fileLocation(&coff.mf, false).offset);3797 const file_offset: u32 = @intCast(member.header_ni.fileLocation(&coff.mf, false).offset);
3589 const first_linker_offsets = coff.firstLinkerMemberOffsetsSlice();3798 const first_linker_offsets = coff.firstLinkerMemberOffsetsSlice();
3590 for (member.symbol_offsets.values()) |offset_index|3799 for (member.first_linker_indices.values()) |mfli|
3591 first_linker_offsets[offset_index] = std.mem.nativeTo(u32, file_offset, .big);3800 first_linker_offsets[@intFromEnum(mfli)] = std.mem.nativeTo(u32, file_offset, .big);
3592 },3801 },
3593 }3802 }
3594}3803}
...@@ -3631,12 +3840,12 @@ fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {...@@ -3631,12 +3840,12 @@ fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {
3631 for (3840 for (
3632 coff.section_table.items[start_section_index..],3841 coff.section_table.items[start_section_index..],
3633 coff.sectionTableSlice()[start_section_index..],3842 coff.sectionTableSlice()[start_section_index..],
3634 ) |section_si, *section| {3843 ) |*section, *header| {
3635 const section_sym = section_si.get(coff);3844 const section_sym = section.si.get(coff);
3636 section_sym.rva = rva;3845 section_sym.rva = rva;
3637 coff.targetStore(&section.virtual_address, rva);3846 coff.targetStore(&header.virtual_address, rva);
3638 try section_sym.ni.childrenMoved(coff.base.comp.gpa, &coff.mf);3847 try section_sym.ni.childrenMoved(coff.base.comp.gpa, &coff.mf);
3639 rva += coff.targetLoad(&section.virtual_size);3848 rva += coff.targetLoad(&header.virtual_size);
3640 }3849 }
3641 switch (coff.optionalHeaderPtr()) {3850 switch (coff.optionalHeaderPtr()) {
3642 inline else => |optional_header| coff.targetStore(3851 inline else => |optional_header| coff.targetStore(
...@@ -3690,8 +3899,10 @@ fn updateExportsInner(...@@ -3690,8 +3899,10 @@ fn updateExportsInner(
3690 for (export_indices) |export_index| {3899 for (export_indices) |export_index| {
3691 const @"export" = export_index.ptr(zcu);3900 const @"export" = export_index.ptr(zcu);
3692 const name = @"export".opts.name.toSlice(ip);3901 const name = @"export".opts.name.toSlice(ip);
3693 const symbol_gop = try coff.getOrPutGlobalSymbol(name, null);3902 const export_si = try coff.globalSymbol(.{
3694 const export_si = symbol_gop.value_ptr.*;3903 .name = name,
3904 .lib_name = null,
3905 });
3695 const export_sym = export_si.get(coff);3906 const export_sym = export_si.get(coff);
3696 export_sym.ni = exported_ni;3907 export_sym.ni = exported_ni;
3697 export_sym.rva = exported_sym.rva;3908 export_sym.rva = exported_sym.rva;
...@@ -3707,20 +3918,6 @@ fn updateExportsInner(...@@ -3707,20 +3918,6 @@ fn updateExportsInner(
3707 std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);3918 std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory);
3708 }3919 }
37093920
3710 if (coff.isArchive()) {
3711 try coff.addMemberSymbol(
3712 symbol_gop.key_ptr.*.name,
3713 coff.getNode(Node.known.zcu_member).archive_member,
3714 export_si,
3715 );
3716
3717 try coff.addSymbolTableEntry(
3718 .{ .bytes = name },
3719 export_si,
3720 .{ .global = .{ .import = false } },
3721 );
3722 }
3723
3724 if (coff.export_table.ni == .none) continue;3921 if (coff.export_table.ni == .none) continue;
37253922
3726 const entries_ctx = ExportTable.Adapter{ .coff = coff };3923 const entries_ctx = ExportTable.Adapter{ .coff = coff };
...@@ -3809,7 +4006,7 @@ fn updateExportsInner(...@@ -3809,7 +4006,7 @@ fn updateExportsInner(
3809 gop.value_ptr.si = export_si;4006 gop.value_ptr.si = export_si;
3810 const reloc = gop.value_ptr.*.export_address_table_ri.get(coff);4007 const reloc = gop.value_ptr.*.export_address_table_ri.get(coff);
3811 reloc.target = export_si;4008 reloc.target = export_si;
3812 export_si.applyTargetRelocs(coff);4009 export_si.applyTargetRelocs(coff); // TODO: Potentially doing this twice, defer first one?
3813 }4010 }
3814 }4011 }
3815}4012}
...@@ -3818,6 +4015,9 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe...@@ -3818,6 +4015,9 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
3818 _ = coff;4015 _ = coff;
3819 _ = exported;4016 _ = exported;
3820 _ = name;4017 _ = name;
4018
4019 // TODO: Delete from first / second linker member table (remove swap?)
4020 // TODO: Delete from symbol table inside section
3821}4021}
38224022
3823fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void {4023fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void {