| ... | @@ -100,13 +100,15 @@ dynstr: StringTable, | ... | @@ -100,13 +100,15 @@ dynstr: StringTable, |
| 100 | /// | 100 | /// |
| 101 | /// Value is the output relocation in `.rela.dyn` for the GOT entry. | 101 | /// Value is the output relocation in `.rela.dyn` for the GOT entry. |
| 102 | got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), | 102 | got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), |
| | 103 | /// Key is the name of a global. |
| | 104 | /// |
| 103 | /// Indices map 1--1 to indices into the actual `.got.plt` section. These also equal indices into | 105 | /// Indices map 1--1 to indices into the actual `.got.plt` section. These also equal indices into |
| 104 | /// the relocations in `.rela.plt`, because every PLT entry has one output relocation (if a runtime | 106 | /// the relocations in `.rela.plt`, because every PLT entry has one output relocation (if a runtime |
| 105 | /// relocation is no longer necessary, then neither is the corresponding PLT entry!). | 107 | /// relocation is no longer necessary, then neither is the corresponding PLT entry!). |
| 106 | /// | 108 | /// |
| 107 | /// PLT entries in this map may be "dead", meaning the PLT entry has been deemed unnecessary so is | 109 | /// PLT entries in this map may be "dead", meaning the PLT entry has been deemed unnecessary so is |
| 108 | /// available for reuse---see `Elf.pltEntryIsDead`. Such entries must not be targeted by relocs. | 110 | /// available for reuse---see `Elf.pltEntryIsDead`. Such entries must not be targeted by relocs. |
| 109 | plt: std.array_hash_map.Auto(Symbol.Id, void), | 111 | plt: std.array_hash_map.Auto(String(.strtab), void), |
| 110 | /// The `.plt` section contains zero or more symbol relocations starting at this index. | 112 | /// The `.plt` section contains zero or more symbol relocations starting at this index. |
| 111 | plt_first_symbol_reloc: SymbolReloc.Index, | 113 | plt_first_symbol_reloc: SymbolReloc.Index, |
| 112 | /// The `.dynamic` section contains zero or more symbol relocations starting at this index. | 114 | /// The `.dynamic` section contains zero or more symbol relocations starting at this index. |
| ... | @@ -1126,7 +1128,10 @@ const SymbolReloc = struct { | ... | @@ -1126,7 +1128,10 @@ const SymbolReloc = struct { |
| 1126 | target_endian, | 1128 | target_endian, |
| 1127 | ), | 1129 | ), |
| 1128 | .pltrel64 => { | 1130 | .pltrel64 => { |
| 1129 | const plt_index = elf.plt.getIndex(reloc.target) orelse continue :type .rel64; | 1131 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1132 | .local => continue :type .rel64, |
| | 1133 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64, |
| | 1134 | }; |
| 1130 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel64; | 1135 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel64; |
| 1131 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { | 1136 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1132 | else => |machine| @panic(@tagName(machine)), | 1137 | else => |machine| @panic(@tagName(machine)), |
| ... | @@ -1141,7 +1146,10 @@ const SymbolReloc = struct { | ... | @@ -1141,7 +1146,10 @@ const SymbolReloc = struct { |
| 1141 | ); | 1146 | ); |
| 1142 | }, | 1147 | }, |
| 1143 | .pltrel32 => { | 1148 | .pltrel32 => { |
| 1144 | const plt_index = elf.plt.getIndex(reloc.target) orelse continue :type .rel32; | 1149 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1150 | .local => continue :type .rel32, |
| | 1151 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32, |
| | 1152 | }; |
| 1145 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel32; | 1153 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel32; |
| 1146 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { | 1154 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1147 | else => |machine| @panic(@tagName(machine)), | 1155 | else => |machine| @panic(@tagName(machine)), |
| ... | @@ -1843,7 +1851,7 @@ fn setGlobalSymbolValue( | ... | @@ -1843,7 +1851,7 @@ fn setGlobalSymbolValue( |
| 1843 | // If this symbol was previously undefined, it may have had a PLT entry. If so, we now need to | 1851 | // If this symbol was previously undefined, it may have had a PLT entry. If so, we now need to |
| 1844 | // delete its newly-unnecessary runtime relocation to avoid a runtime dynamic linker error. | 1852 | // delete its newly-unnecessary runtime relocation to avoid a runtime dynamic linker error. |
| 1845 | // This also allows the PLT entry to be reused---see `pltEntryIsDead`. | 1853 | // This also allows the PLT entry to be reused---see `pltEntryIsDead`. |
| 1846 | if (elf.plt.getIndex(.global(global_name))) |plt_index| { | 1854 | if (elf.plt.getIndex(global_name)) |plt_index| { |
| 1847 | // TODO: we might still need the PLT entry if the symbol could be preempted/interposed! See | 1855 | // TODO: we might still need the PLT entry if the symbol could be preempted/interposed! See |
| 1848 | // matching comment at the end of `addGlobalSymbolAssumeCapacity`. | 1856 | // matching comment at the end of `addGlobalSymbolAssumeCapacity`. |
| 1849 | if (!elf.pltEntryIsDead(plt_index)) { | 1857 | if (!elf.pltEntryIsDead(plt_index)) { |
| ... | @@ -2033,13 +2041,13 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -2033,13 +2041,13 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2033 | | 2041 | |
| 2034 | if (plt_index < elf.plt.count()) { | 2042 | if (plt_index < elf.plt.count()) { |
| 2035 | // We reused a free entry, so we're already done! | 2043 | // We reused a free entry, so we're already done! |
| 2036 | elf.plt.setKey(plt_index, .global(global_name)); | 2044 | elf.plt.setKey(plt_index, global_name); |
| 2037 | return; | 2045 | return; |
| 2038 | } | 2046 | } |
| 2039 | | 2047 | |
| 2040 | // We added a new entry, so we now need to extend the PLT sections. | 2048 | // We added a new entry, so we now need to extend the PLT sections. |
| 2041 | assert(plt_index == elf.plt.count()); | 2049 | assert(plt_index == elf.plt.count()); |
| 2042 | elf.plt.putAssumeCapacityNoClobber(.global(global_name), {}); | 2050 | elf.plt.putAssumeCapacityNoClobber(global_name, {}); |
| 2043 | | 2051 | |
| 2044 | switch (elf.ehdrField(.machine)) { | 2052 | switch (elf.ehdrField(.machine)) { |
| 2045 | else => |machine| @panic(@tagName(machine)), | 2053 | else => |machine| @panic(@tagName(machine)), |
| ... | @@ -6995,8 +7003,8 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad | ... | @@ -6995,8 +7003,8 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad |
| 6995 | // its relocations are probably going through the PLT, so we don't bother with | 7003 | // its relocations are probably going through the PLT, so we don't bother with |
| 6996 | // specific tracking for PLT relocations---instead just re-apply all relocations | 7004 | // specific tracking for PLT relocations---instead just re-apply all relocations |
| 6997 | // targeting symbols with PLT entries. | 7005 | // targeting symbols with PLT entries. |
| 6998 | for (elf.plt.keys()) |sym| { | 7006 | for (elf.plt.keys()) |name| { |
| 6999 | sym.applyTargetRelocs(elf); | 7007 | Symbol.Id.global(name).applyTargetRelocs(elf); |
| 7000 | } | 7008 | } |
| 7001 | // We also need to update all of the references from `.plt.sec` to `.got.plt`. | 7009 | // We also need to update all of the references from `.plt.sec` to `.got.plt`. |
| 7002 | // However, if there's also a flush pending for `.got.plt`, don't bother doing | 7010 | // However, if there's also a flush pending for `.got.plt`, don't bother doing |