aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object/ELFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/ELFObjectFile.cpp85
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;
}