diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:03:47 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:04:23 +0000 |
commit | 7fa27ce4a07f19b07799a767fc29416f3b625afb (patch) | |
tree | 27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/Object/ELFObjectFile.cpp | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
download | src-7fa27ce4a07f19b07799a767fc29416f3b625afb.tar.gz src-7fa27ce4a07f19b07799a767fc29416f3b625afb.zip |
Vendor import of llvm-project main llvmorg-17-init-19304-gd0b54bb50e51,vendor/llvm-project/llvmorg-17-init-19304-gd0b54bb50e51
the last commit before the upstream release/17.x branch was created.
Diffstat (limited to 'llvm/lib/Object/ELFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/ELFObjectFile.cpp | 162 |
1 files changed, 103 insertions, 59 deletions
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index ebc57bd04be7..143f9d37849d 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -11,10 +11,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/ELFObjectFile.h" -#include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCInstrAnalysis.h" -#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFTypes.h" @@ -26,6 +24,8 @@ #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" #include "llvm/Support/RISCVISAInfo.h" +#include "llvm/TargetParser/SubtargetFeature.h" +#include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cstddef> #include <cstdint> @@ -73,7 +73,7 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) { std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj.getBuffer()); std::size_t MaxAlignment = - 1ULL << countTrailingZeros( + 1ULL << llvm::countr_zero( reinterpret_cast<uintptr_t>(Obj.getBufferStart())); if (MaxAlignment < 2) @@ -303,12 +303,7 @@ Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const { std::optional<StringRef> Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); if (Attr) { - // Suppress version checking for experimental extensions to prevent erroring - // when getting any unknown version of experimental extension. - auto ParseResult = RISCVISAInfo::parseArchString( - *Attr, /*EnableExperimentalExtension=*/true, - /*ExperimentalExtensionVersionCheck=*/false, - /*IgnoreUnknown=*/true); + auto ParseResult = RISCVISAInfo::parseNormalizedArchString(*Attr); if (!ParseResult) return ParseResult.takeError(); auto &ISAInfo = *ParseResult; @@ -363,6 +358,7 @@ std::optional<StringRef> ELFObjectFileBase::tryGetCPUName() const { switch (getEMachine()) { case ELF::EM_AMDGPU: return getAMDGPUCPUName(); + case ELF::EM_PPC: case ELF::EM_PPC64: return StringRef("future"); default: @@ -468,6 +464,10 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { return "gfx90c"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX940: return "gfx940"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX941: + return "gfx941"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX942: + return "gfx942"; // AMDGCN GFX10. case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1010: @@ -502,6 +502,10 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { return "gfx1102"; case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1103: return "gfx1103"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1150: + return "gfx1150"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151: + return "gfx1151"; default: llvm_unreachable("Unknown EF_AMDGPU_MACH value"); } @@ -602,20 +606,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: @@ -629,7 +634,9 @@ ELFObjectFileBase::getPltAddresses() const { T->createMCInstrAnalysis(MII.get())); if (!MIA) return {}; - std::optional<SectionRef> Plt, RelaPlt, GotPlt; + 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(); if (!NameOrErr) { @@ -638,42 +645,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") - GotPlt = Section; - } - if (!Plt || !RelaPlt || !GotPlt) - return {}; - Expected<StringRef> PltContents = Plt->getContents(); - if (!PltContents) { - consumeError(PltContents.takeError()); - return {}; + } 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)); + } } - auto PltEntries = MIA->findPltEntries(Plt->getAddress(), - arrayRefFromStringRef(*PltContents), - GotPlt->getAddress(), Triple); + // Build a map from GOT entry virtual address to PLT entry virtual address. DenseMap<uint64_t, uint64_t> GotToPlt; - for (const auto &Entry : PltEntries) - GotToPlt.insert(std::make_pair(Entry.second, Entry.first)); + 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. + // 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; } @@ -681,24 +712,39 @@ template <class ELFT> Expected<std::vector<BBAddrMap>> static readBBAddrMapImpl( const ELFFile<ELFT> &EF, std::optional<unsigned> TextSectionIndex) { using Elf_Shdr = typename ELFT::Shdr; + bool IsRelocatable = EF.getHeader().e_type == ELF::ET_REL; std::vector<BBAddrMap> BBAddrMaps; + const auto &Sections = cantFail(EF.sections()); - for (const Elf_Shdr &Sec : Sections) { + auto IsMatch = [&](const Elf_Shdr &Sec) -> Expected<bool> { if (Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP && Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP_V0) - continue; - if (TextSectionIndex) { - Expected<const Elf_Shdr *> TextSecOrErr = EF.getSection(Sec.sh_link); - if (!TextSecOrErr) - return createError("unable to get the linked-to section for " + - describe(EF, Sec) + ": " + - toString(TextSecOrErr.takeError())); - if (*TextSectionIndex != std::distance(Sections.begin(), *TextSecOrErr)) - continue; - } - Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = EF.decodeBBAddrMap(Sec); + return false; + if (!TextSectionIndex) + return true; + Expected<const Elf_Shdr *> TextSecOrErr = EF.getSection(Sec.sh_link); + if (!TextSecOrErr) + return createError("unable to get the linked-to section for " + + describe(EF, Sec) + ": " + + toString(TextSecOrErr.takeError())); + if (*TextSectionIndex != std::distance(Sections.begin(), *TextSecOrErr)) + return false; + return true; + }; + + Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SectionRelocMapOrErr = + EF.getSectionAndRelocations(IsMatch); + if (!SectionRelocMapOrErr) + return SectionRelocMapOrErr.takeError(); + + for (auto const &[Sec, RelocSec] : *SectionRelocMapOrErr) { + if (IsRelocatable && !RelocSec) + return createError("unable to get relocation section for " + + describe(EF, *Sec)); + Expected<std::vector<BBAddrMap>> BBAddrMapOrErr = + EF.decodeBBAddrMap(*Sec, RelocSec); if (!BBAddrMapOrErr) - return createError("unable to read " + describe(EF, Sec) + ": " + + return createError("unable to read " + describe(EF, *Sec) + ": " + toString(BBAddrMapOrErr.takeError())); std::move(BBAddrMapOrErr->begin(), BBAddrMapOrErr->end(), std::back_inserter(BBAddrMaps)); @@ -783,8 +829,6 @@ Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap( return readBBAddrMapImpl(Obj->getELFFile(), TextSectionIndex); if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this)) return readBBAddrMapImpl(Obj->getELFFile(), TextSectionIndex); - if (const auto *Obj = cast<ELF64BEObjectFile>(this)) - return readBBAddrMapImpl(Obj->getELFFile(), TextSectionIndex); - else - llvm_unreachable("Unsupported binary format"); + return readBBAddrMapImpl(cast<ELF64BEObjectFile>(this)->getELFFile(), + TextSectionIndex); } |