aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/Object/ELFObjectFile.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
downloadsrc-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.cpp162
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);
}