diff options
Diffstat (limited to 'llvm/lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/ELFObjectFile.cpp | 85 |
1 files changed, 53 insertions, 32 deletions
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 204ba6b..da36da3 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -601,20 +601,21 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { TheTriple.setArchName(Triple); } -std::vector<std::pair<std::optional<DataRefImpl>, uint64_t>> -ELFObjectFileBase::getPltAddresses() const { +std::vector<ELFPltEntry> ELFObjectFileBase::getPltEntries() const { std::string Err; const auto Triple = makeTriple(); const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err); if (!T) return {}; - uint64_t JumpSlotReloc = 0; + uint32_t JumpSlotReloc = 0, GlobDatReloc = 0; switch (Triple.getArch()) { case Triple::x86: JumpSlotReloc = ELF::R_386_JUMP_SLOT; + GlobDatReloc = ELF::R_386_GLOB_DAT; break; case Triple::x86_64: JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT; + GlobDatReloc = ELF::R_X86_64_GLOB_DAT; break; case Triple::aarch64: case Triple::aarch64_be: @@ -628,7 +629,8 @@ ELFObjectFileBase::getPltAddresses() const { T->createMCInstrAnalysis(MII.get())); if (!MIA) return {}; - std::optional<SectionRef> Plt, RelaPlt; + std::vector<std::pair<uint64_t, uint64_t>> PltEntries; + std::optional<SectionRef> RelaPlt, RelaDyn; uint64_t GotBaseVA = 0; for (const SectionRef &Section : sections()) { Expected<StringRef> NameOrErr = Section.getName(); @@ -638,47 +640,66 @@ ELFObjectFileBase::getPltAddresses() const { } StringRef Name = *NameOrErr; - if (Name == ".plt") - Plt = Section; - else if (Name == ".rela.plt" || Name == ".rel.plt") + if (Name == ".rela.plt" || Name == ".rel.plt") { RelaPlt = Section; - else if (Name == ".got.plt") + } else if (Name == ".rela.dyn" || Name == ".rel.dyn") { + RelaDyn = Section; + } else if (Name == ".got.plt") { GotBaseVA = Section.getAddress(); + } else if (Name == ".plt" || Name == ".plt.got") { + Expected<StringRef> PltContents = Section.getContents(); + if (!PltContents) { + consumeError(PltContents.takeError()); + return {}; + } + llvm::append_range( + PltEntries, + MIA->findPltEntries(Section.getAddress(), + arrayRefFromStringRef(*PltContents), Triple)); + } } - if (!Plt || !RelaPlt) - return {}; - Expected<StringRef> PltContents = Plt->getContents(); - if (!PltContents) { - consumeError(PltContents.takeError()); - return {}; - } - auto PltEntries = MIA->findPltEntries( - Plt->getAddress(), arrayRefFromStringRef(*PltContents), Triple); // Build a map from GOT entry virtual address to PLT entry virtual address. DenseMap<uint64_t, uint64_t> GotToPlt; - for (auto [Plt, GotPltEntry] : PltEntries) { + for (auto [Plt, GotPlt] : PltEntries) { + uint64_t GotPltEntry = GotPlt; // An x86-32 PIC PLT uses jmp DWORD PTR [ebx-offset]. Add // _GLOBAL_OFFSET_TABLE_ (EBX) to get the .got.plt (or .got) entry address. - if (static_cast<int64_t>(GotPltEntry) < 0 && getEMachine() == ELF::EM_386) - GotPltEntry = ~GotPltEntry + GotBaseVA; + // See X86MCTargetDesc.cpp:findPltEntries for the 1 << 32 bit. + if (GotPltEntry & (uint64_t(1) << 32) && getEMachine() == ELF::EM_386) + GotPltEntry = static_cast<int32_t>(GotPltEntry) + GotBaseVA; GotToPlt.insert(std::make_pair(GotPltEntry, Plt)); } + // Find the relocations in the dynamic relocation table that point to // locations in the GOT for which we know the corresponding PLT entry. - std::vector<std::pair<std::optional<DataRefImpl>, uint64_t>> Result; - for (const auto &Relocation : RelaPlt->relocations()) { - if (Relocation.getType() != JumpSlotReloc) - continue; - auto PltEntryIter = GotToPlt.find(Relocation.getOffset()); - if (PltEntryIter != GotToPlt.end()) { - symbol_iterator Sym = Relocation.getSymbol(); - if (Sym == symbol_end()) - Result.emplace_back(std::nullopt, PltEntryIter->second); - else - Result.emplace_back(Sym->getRawDataRefImpl(), PltEntryIter->second); + std::vector<ELFPltEntry> Result; + auto handleRels = [&](iterator_range<relocation_iterator> Rels, + uint32_t RelType, StringRef PltSec) { + for (const auto &R : Rels) { + if (R.getType() != RelType) + continue; + auto PltEntryIter = GotToPlt.find(R.getOffset()); + if (PltEntryIter != GotToPlt.end()) { + symbol_iterator Sym = R.getSymbol(); + if (Sym == symbol_end()) + Result.push_back( + ELFPltEntry{PltSec, std::nullopt, PltEntryIter->second}); + else + Result.push_back(ELFPltEntry{PltSec, Sym->getRawDataRefImpl(), + PltEntryIter->second}); + } } - } + }; + + if (RelaPlt) + handleRels(RelaPlt->relocations(), JumpSlotReloc, ".plt"); + + // If a symbol needing a PLT entry also needs a GLOB_DAT relocation, GNU ld's + // x86 port places the PLT entry in the .plt.got section. + if (RelaDyn) + handleRels(RelaDyn->relocations(), GlobDatReloc, ".plt.got"); + return Result; } |