| ... | @@ -36,6 +36,7 @@ shndx: struct { | ... | @@ -36,6 +36,7 @@ shndx: struct { |
| 36 | dynsym: Section.Index, | 36 | dynsym: Section.Index, |
| 37 | dynstr: Section.Index, | 37 | dynstr: Section.Index, |
| 38 | dynamic: Section.Index, | 38 | dynamic: Section.Index, |
| | 39 | hash: Section.Index, |
| 39 | tdata: Section.Index, | 40 | tdata: Section.Index, |
| 40 | rela_dyn: Section.Index, | 41 | rela_dyn: Section.Index, |
| 41 | rela_plt: Section.Index, | 42 | rela_plt: Section.Index, |
| ... | @@ -1751,6 +1752,150 @@ const SymbolReloc = struct { | ... | @@ -1751,6 +1752,150 @@ const SymbolReloc = struct { |
| 1751 | } | 1752 | } |
| 1752 | }; | 1753 | }; |
| 1753 | | 1754 | |
| | 1755 | fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { |
| | 1756 | const min_buckets = max_dynsym_count / 2; |
| | 1757 | |
| | 1758 | const cur_dynsym_count: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { |
| | 1759 | inline else => |shdr, class| @intCast(@divExact( |
| | 1760 | elf.targetLoad(&shdr.size), |
| | 1761 | @sizeOf(class.ElfN().Sym), |
| | 1762 | )), |
| | 1763 | }; |
| | 1764 | |
| | 1765 | { |
| | 1766 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1767 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1768 | assert(elf.targetLoad(&header.nchain) == cur_dynsym_count); |
| | 1769 | const nbucket = elf.targetLoad(&header.nbucket); |
| | 1770 | if (nbucket >= min_buckets) { |
| | 1771 | // We don't need to add any buckets, but we still need to make sure the section is large |
| | 1772 | // enough to fit `max_dynsym_count` chains. |
| | 1773 | const need_size = @sizeOf(std.elf.hash.Header) + (nbucket + max_dynsym_count) * 4; |
| | 1774 | try elf.ensureNodeSize(elf.shndx.hash.get(elf).ni, need_size); |
| | 1775 | return; |
| | 1776 | } |
| | 1777 | // We need more buckets, so we'll have to rebuild the hash table. |
| | 1778 | } |
| | 1779 | |
| | 1780 | // Rebuilding the hash table is quite expensive, so to avoid doing it too often we use a large |
| | 1781 | // growth factor (* 2) for `nbucket`. |
| | 1782 | const new_nbucket = min_buckets * 2; |
| | 1783 | |
| | 1784 | { |
| | 1785 | const need_size = @sizeOf(std.elf.hash.Header) + (new_nbucket + max_dynsym_count) * 4; |
| | 1786 | try elf.ensureNodeSize(elf.shndx.hash.get(elf).ni, need_size); |
| | 1787 | } |
| | 1788 | |
| | 1789 | elf.mf.nodes_lock.lock(); |
| | 1790 | defer elf.mf.nodes_lock.unlock(); |
| | 1791 | |
| | 1792 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1793 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1794 | const trailing: []u32 = @ptrCast(section_slice[@sizeOf(std.elf.hash.Header)..]); |
| | 1795 | |
| | 1796 | header.* = .{ .nbucket = new_nbucket, .nchain = cur_dynsym_count }; |
| | 1797 | if (elf.targetEndian() != std.lang.Endian.native) { |
| | 1798 | std.mem.byteSwapAllFields(std.elf.hash.Header, header); |
| | 1799 | } |
| | 1800 | const buckets: []u32 = trailing[0..elf.targetLoad(&header.nbucket)]; |
| | 1801 | const chains: []u32 = trailing[elf.targetLoad(&header.nbucket)..][0..elf.targetLoad(&header.nchain)]; |
| | 1802 | |
| | 1803 | @memset(buckets, 0); |
| | 1804 | chains[0] = 0; |
| | 1805 | for (1..cur_dynsym_count, chains[1..]) |dynsym_index_usize, *chain| { |
| | 1806 | const dynsym_index: u32 = @intCast(dynsym_index_usize); |
| | 1807 | const sym_name: String(.dynstr) = switch (elf.dynsymPtr(dynsym_index)) { |
| | 1808 | inline else => |sym| @fromBackingInt(elf.targetLoad(&sym.name)), |
| | 1809 | }; |
| | 1810 | const b = std.elf.hash.calculate(sym_name.slice(elf)) % buckets.len; |
| | 1811 | // Make this symbol the head of that bucket, and chain to the old head. |
| | 1812 | chain.* = buckets[b]; |
| | 1813 | elf.targetStore(&buckets[b], dynsym_index); |
| | 1814 | } |
| | 1815 | } |
| | 1816 | |
| | 1817 | fn appendDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| | 1818 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1819 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1820 | assert(elf.targetLoad(&header.nchain) == dynsym_index); |
| | 1821 | elf.targetStore(&header.nchain, dynsym_index + 1); |
| | 1822 | |
| | 1823 | switch (elf.shdrPtr(elf.shndx.hash)) { |
| | 1824 | inline else => |shdr| elf.targetStore(&shdr.size, elf.targetLoad(&shdr.size) + 4), |
| | 1825 | } |
| | 1826 | |
| | 1827 | elf.populateDynsymHashEntry(dynsym_index); |
| | 1828 | } |
| | 1829 | fn populateDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| | 1830 | elf.mf.nodes_lock.lock(); |
| | 1831 | defer elf.mf.nodes_lock.unlock(); |
| | 1832 | |
| | 1833 | assert(dynsym_index != 0); |
| | 1834 | |
| | 1835 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1836 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1837 | const trailing: []u32 = @ptrCast(section_slice[@sizeOf(std.elf.hash.Header)..]); |
| | 1838 | |
| | 1839 | const buckets: []u32 = trailing[0..elf.targetLoad(&header.nbucket)]; |
| | 1840 | const chains: []u32 = trailing[elf.targetLoad(&header.nbucket)..][0..elf.targetLoad(&header.nchain)]; |
| | 1841 | |
| | 1842 | const sym_name: String(.dynstr) = switch (elf.dynsymPtr(dynsym_index)) { |
| | 1843 | inline else => |sym| @fromBackingInt(elf.targetLoad(&sym.name)), |
| | 1844 | }; |
| | 1845 | const b = std.elf.hash.calculate(sym_name.slice(elf)) % buckets.len; |
| | 1846 | // Make this symbol the head of that bucket, and chain to the old head. |
| | 1847 | chains[dynsym_index] = buckets[b]; |
| | 1848 | elf.targetStore(&buckets[b], dynsym_index); |
| | 1849 | } |
| | 1850 | fn popDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| | 1851 | elf.clearDynsymHashEntry(dynsym_index); |
| | 1852 | |
| | 1853 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1854 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1855 | assert(elf.targetLoad(&header.nchain) == dynsym_index + 1); |
| | 1856 | elf.targetStore(&header.nchain, dynsym_index); |
| | 1857 | |
| | 1858 | switch (elf.shdrPtr(elf.shndx.hash)) { |
| | 1859 | inline else => |shdr| elf.targetStore(&shdr.size, elf.targetLoad(&shdr.size) - 4), |
| | 1860 | } |
| | 1861 | } |
| | 1862 | fn clearDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| | 1863 | elf.mf.nodes_lock.lock(); |
| | 1864 | defer elf.mf.nodes_lock.unlock(); |
| | 1865 | |
| | 1866 | assert(dynsym_index != 0); |
| | 1867 | |
| | 1868 | const section_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 1869 | const header: *std.elf.hash.Header = @ptrCast(section_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 1870 | const trailing: []u32 = @ptrCast(section_slice[@sizeOf(std.elf.hash.Header)..]); |
| | 1871 | |
| | 1872 | const buckets: []u32 = trailing[0..elf.targetLoad(&header.nbucket)]; |
| | 1873 | const chains: []u32 = trailing[elf.targetLoad(&header.nbucket)..][0..elf.targetLoad(&header.nchain)]; |
| | 1874 | |
| | 1875 | const sym_name: String(.dynstr) = switch (elf.dynsymPtr(dynsym_index)) { |
| | 1876 | inline else => |sym| @fromBackingInt(elf.targetLoad(&sym.name)), |
| | 1877 | }; |
| | 1878 | const b = std.elf.hash.calculate(sym_name.slice(elf)) % buckets.len; |
| | 1879 | |
| | 1880 | const next_dynsym_index = elf.targetLoad(&chains[dynsym_index]); |
| | 1881 | elf.targetStore(&chains[dynsym_index], 0); |
| | 1882 | |
| | 1883 | // To remove `dynsym_index` from the singly-linked list, we need to iterate the chain to find |
| | 1884 | // and replace it. But since this is, well, a hash table, that's actually fine. |
| | 1885 | if (elf.targetLoad(&buckets[b]) == dynsym_index) { |
| | 1886 | elf.targetStore(&buckets[b], next_dynsym_index); |
| | 1887 | } else { |
| | 1888 | var cur = elf.targetLoad(&buckets[b]); |
| | 1889 | while (true) { |
| | 1890 | assert(cur != 0); // `dynsym_index` is definitely somewhere in the chain |
| | 1891 | if (elf.targetLoad(&chains[cur]) == dynsym_index) break; |
| | 1892 | cur = elf.targetLoad(&chains[cur]); |
| | 1893 | } |
| | 1894 | // We found `dynsym_index`; replace it with `next_dynsym_index`. |
| | 1895 | elf.targetStore(&chains[cur], next_dynsym_index); |
| | 1896 | } |
| | 1897 | } |
| | 1898 | |
| 1754 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { | 1899 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { |
| 1755 | const gpa = elf.base.comp.gpa; | 1900 | const gpa = elf.base.comp.gpa; |
| 1756 | | 1901 | |
| ... | @@ -1780,12 +1925,19 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe | ... | @@ -1780,12 +1925,19 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe |
| 1780 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); | 1925 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); |
| 1781 | | 1926 | |
| 1782 | if (elf.shndx.dynsym != .UNDEF) { | 1927 | if (elf.shndx.dynsym != .UNDEF) { |
| 1783 | // Ensure the `.dynsym` section's node is big enough | 1928 | const dynsym_cur_size: u64, const dynsym_ent_size: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { |
| 1784 | const dynsym_need_size: u64 = switch (elf.shdrPtr(elf.shndx.dynsym)) { | 1929 | inline else => |shdr, class| .{ |
| 1785 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym), | 1930 | elf.targetLoad(&shdr.size), |
| | 1931 | @sizeOf(class.ElfN().Sym), |
| | 1932 | }, |
| 1786 | }; | 1933 | }; |
| | 1934 | const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size)); |
| | 1935 | |
| | 1936 | const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size; |
| 1787 | try elf.ensureNodeSize(elf.shndx.dynsym.get(elf).ni, dynsym_need_size); | 1937 | try elf.ensureNodeSize(elf.shndx.dynsym.get(elf).ni, dynsym_need_size); |
| 1788 | | 1938 | |
| | 1939 | try elf.ensureDynsymHashCapacity(dynsym_cur_len + len); |
| | 1940 | |
| 1789 | try elf.ensureUnusedPltCapacity(len); | 1941 | try elf.ensureUnusedPltCapacity(len); |
| 1790 | } | 1942 | } |
| 1791 | }, | 1943 | }, |
| ... | @@ -2122,6 +2274,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ | ... | @@ -2122,6 +2274,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ |
| 2122 | if (elf.targetEndian() != native_endian) { | 2274 | if (elf.targetEndian() != native_endian) { |
| 2123 | std.mem.byteSwapAllFields(Sym, sym); | 2275 | std.mem.byteSwapAllFields(Sym, sym); |
| 2124 | } | 2276 | } |
| | 2277 | elf.appendDynsymHashEntry(dynsym_index); |
| 2125 | break :dynsym_index dynsym_index; | 2278 | break :dynsym_index dynsym_index; |
| 2126 | }, | 2279 | }, |
| 2127 | } | 2280 | } |
| ... | @@ -2396,6 +2549,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { | ... | @@ -2396,6 +2549,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { |
| 2396 | const new_size = old_size - ent_size; | 2549 | const new_size = old_size - ent_size; |
| 2397 | const remove_dynsym_index: u32 = @intCast(@divExact(new_size, ent_size)); | 2550 | const remove_dynsym_index: u32 = @intCast(@divExact(new_size, ent_size)); |
| 2398 | | 2551 | |
| | 2552 | elf.popDynsymHashEntry(remove_dynsym_index); |
| | 2553 | |
| 2399 | const free_dynsym_index = global_ptr.dynsym_index; | 2554 | const free_dynsym_index = global_ptr.dynsym_index; |
| 2400 | global_ptr.dynsym_index = 0; | 2555 | global_ptr.dynsym_index = 0; |
| 2401 | | 2556 | |
| ... | @@ -2403,6 +2558,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { | ... | @@ -2403,6 +2558,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { |
| 2403 | // The demoted global wasn't the last entry, so move whatever entry we just | 2558 | // The demoted global wasn't the last entry, so move whatever entry we just |
| 2404 | // truncated out of dynsym into its place. | 2559 | // truncated out of dynsym into its place. |
| 2405 | | 2560 | |
| | 2561 | elf.clearDynsymHashEntry(free_dynsym_index); |
| | 2562 | |
| 2406 | const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class)); | 2563 | const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class)); |
| 2407 | const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class)); | 2564 | const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class)); |
| 2408 | | 2565 | |
| ... | @@ -2415,6 +2572,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { | ... | @@ -2415,6 +2572,8 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { |
| 2415 | assert(moved_global_ptr.dynsym_index == remove_dynsym_index); | 2572 | assert(moved_global_ptr.dynsym_index == remove_dynsym_index); |
| 2416 | moved_global_ptr.dynsym_index = free_dynsym_index; | 2573 | moved_global_ptr.dynsym_index = free_dynsym_index; |
| 2417 | | 2574 | |
| | 2575 | elf.populateDynsymHashEntry(free_dynsym_index); |
| | 2576 | |
| 2418 | // Since that symbol's dynsym index has changed, we'll have to update any | 2577 | // Since that symbol's dynsym index has changed, we'll have to update any |
| 2419 | // relocation entries targeting it. | 2578 | // relocation entries targeting it. |
| 2420 | elf.changed_symtab_index.putAssumeCapacity(moved_name, {}); | 2579 | elf.changed_symtab_index.putAssumeCapacity(moved_name, {}); |
| ... | @@ -3161,6 +3320,7 @@ fn create( | ... | @@ -3161,6 +3320,7 @@ fn create( |
| 3161 | .dynsym = .UNDEF, | 3320 | .dynsym = .UNDEF, |
| 3162 | .dynstr = .UNDEF, | 3321 | .dynstr = .UNDEF, |
| 3163 | .dynamic = .UNDEF, | 3322 | .dynamic = .UNDEF, |
| | 3323 | .hash = .UNDEF, |
| 3164 | .tdata = .UNDEF, | 3324 | .tdata = .UNDEF, |
| 3165 | .rela_dyn = .UNDEF, | 3325 | .rela_dyn = .UNDEF, |
| 3166 | .rela_plt = .UNDEF, | 3326 | .rela_plt = .UNDEF, |
| ... | @@ -3298,6 +3458,7 @@ fn initHeaders( | ... | @@ -3298,6 +3458,7 @@ fn initHeaders( |
| 3298 | shnum += 1; // .dynamic | 3458 | shnum += 1; // .dynamic |
| 3299 | shnum += 1; // .dynstr | 3459 | shnum += 1; // .dynstr |
| 3300 | shnum += 1; // .dynsym | 3460 | shnum += 1; // .dynsym |
| | 3461 | shnum += 1; // .hash |
| 3301 | shnum += 1; // .rela.dyn | 3462 | shnum += 1; // .rela.dyn |
| 3302 | shnum += 1; // .rela.plt | 3463 | shnum += 1; // .rela.plt |
| 3303 | } | 3464 | } |
| ... | @@ -3926,6 +4087,26 @@ fn initHeaders( | ... | @@ -3926,6 +4087,26 @@ fn initHeaders( |
| 3926 | .entsize = @intCast(addr_align.toByteUnits() * 2), | 4087 | .entsize = @intCast(addr_align.toByteUnits() * 2), |
| 3927 | .node_align = addr_align, | 4088 | .node_align = addr_align, |
| 3928 | }); | 4089 | }); |
| | 4090 | elf.shndx.hash = try elf.addSection(elf.ni.rodata, .{ |
| | 4091 | .name = ".hash", |
| | 4092 | .type = .HASH, |
| | 4093 | .flags = .{ .ALLOC = true }, |
| | 4094 | .link = elf.shndx.dynsym.toSection().?, |
| | 4095 | .addralign = .@"4", |
| | 4096 | // initially: nbucket = 8, nchain = 1 |
| | 4097 | .size = @sizeOf(std.elf.hash.Header) + (8 + 1) * 4, |
| | 4098 | }); |
| | 4099 | { |
| | 4100 | const hash_slice: []align(4) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| | 4101 | const header: *std.elf.hash.Header = @ptrCast(hash_slice[0..@sizeOf(std.elf.hash.Header)]); |
| | 4102 | header.* = .{ .nbucket = 8, .nchain = 1 }; |
| | 4103 | if (elf.targetEndian() != std.lang.Endian.native) { |
| | 4104 | std.mem.byteSwapAllFields(std.elf.hash.Header, header); |
| | 4105 | } |
| | 4106 | // The initial bucket and chain values are all 0, but `MappedFile` initialized the |
| | 4107 | // node with zeroes anyway, so no need to memset. |
| | 4108 | } |
| | 4109 | |
| 3929 | switch (machine) { | 4110 | switch (machine) { |
| 3930 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), | 4111 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), |
| 3931 | .X86_64 => { | 4112 | .X86_64 => { |
| ... | @@ -5931,7 +6112,7 @@ fn prepareDynamic(elf: *Elf) Error!void { | ... | @@ -5931,7 +6112,7 @@ fn prepareDynamic(elf: *Elf) Error!void { |
| 5931 | @as(usize, @intFromBool(elf.shndx.preinit_array != .UNDEF)) * 2 + | 6112 | @as(usize, @intFromBool(elf.shndx.preinit_array != .UNDEF)) * 2 + |
| 5932 | @as(usize, @intFromBool(use_plt)) * 4 + | 6113 | @as(usize, @intFromBool(use_plt)) * 4 + |
| 5933 | @intFromBool(comp.config.output_mode == .Exe) + | 6114 | @intFromBool(comp.config.output_mode == .Exe) + |
| 5934 | @intFromBool(elf.textrel_count > 0) + 8; | 6115 | @intFromBool(elf.textrel_count > 0) + 9; |
| 5935 | | 6116 | |
| 5936 | const dynamic_size = dynamic_len * 2 * elf.targetPtrSize(); | 6117 | const dynamic_size = dynamic_len * 2 * elf.targetPtrSize(); |
| 5937 | | 6118 | |
| ... | @@ -6031,7 +6212,7 @@ fn flushDynamic(elf: *Elf) void { | ... | @@ -6031,7 +6212,7 @@ fn flushDynamic(elf: *Elf) void { |
| 6031 | dynamic_index += 4; | 6212 | dynamic_index += 4; |
| 6032 | } | 6213 | } |
| 6033 | | 6214 | |
| 6034 | dynamic_entries[dynamic_index..][0..8].* = .{ | 6215 | dynamic_entries[dynamic_index..][0..9].* = .{ |
| 6035 | .{ std.elf.DT_RELA, @intCast(elf.shndx.rela_dyn.vaddr(elf)) }, | 6216 | .{ std.elf.DT_RELA, @intCast(elf.shndx.rela_dyn.vaddr(elf)) }, |
| 6036 | .{ std.elf.DT_RELASZ, @intCast(elf.shndx.rela_dyn.size(elf)) }, | 6217 | .{ std.elf.DT_RELASZ, @intCast(elf.shndx.rela_dyn.size(elf)) }, |
| 6037 | .{ std.elf.DT_RELAENT, @sizeOf(ElfN.Rela) }, | 6218 | .{ std.elf.DT_RELAENT, @sizeOf(ElfN.Rela) }, |
| ... | @@ -6039,9 +6220,10 @@ fn flushDynamic(elf: *Elf) void { | ... | @@ -6039,9 +6220,10 @@ fn flushDynamic(elf: *Elf) void { |
| 6039 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, | 6220 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, |
| 6040 | .{ std.elf.DT_STRTAB, @intCast(elf.shndx.dynstr.vaddr(elf)) }, | 6221 | .{ std.elf.DT_STRTAB, @intCast(elf.shndx.dynstr.vaddr(elf)) }, |
| 6041 | .{ std.elf.DT_STRSZ, @intCast(elf.shndx.dynstr.size(elf)) }, | 6222 | .{ std.elf.DT_STRSZ, @intCast(elf.shndx.dynstr.size(elf)) }, |
| | 6223 | .{ std.elf.DT_HASH, @intCast(elf.shndx.hash.vaddr(elf)) }, |
| 6042 | .{ std.elf.DT_NULL, 0 }, | 6224 | .{ std.elf.DT_NULL, 0 }, |
| 6043 | }; | 6225 | }; |
| 6044 | dynamic_index += 8; | 6226 | dynamic_index += 9; |
| 6045 | | 6227 | |
| 6046 | assert(dynamic_index == dynamic_entries.len); | 6228 | assert(dynamic_index == dynamic_entries.len); |
| 6047 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| | 6229 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| |
| ... | @@ -7821,6 +8003,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -7821,6 +8003,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 7821 | .REL, | 8003 | .REL, |
| 7822 | .RELA, | 8004 | .RELA, |
| 7823 | .DYNSYM, | 8005 | .DYNSYM, |
| | 8006 | .HASH, |
| 7824 | => return, | 8007 | => return, |
| 7825 | } | 8008 | } |
| 7826 | if (shndx != elf.shndx.plt and | 8009 | if (shndx != elf.shndx.plt and |