diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -366,6 +366,13 @@ BinaryFunction *getBinaryFunctionContainingAddress(uint64_t Address, bool CheckPastEnd = false, bool UseMaxSize = false); + const BinaryFunction * + getBinaryFunctionContainingAddress(uint64_t Address, + bool CheckPastEnd = false, + bool UseMaxSize = false) const { + return const_cast(this) + ->getBinaryFunctionContainingAddress(Address, CheckPastEnd, UseMaxSize); + } /// Return a BinaryFunction that starts at a given \p Address. BinaryFunction *getBinaryFunctionAtAddress(uint64_t Address); @@ -504,9 +511,11 @@ /// Optionally, populate \p Address from jump table entries. The entries /// could be partially populated if the jump table detection fails. bool analyzeJumpTable(const uint64_t Address, - const JumpTable::JumpTableType Type, BinaryFunction &BF, + const JumpTable::JumpTableType Type, + const BinaryFunction &BF, const uint64_t NextJTAddress = 0, - JumpTable::AddressesType *EntriesAsAddress = nullptr); + JumpTable::AddressesType *EntriesAsAddress = nullptr, + bool *HasEntryInFragment = nullptr) const; /// After jump table locations are established, this function will populate /// their EntriesAsAddress based on memory contents. @@ -1143,7 +1152,7 @@ /// Return a relocation registered at a given \p Address, or nullptr if there /// is no relocation at such address. - const Relocation *getRelocationAt(uint64_t Address); + const Relocation *getRelocationAt(uint64_t Address) const; /// Register a presence of PC-relative relocation at the given \p Address. void addPCRelativeDataRelocation(uint64_t Address) { diff --git a/bolt/include/bolt/Core/JumpTable.h b/bolt/include/bolt/Core/JumpTable.h --- a/bolt/include/bolt/Core/JumpTable.h +++ b/bolt/include/bolt/Core/JumpTable.h @@ -66,6 +66,9 @@ /// The type of this jump table. JumpTableType Type; + /// Whether this jump table has entries pointing to multiple functions. + bool IsSplit{false}; + /// All the entries as labels. std::vector Entries; 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 @@ -479,10 +479,12 @@ return MemoryContentsType::UNKNOWN; } -bool BinaryContext::analyzeJumpTable( - const uint64_t Address, const JumpTable::JumpTableType Type, - BinaryFunction &BF, const uint64_t NextJTAddress, - JumpTable::AddressesType *EntriesAsAddress) { +bool BinaryContext::analyzeJumpTable(const uint64_t Address, + const JumpTable::JumpTableType Type, + const BinaryFunction &BF, + const uint64_t NextJTAddress, + JumpTable::AddressesType *EntriesAsAddress, + bool *HasEntryInFragment) const { // Is one of the targets __builtin_unreachable? bool HasUnreachable = false; @@ -495,7 +497,7 @@ }; auto doesBelongToFunction = [&](const uint64_t Addr, - BinaryFunction *TargetBF) -> bool { + const BinaryFunction *TargetBF) -> bool { if (BF.containsAddress(Addr)) return true; // Nothing to do if we failed to identify the containing function. @@ -505,7 +507,7 @@ return BF.isChildOf(*TargetBF) || TargetBF->isChildOf(BF); }; - ErrorOr Section = getSectionForAddress(Address); + ErrorOr Section = getSectionForAddress(Address); if (!Section) return false; @@ -562,7 +564,7 @@ } // Function or one of its fragments. - BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value); + const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value); // We assume that a jump table cannot have function start as an entry. if (!doesBelongToFunction(Value, TargetBF) || Value == BF.getAddress()) { @@ -596,8 +598,8 @@ ++NumRealEntries; LLVM_DEBUG(dbgs() << formatv("OK: {0:x} real entry\n", Value)); - if (TargetBF != &BF) - BF.setHasIndirectTargetToSplitFragment(true); + if (TargetBF != &BF && HasEntryInFragment) + *HasEntryInFragment = true; addEntryAddress(Value); } @@ -627,7 +629,7 @@ const bool Success = analyzeJumpTable(JT->getAddress(), JT->Type, *(JT->Parents[0]), - NextJTAddress, &JT->EntriesAsAddress); + NextJTAddress, &JT->EntriesAsAddress, &JT->IsSplit); if (!Success) { LLVM_DEBUG({ dbgs() << "failed to analyze "; @@ -640,6 +642,8 @@ llvm_unreachable("jump table heuristic failure"); } for (BinaryFunction *Frag : JT->Parents) { + if (JT->IsSplit) + Frag->setHasIndirectTargetToSplitFragment(true); for (uint64_t EntryAddress : JT->EntriesAsAddress) // if target is builtin_unreachable if (EntryAddress == Frag->getAddress() + Frag->getSize()) { @@ -2087,8 +2091,8 @@ return Section->removeRelocationAt(Address - Section->getAddress()); } -const Relocation *BinaryContext::getRelocationAt(uint64_t Address) { - ErrorOr Section = getSectionForAddress(Address); +const Relocation *BinaryContext::getRelocationAt(uint64_t Address) const { + ErrorOr Section = getSectionForAddress(Address); if (!Section) return nullptr;