diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -495,6 +495,7 @@ const uint64_t NextJTAddress, JumpTable::AddressesType *EntriesAsAddress, bool *HasEntryInFragment) const { + using JTT = JumpTable::JumpTableType; // Is one of the targets __builtin_unreachable? bool HasUnreachable = false; @@ -506,6 +507,27 @@ EntriesAsAddress->emplace_back(EntryAddress); }; + // Dynamic relocations are only eligible for jump table entries if their + // computed value is known to always point to the same location (code target) + // at runtime. + // + // A prerequisite for that is that 1) they are from read-only section (or + // write-once, such as in PT_GNU_RELRO case), 2) the value can't point to any + // location other than jump table target. The latter only holds for *_RELATIVE + // relocations where the value is computed against the base address at which a + // shared object has been loaded into memory during execution, hence it can't + // arbitrarily change. + auto hasEligibleDynamicRelocation = [&](uint64_t EntryAddress) { + const Relocation *Relocation = getDynamicRelocationAt(EntryAddress); + if (!Relocation || !Relocation->isRelative()) + return false; + if (auto SectionOrErr = getSectionForAddress(EntryAddress)) { + const BinarySection &Section = SectionOrErr.get(); + return !Section.isWritable() || Section.isRelro(); + } + return false; + }; + ErrorOr Section = getSectionForAddress(Address); if (!Section) return false; @@ -523,7 +545,6 @@ UpperBound = std::min(NextJTAddress, UpperBound); LLVM_DEBUG({ - using JTT = JumpTable::JumpTableType; dbgs() << formatv("BOLT-DEBUG: analyzeJumpTable @{0:x} in {1}, JTT={2}\n", Address, BF.getPrintName(), Type == JTT::JTT_PIC ? "PIC" : "Normal"); @@ -535,16 +556,13 @@ << " -> "); // Check if there's a proper relocation against the jump table entry. if (HasRelocations) { - if (Type == JumpTable::JTT_PIC && - !DataPCRelocations.count(EntryAddress)) { - LLVM_DEBUG( - dbgs() << "FAIL: JTT_PIC table, no relocation for this address\n"); + if (Type == JTT::JTT_PIC && !DataPCRelocations.count(EntryAddress)) { + LLVM_DEBUG(dbgs() << "FAIL: no relocation for this address\n"); break; } - if (Type == JumpTable::JTT_NORMAL && !getRelocationAt(EntryAddress)) { - LLVM_DEBUG( - dbgs() - << "FAIL: JTT_NORMAL table, no relocation for this address\n"); + if (Type == JTT::JTT_NORMAL && !getRelocationAt(EntryAddress) && + !hasEligibleDynamicRelocation(EntryAddress)) { + LLVM_DEBUG(dbgs() << "FAIL: no relocation for this address\n"); break; } }