@@ -496,7 +496,7 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
496496 const MemoryContentsType MemType = analyzeMemoryAt (Address, BF);
497497 if (MemType == MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE && IsPCRel) {
498498 const MCSymbol *Symbol =
499- getOrCreateJumpTable (BF, Address, JumpTable::JTT_PIC );
499+ getOrCreateJumpTable (BF, Address, JumpTable::JTT_X86_64_PIC4 );
500500
501501 return std::make_pair (Symbol, 0 );
502502 }
@@ -540,10 +540,10 @@ MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
540540
541541 // Start with checking for PIC jump table. We expect non-PIC jump tables
542542 // to have high 32 bits set to 0.
543- if (analyzeJumpTable (Address, JumpTable::JTT_PIC , BF))
543+ if (analyzeJumpTable (Address, JumpTable::JTT_X86_64_PIC4 , BF))
544544 return MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE;
545545
546- if (analyzeJumpTable (Address, JumpTable::JTT_NORMAL , BF))
546+ if (analyzeJumpTable (Address, JumpTable::JTT_X86_64_ABS , BF))
547547 return MemoryContentsType::POSSIBLE_JUMP_TABLE;
548548
549549 return MemoryContentsType::UNKNOWN;
@@ -553,8 +553,7 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
553553 const JumpTable::JumpTableType Type,
554554 const BinaryFunction &BF,
555555 const uint64_t NextJTAddress,
556- JumpTable::AddressesType *EntriesAsAddress,
557- bool *HasEntryInFragment) const {
556+ JumpTable *JT) const {
558557 // Target address of __builtin_unreachable.
559558 const uint64_t UnreachableAddress = BF.getAddress () + BF.getSize ();
560559
@@ -571,11 +570,11 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
571570 size_t TrimmedSize = 0 ;
572571
573572 auto addEntryAddress = [&](uint64_t EntryAddress, bool Unreachable = false ) {
574- if (!EntriesAsAddress )
573+ if (!JT )
575574 return ;
576- EntriesAsAddress-> emplace_back (EntryAddress);
575+ JT-> EntriesAsAddress . emplace_back (EntryAddress);
577576 if (!Unreachable)
578- TrimmedSize = EntriesAsAddress-> size ();
577+ TrimmedSize = JT-> EntriesAsAddress . size ();
579578 };
580579
581580 ErrorOr<const BinarySection &> Section = getSectionForAddress (Address);
@@ -594,37 +593,39 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
594593 if (NextJTAddress)
595594 UpperBound = std::min (NextJTAddress, UpperBound);
596595
597- LLVM_DEBUG ({
598- using JTT = JumpTable::JumpTableType;
599- dbgs () << formatv (" BOLT-DEBUG: analyzeJumpTable @{0:x} in {1}, JTT={2}\n " ,
600- Address, BF.getPrintName (),
601- Type == JTT::JTT_PIC ? " PIC" : " Normal" );
602- });
596+ LLVM_DEBUG (
597+ dbgs () << formatv (" BOLT-DEBUG: analyzeJumpTable @{0:x} in {1}, JTT={2}\n " ,
598+ Address, BF, JumpTable::getTypeStr (Type)));
603599 const uint64_t EntrySize = getJumpTableEntrySize (Type);
604600 for (uint64_t EntryAddress = Address; EntryAddress <= UpperBound - EntrySize;
605601 EntryAddress += EntrySize) {
606602 LLVM_DEBUG (dbgs () << " * Checking 0x" << Twine::utohexstr (EntryAddress)
607603 << " -> " );
608604 // Check if there's a proper relocation against the jump table entry.
609605 if (HasRelocations) {
610- if (Type == JumpTable::JTT_PIC &&
606+ if (Type == JumpTable::JTT_X86_64_PIC4 &&
611607 !DataPCRelocations.count (EntryAddress)) {
612608 LLVM_DEBUG (
613609 dbgs () << " FAIL: JTT_PIC table, no relocation for this address\n " );
614610 break ;
615611 }
616- if (Type == JumpTable::JTT_NORMAL && !getRelocationAt (EntryAddress)) {
612+ if (Type == JumpTable::JTT_X86_64_ABS && !getRelocationAt (EntryAddress)) {
617613 LLVM_DEBUG (
618614 dbgs ()
619615 << " FAIL: JTT_NORMAL table, no relocation for this address\n " );
620616 break ;
621617 }
622618 }
623619
624- const uint64_t Value =
625- (Type == JumpTable::JTT_PIC)
626- ? Address + *getSignedValueAtAddress (EntryAddress, EntrySize)
627- : *getPointerAtAddress (EntryAddress);
620+ uint64_t Value = 0 ;
621+ switch (Type) {
622+ case JumpTable::JTT_X86_64_PIC4:
623+ Value = Address + *getSignedValueAtAddress (EntryAddress, EntrySize);
624+ break ;
625+ case JumpTable::JTT_X86_64_ABS:
626+ Value = *getPointerAtAddress (EntryAddress);
627+ break ;
628+ }
628629
629630 // __builtin_unreachable() case.
630631 if (Value == UnreachableAddress) {
@@ -645,24 +646,19 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
645646
646647 // Function or one of its fragments.
647648 const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress (Value);
648- const bool DoesBelongToFunction =
649- BF.containsAddress (Value) ||
650- (TargetBF && areRelatedFragments (TargetBF, &BF));
651- if (!DoesBelongToFunction) {
649+ if (!TargetBF || !areRelatedFragments (TargetBF, &BF)) {
652650 LLVM_DEBUG ({
653- if (!BF.containsAddress (Value)) {
654- dbgs () << " FAIL: function doesn't contain this address\n " ;
655- if (TargetBF) {
656- dbgs () << " ! function containing this address: "
657- << TargetBF->getPrintName () << ' \n ' ;
658- if (TargetBF->isFragment ()) {
659- dbgs () << " ! is a fragment" ;
660- for (BinaryFunction *Parent : TargetBF->ParentFragments )
661- dbgs () << " , parent: " << Parent->getPrintName ();
662- dbgs () << ' \n ' ;
663- }
664- }
665- }
651+ dbgs () << " FAIL: function doesn't contain this address\n " ;
652+ if (!TargetBF)
653+ break ;
654+ dbgs () << " ! function containing this address: " << *TargetBF << ' \n ' ;
655+ if (!TargetBF->isFragment ())
656+ break ;
657+ dbgs () << " ! is a fragment with parents: " ;
658+ ListSeparator LS;
659+ for (BinaryFunction *Parent : TargetBF->ParentFragments )
660+ dbgs () << LS << *Parent;
661+ dbgs () << ' \n ' ;
666662 });
667663 break ;
668664 }
@@ -677,17 +673,17 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
677673 ++NumRealEntries;
678674 LLVM_DEBUG (dbgs () << formatv (" OK: {0:x} real entry\n " , Value));
679675
680- if (TargetBF != &BF && HasEntryInFragment )
681- *HasEntryInFragment = true ;
676+ if (TargetBF != &BF && JT )
677+ JT-> IsSplit = true ;
682678 addEntryAddress (Value);
683679 }
684680
685681 // Trim direct/normal jump table to exclude trailing unreachable entries that
686682 // can collide with a function address.
687- if (Type == JumpTable::JTT_NORMAL && EntriesAsAddress &&
688- TrimmedSize != EntriesAsAddress-> size () &&
683+ if (Type == JumpTable::JTT_X86_64_ABS && JT &&
684+ TrimmedSize != JT-> EntriesAsAddress . size () &&
689685 getBinaryFunctionAtAddress (UnreachableAddress))
690- EntriesAsAddress-> resize (TrimmedSize);
686+ JT-> EntriesAsAddress . resize (TrimmedSize);
691687
692688 // It's a jump table if the number of real entries is more than 1, or there's
693689 // one real entry and one or more special targets. If there are only multiple
@@ -702,20 +698,17 @@ void BinaryContext::populateJumpTables() {
702698 ++JTI) {
703699 JumpTable *JT = JTI->second ;
704700
705- bool NonSimpleParent = false ;
706- for (BinaryFunction *BF : JT->Parents )
707- NonSimpleParent |= !BF->isSimple ();
708- if (NonSimpleParent)
701+ auto isSimple = std::bind (&BinaryFunction::isSimple, std::placeholders::_1);
702+ if (!llvm::all_of (JT->Parents , isSimple))
709703 continue ;
710704
711705 uint64_t NextJTAddress = 0 ;
712706 auto NextJTI = std::next (JTI);
713707 if (NextJTI != JTE)
714708 NextJTAddress = NextJTI->second ->getAddress ();
715709
716- const bool Success =
717- analyzeJumpTable (JT->getAddress (), JT->Type , *(JT->Parents [0 ]),
718- NextJTAddress, &JT->EntriesAsAddress , &JT->IsSplit );
710+ const bool Success = analyzeJumpTable (
711+ JT->getAddress (), JT->Type , *JT->Parents .front (), NextJTAddress, JT);
719712 if (!Success) {
720713 LLVM_DEBUG ({
721714 dbgs () << " failed to analyze " ;
@@ -743,7 +736,7 @@ void BinaryContext::populateJumpTables() {
743736
744737 // In strict mode, erase PC-relative relocation record. Later we check that
745738 // all such records are erased and thus have been accounted for.
746- if (opts::StrictMode && JT->Type == JumpTable::JTT_PIC ) {
739+ if (opts::StrictMode && JT->Type == JumpTable::JTT_X86_64_PIC4 ) {
747740 for (uint64_t Address = JT->getAddress ();
748741 Address < JT->getAddress () + JT->getSize ();
749742 Address += JT->EntrySize ) {
@@ -839,33 +832,26 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
839832 assert (JT->Type == Type && " jump table types have to match" );
840833 assert (Address == JT->getAddress () && " unexpected non-empty jump table" );
841834
842- // Prevent associating a jump table to a specific fragment twice.
843- if (!llvm::is_contained (JT->Parents , &Function)) {
844- assert (llvm::all_of (JT->Parents ,
845- [&](const BinaryFunction *BF) {
846- return areRelatedFragments (&Function, BF);
847- }) &&
848- " cannot re-use jump table of a different function" );
849- // Duplicate the entry for the parent function for easy access
850- JT->Parents .push_back (&Function);
851- if (opts::Verbosity > 2 ) {
852- this ->outs () << " BOLT-INFO: Multiple fragments access same jump table: "
853- << JT->Parents [0 ]->getPrintName () << " ; "
854- << Function.getPrintName () << " \n " ;
855- JT->print (this ->outs ());
856- }
857- Function.JumpTables .emplace (Address, JT);
858- for (BinaryFunction *Parent : JT->Parents )
859- Parent->setHasIndirectTargetToSplitFragment (true );
860- }
835+ if (llvm::is_contained (JT->Parents , &Function))
836+ return JT->getFirstLabel ();
861837
862- bool IsJumpTableParent = false ;
863- (void )IsJumpTableParent;
864- for (BinaryFunction *Frag : JT->Parents )
865- if (Frag == &Function)
866- IsJumpTableParent = true ;
867- assert (IsJumpTableParent &&
838+ // Prevent associating a jump table to a specific fragment twice.
839+ auto isSibling = std::bind (&BinaryContext::areRelatedFragments, this ,
840+ &Function, std::placeholders::_1);
841+ assert (llvm::all_of (JT->Parents , isSibling) &&
868842 " cannot re-use jump table of a different function" );
843+ if (opts::Verbosity > 2 ) {
844+ this ->outs () << " BOLT-INFO: Multiple fragments access same jump table: "
845+ << JT->Parents [0 ]->getPrintName () << " ; "
846+ << Function.getPrintName () << " \n " ;
847+ JT->print (this ->outs ());
848+ }
849+ if (JT->Parents .size () == 1 )
850+ JT->Parents .front ()->setHasIndirectTargetToSplitFragment (true );
851+ Function.setHasIndirectTargetToSplitFragment (true );
852+ // Duplicate the entry for the parent function for easy access
853+ JT->Parents .push_back (&Function);
854+ Function.JumpTables .emplace (Address, JT);
869855 return JT->getFirstLabel ();
870856 }
871857
0 commit comments