diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -35,6 +35,8 @@ int32_t index) const override { llvm_unreachable("should call writePPC32GlinkSection() instead"); } + void writeIplt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index) const override; void writeGotPlt(uint8_t *buf, const Symbol &s) const override; bool needsThunk(RelExpr expr, RelType relocType, const InputFile *file, uint64_t branchAddr, const Symbol &s, @@ -144,7 +146,7 @@ gotPltHeaderEntriesNum = 0; pltHeaderSize = 64; // size of PLTresolve in .glink pltEntrySize = 4; - ipltEntrySize = 4; + ipltEntrySize = 16; needsThunks = true; @@ -158,6 +160,20 @@ write32(trapInstr.data(), 0x7fe00008); } +void PPC::writeIplt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index) const { + uint64_t va = gotPltEntryAddr; + // !config->isPic + write32(buf + 0, 0x3d600000 | (va + 0x8000) >> 16); // lis r11,ha + write32(buf + 4, 0x816b0000 | (uint16_t)va); // lwz r11,l(r11) + write32(buf + 8, 0x7d6903a6); // mtctr r11 + write32(buf + 12, 0x4e800420); // bctr + + // config->isPic + // file->ppc32Got2OutSecOff is not known. + // See Thunks.cpp PPC32PltCallStub::writeTo +} + void PPC::writeGotHeader(uint8_t *buf) const { // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],