| ... | ... | @@ -38,7 +38,7 @@ strings: std.HashMapUnmanaged( |
| 38 | 38 | std.hash_map.default_max_load_percentage, |
| 39 | 39 | ), |
| 40 | 40 | string_bytes: std.ArrayList(u8), |
| 41 | | section_table: std.ArrayList(Symbol.Index), |
| 41 | section_table: std.ArrayList(Section), |
| 42 | 42 | pseudo_section_table: std.array_hash_map.Auto(String, Symbol.Index), |
| 43 | 43 | object_section_table: std.array_hash_map.Auto(String, Symbol.Index), |
| 44 | 44 | symbols: std.ArrayList(Symbol), |
| ... | ... | @@ -161,8 +161,11 @@ pub const Node = union(enum) { |
| 161 | 161 | symbol_table_entry, |
| 162 | 162 | // Archives and objects only |
| 163 | 163 | string_table, |
| 164 | // Archives and objects only |
| 165 | relocation_table: Symbol.SectionNumber, |
| 166 | relocation_table_entry: Reloc.Index, |
| 164 | 167 | |
| 165 | | image_section: Symbol.Index, // TODO: image_section -> section |
| 168 | image_section: Symbol.Index, // TODO: rename image_section -> section |
| 166 | 169 | |
| 167 | 170 | /// Images only |
| 168 | 171 | import_directory_table, |
| ... | ... | @@ -318,9 +321,7 @@ pub const Member = struct { |
| 318 | 321 | kind: Kind, |
| 319 | 322 | header_ni: MappedFile.Node.Index, |
| 320 | 323 | content_ni: MappedFile.Node.Index, |
| 321 | | // Maps symbols contained in this member to their index in the first linker member's symbol table |
| 322 | | // TODO: This could contain information about the name string if we need |
| 323 | | symbol_offsets: std.AutoArrayHashMapUnmanaged(Symbol.Index, u33), |
| 324 | first_linker_indices: std.AutoArrayHashMapUnmanaged(Symbol.Index, FirstLinkerIndex), |
| 324 | 325 | |
| 325 | 326 | pub const Kind = enum { |
| 326 | 327 | first_linker, |
| ... | ... | @@ -343,6 +344,10 @@ pub const Member = struct { |
| 343 | 344 | } |
| 344 | 345 | }; |
| 345 | 346 | |
| 347 | pub const FirstLinkerIndex = enum(u32) { |
| 348 | _, |
| 349 | }; |
| 350 | |
| 346 | 351 | pub fn headerPtr(member: *Member, coff: *Coff) *std.coff.ArchiveMemberHeader { |
| 347 | 352 | return @ptrCast(@alignCast(member.header_ni.slice(&coff.mf))); |
| 348 | 353 | } |
| ... | ... | @@ -458,14 +463,12 @@ pub const SymbolTable = struct { |
| 458 | 463 | |
| 459 | 464 | pub const Entry = struct { |
| 460 | 465 | entry_si: Symbol.Index, |
| 461 | | index: Index, |
| 466 | sti: Index, // TODO: Is this redundant now that we store it on symbol? |
| 462 | 467 | }; |
| 463 | 468 | |
| 464 | 469 | pub const Add = union(enum) { |
| 465 | 470 | section, |
| 466 | | global: struct { |
| 467 | | import: bool, |
| 468 | | }, |
| 471 | global, |
| 469 | 472 | }; |
| 470 | 473 | |
| 471 | 474 | pub const SymbolName = union(enum) { |
| ... | ... | @@ -473,12 +476,25 @@ pub const SymbolTable = struct { |
| 473 | 476 | long: StringIndex, |
| 474 | 477 | }; |
| 475 | 478 | |
| 476 | | // Symbol.Index does not map 1:1 with SymbolTable.Index due to auxiliary entries |
| 479 | // Symbol.Index does not map 1:1 with SymbolTable.Index due to |
| 480 | // variable number of auxiliary entries that may trail each symbol |
| 477 | 481 | pub const Index = enum(u32) { |
| 482 | none, |
| 478 | 483 | _, |
| 479 | 484 | |
| 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 | 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 | }; |
| 484 | 500 | |
| ... | ... | @@ -607,6 +623,37 @@ pub const String = enum(u32) { |
| 607 | 623 | } |
| 608 | 624 | }; |
| 609 | 625 | |
| 626 | pub 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 | |
| 610 | 657 | pub const GlobalName = struct { name: String, lib_name: String.Optional }; |
| 611 | 658 | |
| 612 | 659 | pub const Symbol = struct { |
| ... | ... | @@ -618,9 +665,9 @@ pub const Symbol = struct { |
| 618 | 665 | /// Relocations targeting this symbol |
| 619 | 666 | target_relocs: Reloc.Index, |
| 620 | 667 | section_number: SectionNumber, |
| 668 | sti: SymbolTable.Index, |
| 621 | 669 | unused0: u32 = 0, |
| 622 | | unused1: u32 = 0, |
| 623 | | unused2: u16 = 0, |
| 670 | unused1: u16 = 0, |
| 624 | 671 | |
| 625 | 672 | pub const SectionNumber = enum(i16) { |
| 626 | 673 | UNDEFINED = 0, |
| ... | ... | @@ -633,7 +680,11 @@ pub const Symbol = struct { |
| 633 | 680 | } |
| 634 | 681 | |
| 635 | 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 | } |
| 638 | 689 | |
| 639 | 690 | pub fn header(sn: SectionNumber, coff: *Coff) *std.coff.SectionHeader { |
| ... | ... | @@ -692,6 +743,17 @@ pub const Symbol = struct { |
| 692 | 743 | } |
| 693 | 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 | }; |
| 696 | 758 | |
| 697 | 759 | comptime { |
| ... | ... | @@ -705,7 +767,7 @@ pub const Reloc = extern struct { |
| 705 | 767 | next: Reloc.Index, |
| 706 | 768 | loc: Symbol.Index, |
| 707 | 769 | target: Symbol.Index, |
| 708 | | unused: u32, |
| 770 | sri: Section.RelocationIndex, |
| 709 | 771 | offset: u64, |
| 710 | 772 | addend: i64, |
| 711 | 773 | |
| ... | ... | @@ -725,8 +787,8 @@ pub const Reloc = extern struct { |
| 725 | 787 | none = std.math.maxInt(u32), |
| 726 | 788 | _, |
| 727 | 789 | |
| 728 | | pub fn get(si: Reloc.Index, coff: *Coff) *Reloc { |
| 729 | | return &coff.relocs.items[@intFromEnum(si)]; |
| 790 | pub fn get(ri: Reloc.Index, coff: *Coff) *Reloc { |
| 791 | return &coff.relocs.items[@intFromEnum(ri)]; |
| 730 | 792 | } |
| 731 | 793 | }; |
| 732 | 794 | |
| ... | ... | @@ -861,6 +923,8 @@ pub const Reloc = extern struct { |
| 861 | 923 | } |
| 862 | 924 | |
| 863 | 925 | pub fn delete(reloc: *Reloc, coff: *Coff) void { |
| 926 | // TODO: Need to remove this from the COFF relocation table (remove swap) |
| 927 | |
| 864 | 928 | switch (reloc.prev) { |
| 865 | 929 | .none => { |
| 866 | 930 | const target = reloc.target.get(coff); |
| ... | ... | @@ -1021,10 +1085,11 @@ pub fn deinit(coff: *Coff) void { |
| 1021 | 1085 | const gpa = coff.base.comp.gpa; |
| 1022 | 1086 | coff.mf.deinit(gpa); |
| 1023 | 1087 | coff.nodes.deinit(gpa); |
| 1024 | | // TODO: Update this |
| 1025 | 1088 | coff.long_names_table.entries.deinit(gpa); |
| 1026 | 1089 | coff.import_table.entries.deinit(gpa); |
| 1027 | 1090 | coff.export_table.entries.deinit(gpa); |
| 1091 | coff.symbol_table.string_offsets.deinit(gpa); |
| 1092 | coff.symbol_table.entries.deinit(gpa); |
| 1028 | 1093 | coff.strings.deinit(gpa); |
| 1029 | 1094 | coff.string_bytes.deinit(gpa); |
| 1030 | 1095 | coff.section_table.deinit(gpa); |
| ... | ... | @@ -1356,9 +1421,10 @@ fn initHeaders( |
| 1356 | 1421 | })); |
| 1357 | 1422 | coff.nodes.appendAssumeCapacity(.section_table); |
| 1358 | 1423 | |
| 1424 | // TODO: These two nodes could be inside one movable node |
| 1359 | 1425 | const symbol_table_ni = Node.known.symbol_table; |
| 1360 | 1426 | assert(symbol_table_ni == try coff.mf.addLastChildNode(gpa, zcu_coff_parent_ni, .{ |
| 1361 | | .alignment = .@"4", |
| 1427 | .alignment = .@"2", |
| 1362 | 1428 | .fixed = true, |
| 1363 | 1429 | .moved = true, |
| 1364 | 1430 | })); |
| ... | ... | @@ -1366,7 +1432,8 @@ fn initHeaders( |
| 1366 | 1432 | |
| 1367 | 1433 | const string_table_ni = Node.known.string_table; |
| 1368 | 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 | 1437 | .fixed = true, |
| 1371 | 1438 | .resized = true, |
| 1372 | 1439 | })); |
| ... | ... | @@ -1382,6 +1449,7 @@ fn initHeaders( |
| 1382 | 1449 | .loc_relocs = .none, |
| 1383 | 1450 | .target_relocs = .none, |
| 1384 | 1451 | .section_number = .UNDEFINED, |
| 1452 | .sti = .none, |
| 1385 | 1453 | }; |
| 1386 | 1454 | assert(try coff.addSection(".data", .{ |
| 1387 | 1455 | .CNT_INITIALIZED_DATA = true, |
| ... | ... | @@ -1533,6 +1601,8 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 { |
| 1533 | 1601 | .symbol_table, |
| 1534 | 1602 | .symbol_table_entry, |
| 1535 | 1603 | .string_table, |
| 1604 | .relocation_table, |
| 1605 | .relocation_table_entry, |
| 1536 | 1606 | => unreachable, |
| 1537 | 1607 | .image_section => |si| si, |
| 1538 | 1608 | .import_directory_table => break :parent_rva coff.targetLoad( |
| ... | ... | @@ -1721,17 +1791,18 @@ pub fn sectionTableSlice(coff: *Coff) []std.coff.SectionHeader { |
| 1721 | 1791 | |
| 1722 | 1792 | pub fn symbolTableEntryPtr(coff: *Coff, sti: SymbolTable.Index) *align(2) std.coff.Symbol { |
| 1723 | 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 | } |
| 1727 | 1797 | |
| 1728 | 1798 | pub fn symbolAuxSectionDefinitionPtr(coff: *Coff, si: Symbol.Index) *align(2) std.coff.SectionDefinition { |
| 1729 | | const sti = coff.symbol_table.entries.get(si).?.index; |
| 1730 | | |
| 1799 | const sti = coff.symbol_table.entries.get(si).?.sti; |
| 1731 | 1800 | const symbol = coff.symbolTableEntryPtr(sti); |
| 1732 | 1801 | assert(symbol.storage_class == .STATIC and symbol.number_of_aux_symbols == 1); |
| 1733 | 1802 | |
| 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 | } |
| 1736 | 1807 | |
| 1737 | 1808 | pub fn symbolTableStringLenPtr(coff: *Coff) *align(2) u32 { |
| ... | ... | @@ -1772,6 +1843,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index { |
| 1772 | 1843 | .loc_relocs = .none, |
| 1773 | 1844 | .target_relocs = .none, |
| 1774 | 1845 | .section_number = .UNDEFINED, |
| 1846 | .sti = .none, |
| 1775 | 1847 | }; |
| 1776 | 1848 | return @enumFromInt(coff.symbols.items.len); |
| 1777 | 1849 | } |
| ... | ... | @@ -1808,27 +1880,22 @@ fn getOrPutStringAssumeCapacity(coff: *Coff, string: []const u8) String { |
| 1808 | 1880 | return @enumFromInt(gop.key_ptr.*); |
| 1809 | 1881 | } |
| 1810 | 1882 | |
| 1811 | | pub fn globalSymbol(coff: *Coff, name: []const u8, lib_name: ?[]const u8) !Symbol.Index { |
| 1812 | | return (try getOrPutGlobalSymbol(coff, name, lib_name)).value_ptr.*; |
| 1813 | | } |
| 1814 | | |
| 1815 | | fn getOrPutGlobalSymbol( |
| 1816 | | coff: *Coff, |
| 1883 | pub fn globalSymbol(coff: *Coff, opts: struct { |
| 1817 | 1884 | name: []const u8, |
| 1818 | | lib_name: ?[]const u8, |
| 1819 | | ) !std.AutoArrayHashMapUnmanaged(GlobalName, Symbol.Index).GetOrPutResult { |
| 1885 | lib_name: ?[]const u8 = null, |
| 1886 | }) !Symbol.Index { |
| 1820 | 1887 | const gpa = coff.base.comp.gpa; |
| 1821 | 1888 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 1822 | 1889 | const sym_gop = try coff.globals.getOrPut(gpa, .{ |
| 1823 | | .name = try coff.getOrPutString(name), |
| 1824 | | .lib_name = try coff.getOrPutOptionalString(lib_name), |
| 1890 | .name = try coff.getOrPutString(opts.name), |
| 1891 | .lib_name = try coff.getOrPutOptionalString(opts.lib_name), |
| 1825 | 1892 | }); |
| 1826 | 1893 | if (!sym_gop.found_existing) { |
| 1827 | 1894 | sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity(); |
| 1828 | 1895 | coff.synth_prog_node.increaseEstimatedTotalItems(1); |
| 1829 | 1896 | } |
| 1830 | 1897 | |
| 1831 | | return sym_gop; |
| 1898 | return sym_gop.value_ptr.*; |
| 1832 | 1899 | } |
| 1833 | 1900 | |
| 1834 | 1901 | fn navSection( |
| ... | ... | @@ -1870,10 +1937,10 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na |
| 1870 | 1937 | pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index { |
| 1871 | 1938 | const ip = &zcu.intern_pool; |
| 1872 | 1939 | const nav = ip.getNav(nav_index); |
| 1873 | | if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol( |
| 1874 | | @"extern".name.toSlice(ip), |
| 1875 | | @"extern".lib_name.toSlice(ip), |
| 1876 | | ); |
| 1940 | if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(.{ |
| 1941 | .name = @"extern".name.toSlice(ip), |
| 1942 | .lib_name = @"extern".lib_name.toSlice(ip), |
| 1943 | }); |
| 1877 | 1944 | const nmi = try coff.navMapIndex(zcu, nav_index); |
| 1878 | 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 | 1993 | reloc_info.addend, |
| 1927 | 1994 | switch (coff.targetLoad(&coff.headerPtr().machine)) { |
| 1928 | 1995 | else => unreachable, |
| 1929 | | .AMD64 => .{ .AMD64 = .ADDR64 }, |
| 1996 | .AMD64 => .{ .AMD64 = .ADDR64 }, // TODO: Switch to REL32 for obj/archive |
| 1930 | 1997 | .I386 => .{ .I386 = .DIR32 }, |
| 1931 | 1998 | }, |
| 1932 | 1999 | ); |
| ... | ... | @@ -1941,7 +2008,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member. |
| 1941 | 2008 | const comp = coff.base.comp; |
| 1942 | 2009 | const gpa = comp.gpa; |
| 1943 | 2010 | |
| 1944 | | // TODO: These two nodes could to be inside a movable node? Only if coff or import |
| 2011 | // TODO: These two nodes could to be inside a movable node if kind == .coff|.import |
| 1945 | 2012 | |
| 1946 | 2013 | const header_ni = try coff.mf.addLastChildNode(gpa, Node.known.file, .{ |
| 1947 | 2014 | .size = @sizeOf(std.coff.ArchiveMemberHeader), |
| ... | ... | @@ -1967,7 +2034,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: Member.Kind, size: usize) !Member. |
| 1967 | 2034 | .kind = kind, |
| 1968 | 2035 | .header_ni = header_ni, |
| 1969 | 2036 | .content_ni = content_ni, |
| 1970 | | .symbol_offsets = .empty, |
| 2037 | .first_linker_indices = .empty, |
| 1971 | 2038 | }); |
| 1972 | 2039 | |
| 1973 | 2040 | coff.nodes.appendAssumeCapacity(.{ .archive_member_header = mi }); |
| ... | ... | @@ -2028,9 +2095,9 @@ fn appendMemberSymbolString( |
| 2028 | 2095 | name_slice[name.len] = 0; |
| 2029 | 2096 | } |
| 2030 | 2097 | |
| 2031 | | fn addMemberSymbol( |
| 2098 | fn ensureMemberSymbol( |
| 2032 | 2099 | coff: *Coff, |
| 2033 | | name: String, |
| 2100 | name: []const u8, |
| 2034 | 2101 | mi: Member.Index, |
| 2035 | 2102 | si: Symbol.Index, |
| 2036 | 2103 | ) !void { |
| ... | ... | @@ -2038,66 +2105,69 @@ fn addMemberSymbol( |
| 2038 | 2105 | const member = mi.get(coff); |
| 2039 | 2106 | assert(member.kind == .coff); |
| 2040 | 2107 | |
| 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 | 2110 | if (gop.found_existing) return; |
| 2043 | 2111 | |
| 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) |
| 2045 | 2114 | |
| 2046 | | const symbol_index = blk: { |
| 2115 | const mfli: Member.FirstLinkerIndex = blk: { |
| 2047 | 2116 | const num_symbols_ptr = coff.firstLinkerMemberNumSymbolsPtr(); |
| 2048 | 2117 | const num_symbols = std.mem.toNative(u32, num_symbols_ptr.*, .big); |
| 2049 | 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 | }; |
| 2052 | 2121 | |
| 2053 | | gop.value_ptr.* = symbol_index; |
| 2054 | | const name_slice = name.toSlice(coff); |
| 2122 | gop.value_ptr.* = mfli; |
| 2055 | 2123 | |
| 2056 | 2124 | // Linker member fields are not modeled as nodes because MappedFile |
| 2057 | 2125 | // can't guarantee that they will be tightly packed after resizing |
| 2058 | 2126 | |
| 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 | 2128 | defer coff.lib_string_len = new_string_table_size; |
| 2061 | 2129 | |
| 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 | 2132 | const new_header_size = old_header_size + @sizeOf(u32); |
| 2065 | 2133 | try Node.known.first_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size); |
| 2066 | 2134 | |
| 2067 | 2135 | const slice = Node.known.first_linker_member.slice(&coff.mf); |
| 2068 | 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; |
| 2070 | 2139 | |
| 2071 | 2140 | // New offset entry is written in flushMember |
| 2072 | 2141 | } |
| 2073 | 2142 | |
| 2074 | 2143 | { |
| 2075 | 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 | 2146 | const new_header_size = old_header_size + @sizeOf(u16); |
| 2078 | 2147 | try Node.known.second_linker_member.resize(&coff.mf, gpa, new_header_size + new_string_table_size); |
| 2079 | 2148 | |
| 2080 | 2149 | const needs_sort = if (coff.lib_string_table.items.len > 0) |
| 2081 | 2150 | std.mem.lessThan( |
| 2082 | 2151 | u8, |
| 2083 | | name_slice, |
| 2152 | name, |
| 2084 | 2153 | coff.lib_string_table.items[coff.lib_string_table.items.len - 1].toSlice(coff), |
| 2085 | 2154 | ) |
| 2086 | 2155 | else |
| 2087 | 2156 | false; |
| 2088 | 2157 | |
| 2089 | | try coff.lib_string_table.append(gpa, name); |
| 2158 | try coff.lib_string_table.append(gpa, name_string); |
| 2090 | 2159 | |
| 2091 | 2160 | const slice = Node.known.second_linker_member.slice(&coff.mf); |
| 2092 | 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); |
| 2094 | 2163 | |
| 2095 | 2164 | if (needs_sort) { |
| 2096 | 2165 | // The entire string table is rebuilt in flushMember after sorting |
| 2097 | 2166 | coff.pending_members.putAssumeCapacity(Member.Index.second, {}); |
| 2098 | 2167 | } else { |
| 2099 | 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 | } |
| 2102 | 2172 | |
| 2103 | 2173 | // Indices in this table are 1-based |
| ... | ... | @@ -2120,6 +2190,7 @@ fn addSymbolTableEntry( |
| 2120 | 2190 | assert(!coff.isImage()); |
| 2121 | 2191 | const gpa = coff.base.comp.gpa; |
| 2122 | 2192 | |
| 2193 | // TODO: Avoid geOrPutString if it fits (only need to actually make the String for adding member symbol) |
| 2123 | 2194 | const string, const name_slice = switch (name) { |
| 2124 | 2195 | .bytes => |bytes| .{ try coff.getOrPutString(bytes), bytes }, |
| 2125 | 2196 | .string => |s| .{ s, s.toSlice(coff) }, |
| ... | ... | @@ -2140,11 +2211,18 @@ fn addSymbolTableEntry( |
| 2140 | 2211 | break :index .{ .long = string_gop.value_ptr.* }; |
| 2141 | 2212 | } else .{ .short = name_slice }; |
| 2142 | 2213 | |
| 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 | 2224 | const symbols_added: u8 = switch (add) { |
| 2145 | 2225 | .section => count: { |
| 2146 | | const sym = si.get(coff); |
| 2147 | | |
| 2148 | 2226 | try coff.nodes.ensureUnusedCapacity(gpa, 2); |
| 2149 | 2227 | _ = try coff.addSymbolTableEntryAssumeCapacity( |
| 2150 | 2228 | symbol_name, |
| ... | ... | @@ -2159,28 +2237,32 @@ fn addSymbolTableEntry( |
| 2159 | 2237 | ); |
| 2160 | 2238 | |
| 2161 | 2239 | // Aux entry ields are updated by flushMoved / flushResized |
| 2162 | | |
| 2163 | 2240 | try coff.symbol_table.entries.put(gpa, si, .{ |
| 2164 | 2241 | .entry_si = .null, |
| 2165 | | .index = @enumFromInt(symbol_index), |
| 2242 | .sti = sym.sti, |
| 2166 | 2243 | }); |
| 2167 | 2244 | |
| 2168 | 2245 | break :count 2; |
| 2169 | 2246 | }, |
| 2170 | | .global => |global| count: { |
| 2171 | | const sym = si.get(coff); |
| 2172 | | |
| 2247 | .global => count: { |
| 2173 | 2248 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 2174 | 2249 | try coff.symbols.ensureUnusedCapacity(gpa, 1); |
| 2175 | 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 | |
| 2176 | 2259 | const entry_ni = try coff.addSymbolTableEntryAssumeCapacity( |
| 2177 | 2260 | symbol_name, |
| 2178 | | if (global.import) 0 else coff.computeNodeSectionOffset(sym.ni), |
| 2179 | | if (global.import) .UNDEFINED else sym.section_number, |
| 2261 | if (sym.ni == .none) 0 else coff.computeNodeSectionOffset(sym.ni), |
| 2262 | sym.section_number, |
| 2180 | 2263 | .{ |
| 2181 | 2264 | .base_type = .NULL, |
| 2182 | | .complex_type = if (global.import or |
| 2183 | | Symbol.Index.text.get(coff).section_number == sym.section_number) |
| 2265 | .complex_type = if (Symbol.Index.text.get(coff).section_number == sym.section_number) |
| 2184 | 2266 | .FUNCTION |
| 2185 | 2267 | else |
| 2186 | 2268 | .NULL, |
| ... | ... | @@ -2198,24 +2280,27 @@ fn addSymbolTableEntry( |
| 2198 | 2280 | entry_sym.section_number = .UNDEFINED; |
| 2199 | 2281 | } |
| 2200 | 2282 | |
| 2201 | | try coff.addReloc( |
| 2202 | | entry_si, |
| 2203 | | @offsetOf(std.coff.Symbol, "value"), |
| 2204 | | si, |
| 2205 | | 0, |
| 2206 | | .{ .AMD64 = .SECREL }, |
| 2207 | | ); |
| 2283 | if (sym.ni != .none) { |
| 2284 | // TODO: This serves to update the std.coff.Symbol.value (to VA of si), is this working? |
| 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 | } |
| 2208 | 2293 | |
| 2209 | 2294 | try coff.symbol_table.entries.put(gpa, si, .{ |
| 2210 | 2295 | .entry_si = entry_si, |
| 2211 | | .index = @enumFromInt(symbol_index), |
| 2296 | .sti = sym.sti, |
| 2212 | 2297 | }); |
| 2213 | 2298 | |
| 2214 | 2299 | break :count 1; |
| 2215 | 2300 | }, |
| 2216 | 2301 | }; |
| 2217 | 2302 | |
| 2218 | | const new_num_symbols = symbol_index + symbols_added; |
| 2303 | const new_num_symbols = old_num_symbols + symbols_added; |
| 2219 | 2304 | coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols); |
| 2220 | 2305 | coff.symbol_table.pending_shrink = |
| 2221 | 2306 | Node.known.symbol_table.location(&coff.mf).resolve(&coff.mf)[1] > |
| ... | ... | @@ -2243,15 +2328,6 @@ fn addSymbolTableEntryAssumeCapacity( |
| 2243 | 2328 | coff.nodes.appendAssumeCapacity(.symbol_table_entry); |
| 2244 | 2329 | |
| 2245 | 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 | 2331 | switch (name) { |
| 2256 | 2332 | .short => |s| { |
| 2257 | 2333 | @memcpy(entry.name[0..s.len], s); |
| ... | ... | @@ -2264,6 +2340,13 @@ fn addSymbolTableEntryAssumeCapacity( |
| 2264 | 2340 | }, |
| 2265 | 2341 | } |
| 2266 | 2342 | |
| 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 | 2350 | if (coff.targetEndian() != native_endian) |
| 2268 | 2351 | std.mem.byteSwapAllFields(std.coff.SectionHeader, entry.*); |
| 2269 | 2352 | |
| ... | ... | @@ -2310,7 +2393,10 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags |
| 2310 | 2393 | }); |
| 2311 | 2394 | |
| 2312 | 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 | 2400 | coff.nodes.appendAssumeCapacity(.{ .image_section = si }); |
| 2315 | 2401 | const section_table = coff.sectionTableSlice(); |
| 2316 | 2402 | |
| ... | ... | @@ -2318,7 +2404,7 @@ fn addSection(coff: *Coff, name: []const u8, flags: std.coff.SectionHeader.Flags |
| 2318 | 2404 | const virtual_size = coff.optionalHeaderField(.section_alignment); |
| 2319 | 2405 | const rva: u32 = switch (section_index) { |
| 2320 | 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 | 2408 | coff.targetLoad(&section_table[section_index - 1].virtual_size), |
| 2323 | 2409 | }; |
| 2324 | 2410 | |
| ... | ... | @@ -2456,6 +2542,35 @@ fn objectSectionMapIndex( |
| 2456 | 2542 | return osmi; |
| 2457 | 2543 | } |
| 2458 | 2544 | |
| 2545 | fn 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 | |
| 2459 | 2574 | pub fn addReloc( |
| 2460 | 2575 | coff: *Coff, |
| 2461 | 2576 | loc_si: Symbol.Index, |
| ... | ... | @@ -2464,16 +2579,80 @@ pub fn addReloc( |
| 2464 | 2579 | addend: i64, |
| 2465 | 2580 | @"type": Reloc.Type, |
| 2466 | 2581 | ) !void { |
| 2467 | | const gpa = coff.base.comp.gpa; |
| 2468 | 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 | 2648 | const ri: Reloc.Index = @enumFromInt(coff.relocs.items.len); |
| 2470 | | (try coff.relocs.addOne(gpa)).* = .{ |
| 2649 | coff.relocs.addOneAssumeCapacity().* = .{ |
| 2471 | 2650 | .type = @"type", |
| 2472 | 2651 | .prev = .none, |
| 2473 | 2652 | .next = target.target_relocs, |
| 2474 | 2653 | .loc = loc_si, |
| 2475 | 2654 | .target = target_si, |
| 2476 | | .unused = 0, |
| 2655 | .sri = sri, |
| 2477 | 2656 | .offset = offset, |
| 2478 | 2657 | .addend = addend, |
| 2479 | 2658 | }; |
| ... | ... | @@ -2516,6 +2695,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 2516 | 2695 | |
| 2517 | 2696 | const nmi = try coff.navMapIndex(zcu, nav_index); |
| 2518 | 2697 | const si = nmi.symbol(coff); |
| 2698 | log.debug("updateNav({f}) = {d}", .{ nav.fqn.fmt(ip), si }); |
| 2519 | 2699 | const ni = ni: { |
| 2520 | 2700 | switch (si.get(coff).ni) { |
| 2521 | 2701 | .none => { |
| ... | ... | @@ -2530,7 +2710,13 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 2530 | 2710 | sym.ni = ni; |
| 2531 | 2711 | sym.section_number = sec_si.get(coff).section_number; |
| 2532 | 2712 | |
| 2533 | | // TODO: Add symbol table entry |
| 2713 | // 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 | 2721 | else => si.deleteLocationRelocs(coff), |
| 2536 | 2722 | } |
| ... | ... | @@ -2660,6 +2846,14 @@ fn updateFuncInner( |
| 2660 | 2846 | const sym = si.get(coff); |
| 2661 | 2847 | sym.ni = ni; |
| 2662 | 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 | 2858 | else => si.deleteLocationRelocs(coff), |
| 2665 | 2859 | } |
| ... | ... | @@ -2993,6 +3187,19 @@ fn flushUav( |
| 2993 | 3187 | coff.nodes.appendAssumeCapacity(.{ .uav = umi }); |
| 2994 | 3188 | sym.ni = ni; |
| 2995 | 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 | 3204 | else => { |
| 2998 | 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 | 3235 | const comp = zcu.comp; |
| 3029 | 3236 | const gpa = zcu.gpa; |
| 3030 | 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) }); |
| 3031 | 3239 | |
| 3032 | 3240 | if (!coff.isImage()) { |
| 3033 | | // TODO: What about data imports? |
| 3034 | | |
| 3035 | | // const si = gmi.symbol(coff); |
| 3036 | | // const sym = si.get(coff); |
| 3037 | | // sym.section_number = Symbol.Index.text.get(coff).section_number; |
| 3038 | | // assert(sym.loc_relocs == .none); |
| 3039 | | // sym.loc_relocs = @enumFromInt(coff.relocs.items.len); |
| 3040 | | // |
| 3041 | | // try coff.addSymbolTableEntry( |
| 3042 | | // .{ .bytes = gn.name.toSlice(coff) }, |
| 3043 | | // si, |
| 3044 | | // .{ .global = .{ .import = true } }, |
| 3045 | | // ); |
| 3241 | try coff.addSymbolTableEntry( |
| 3242 | .{ .string = gn.name }, |
| 3243 | gmi.symbol(coff), |
| 3244 | .global, |
| 3245 | ); |
| 3046 | 3246 | |
| 3047 | 3247 | return; |
| 3048 | 3248 | } |
| ... | ... | @@ -3268,8 +3468,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3268 | 3468 | .data_directories, |
| 3269 | 3469 | .section_table, |
| 3270 | 3470 | .placeholder, |
| 3271 | | |
| 3272 | | .symbol_table_entry, |
| 3471 | .symbol_table_entry, // TODO: Need to impl this for symbol table updates to work? |
| 3273 | 3472 | .string_table, |
| 3274 | 3473 | => if (!coff.isArchive()) unreachable, |
| 3275 | 3474 | .symbol_table => { |
| ... | ... | @@ -3278,6 +3477,13 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3278 | 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 | 3487 | .archive_member_header => |mi| { |
| 3282 | 3488 | const member = mi.get(coff); |
| 3283 | 3489 | switch (member.kind) { |
| ... | ... | @@ -3439,7 +3645,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3439 | 3645 | ), |
| 3440 | 3646 | } |
| 3441 | 3647 | |
| 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 | 3649 | 0, |
| 3444 | 3650 | std.mem.alignForward( |
| 3445 | 3651 | u32, |
| ... | ... | @@ -3483,6 +3689,9 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 3483 | 3689 | assert(!coff.isImage()); |
| 3484 | 3690 | coff.targetStore(coff.symbolTableStringLenPtr(), @intCast(size)); |
| 3485 | 3691 | }, |
| 3692 | .relocation_table, |
| 3693 | .relocation_table_entry, |
| 3694 | => assert(!coff.isImage()), |
| 3486 | 3695 | .image_section => |si| { |
| 3487 | 3696 | const sym = si.get(coff); |
| 3488 | 3697 | const section_index = sym.section_number.toIndex(); |
| ... | ... | @@ -3587,8 +3796,8 @@ fn flushMember(coff: *Coff, mi: Member.Index) !void { |
| 3587 | 3796 | .coff => { |
| 3588 | 3797 | const file_offset: u32 = @intCast(member.header_ni.fileLocation(&coff.mf, false).offset); |
| 3589 | 3798 | const first_linker_offsets = coff.firstLinkerMemberOffsetsSlice(); |
| 3590 | | for (member.symbol_offsets.values()) |offset_index| |
| 3591 | | first_linker_offsets[offset_index] = std.mem.nativeTo(u32, file_offset, .big); |
| 3799 | for (member.first_linker_indices.values()) |mfli| |
| 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 | 3840 | for ( |
| 3632 | 3841 | coff.section_table.items[start_section_index..], |
| 3633 | 3842 | coff.sectionTableSlice()[start_section_index..], |
| 3634 | | ) |section_si, *section| { |
| 3635 | | const section_sym = section_si.get(coff); |
| 3843 | ) |*section, *header| { |
| 3844 | const section_sym = section.si.get(coff); |
| 3636 | 3845 | section_sym.rva = rva; |
| 3637 | | coff.targetStore(&section.virtual_address, rva); |
| 3846 | coff.targetStore(&header.virtual_address, rva); |
| 3638 | 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 | 3850 | switch (coff.optionalHeaderPtr()) { |
| 3642 | 3851 | inline else => |optional_header| coff.targetStore( |
| ... | ... | @@ -3690,8 +3899,10 @@ fn updateExportsInner( |
| 3690 | 3899 | for (export_indices) |export_index| { |
| 3691 | 3900 | const @"export" = export_index.ptr(zcu); |
| 3692 | 3901 | const name = @"export".opts.name.toSlice(ip); |
| 3693 | | const symbol_gop = try coff.getOrPutGlobalSymbol(name, null); |
| 3694 | | const export_si = symbol_gop.value_ptr.*; |
| 3902 | const export_si = try coff.globalSymbol(.{ |
| 3903 | .name = name, |
| 3904 | .lib_name = null, |
| 3905 | }); |
| 3695 | 3906 | const export_sym = export_si.get(coff); |
| 3696 | 3907 | export_sym.ni = exported_ni; |
| 3697 | 3908 | export_sym.rva = exported_sym.rva; |
| ... | ... | @@ -3707,20 +3918,6 @@ fn updateExportsInner( |
| 3707 | 3918 | std.mem.byteSwapAllFields(std.coff.ImageDataDirectory, tls_directory); |
| 3708 | 3919 | } |
| 3709 | 3920 | |
| 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 | 3921 | if (coff.export_table.ni == .none) continue; |
| 3725 | 3922 | |
| 3726 | 3923 | const entries_ctx = ExportTable.Adapter{ .coff = coff }; |
| ... | ... | @@ -3809,7 +4006,7 @@ fn updateExportsInner( |
| 3809 | 4006 | gop.value_ptr.si = export_si; |
| 3810 | 4007 | const reloc = gop.value_ptr.*.export_address_table_ri.get(coff); |
| 3811 | 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 | 4015 | _ = coff; |
| 3819 | 4016 | _ = exported; |
| 3820 | 4017 | _ = name; |
| 4018 | |
| 4019 | // TODO: Delete from first / second linker member table (remove swap?) |
| 4020 | // TODO: Delete from symbol table inside section |
| 3821 | 4021 | } |
| 3822 | 4022 | |
| 3823 | 4023 | fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) !void { |