@@ -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,48 @@ 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+ case JumpTable::JTT_AARCH64_REL1:
629+ case JumpTable::JTT_AARCH64_REL2:
630+ case JumpTable::JTT_AARCH64_REL4:
631+ unsigned ShiftAmt = Type == JumpTable::JTT_AARCH64_REL4 ? 0 : 2 ;
632+ assert (JT &&
633+ " jump table must be non-null for AArch64 in analyzeJumpTable" );
634+ Value = JT->BaseAddress +
635+ (*getUnsignedValueAtAddress (EntryAddress, EntrySize) << ShiftAmt);
636+ break ;
637+ }
628638
629639 // __builtin_unreachable() case.
630640 if (Value == UnreachableAddress) {
@@ -645,24 +655,19 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
645655
646656 // Function or one of its fragments.
647657 const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress (Value);
648- const bool DoesBelongToFunction =
649- BF.containsAddress (Value) ||
650- (TargetBF && areRelatedFragments (TargetBF, &BF));
651- if (!DoesBelongToFunction) {
658+ if (!TargetBF || !areRelatedFragments (TargetBF, &BF)) {
652659 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- }
660+ dbgs () << " FAIL: function doesn't contain this address\n " ;
661+ if (!TargetBF)
662+ break ;
663+ dbgs () << " ! function containing this address: " << *TargetBF << ' \n ' ;
664+ if (!TargetBF->isFragment ())
665+ break ;
666+ dbgs () << " ! is a fragment with parents: " ;
667+ ListSeparator LS;
668+ for (BinaryFunction *Parent : TargetBF->ParentFragments )
669+ dbgs () << LS << *Parent;
670+ dbgs () << ' \n ' ;
666671 });
667672 break ;
668673 }
@@ -677,17 +682,17 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
677682 ++NumRealEntries;
678683 LLVM_DEBUG (dbgs () << formatv (" OK: {0:x} real entry\n " , Value));
679684
680- if (TargetBF != &BF && HasEntryInFragment )
681- *HasEntryInFragment = true ;
685+ if (TargetBF != &BF && JT )
686+ JT-> IsSplit = true ;
682687 addEntryAddress (Value);
683688 }
684689
685690 // Trim direct/normal jump table to exclude trailing unreachable entries that
686691 // can collide with a function address.
687- if (Type == JumpTable::JTT_NORMAL && EntriesAsAddress &&
688- TrimmedSize != EntriesAsAddress-> size () &&
692+ if (Type == JumpTable::JTT_X86_64_ABS && JT &&
693+ TrimmedSize != JT-> EntriesAsAddress . size () &&
689694 getBinaryFunctionAtAddress (UnreachableAddress))
690- EntriesAsAddress-> resize (TrimmedSize);
695+ JT-> EntriesAsAddress . resize (TrimmedSize);
691696
692697 // It's a jump table if the number of real entries is more than 1, or there's
693698 // one real entry and one or more special targets. If there are only multiple
@@ -702,20 +707,20 @@ void BinaryContext::populateJumpTables() {
702707 ++JTI) {
703708 JumpTable *JT = JTI->second ;
704709
705- bool NonSimpleParent = false ;
706- for (BinaryFunction *BF : JT->Parents )
707- NonSimpleParent |= !BF->isSimple ();
708- if (NonSimpleParent)
710+ auto isSimple = std::bind (&BinaryFunction::isSimple, std::placeholders::_1);
711+ if (!llvm::all_of (JT->Parents , isSimple))
709712 continue ;
710713
711714 uint64_t NextJTAddress = 0 ;
712715 auto NextJTI = std::next (JTI);
713- if (NextJTI != JTE)
716+ if (isAArch64 ()) {
717+ NextJTAddress = JT->getAddress () + JT->getSize ();
718+ JT->Entries .clear ();
719+ } else if (NextJTI != JTE)
714720 NextJTAddress = NextJTI->second ->getAddress ();
715721
716- const bool Success =
717- analyzeJumpTable (JT->getAddress (), JT->Type , *(JT->Parents [0 ]),
718- NextJTAddress, &JT->EntriesAsAddress , &JT->IsSplit );
722+ const bool Success = analyzeJumpTable (
723+ JT->getAddress (), JT->Type , *JT->Parents .front (), NextJTAddress, JT);
719724 if (!Success) {
720725 LLVM_DEBUG ({
721726 dbgs () << " failed to analyze " ;
@@ -743,7 +748,7 @@ void BinaryContext::populateJumpTables() {
743748
744749 // In strict mode, erase PC-relative relocation record. Later we check that
745750 // all such records are erased and thus have been accounted for.
746- if (opts::StrictMode && JT->Type == JumpTable::JTT_PIC ) {
751+ if (opts::StrictMode && JT->Type == JumpTable::JTT_X86_64_PIC4 ) {
747752 for (uint64_t Address = JT->getAddress ();
748753 Address < JT->getAddress () + JT->getSize ();
749754 Address += JT->EntrySize ) {
@@ -839,33 +844,26 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
839844 assert (JT->Type == Type && " jump table types have to match" );
840845 assert (Address == JT->getAddress () && " unexpected non-empty jump table" );
841846
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- }
847+ if (llvm::is_contained (JT->Parents , &Function))
848+ return JT->getFirstLabel ();
861849
862- bool IsJumpTableParent = false ;
863- (void )IsJumpTableParent;
864- for (BinaryFunction *Frag : JT->Parents )
865- if (Frag == &Function)
866- IsJumpTableParent = true ;
867- assert (IsJumpTableParent &&
850+ // Prevent associating a jump table to a specific fragment twice.
851+ auto isSibling = std::bind (&BinaryContext::areRelatedFragments, this ,
852+ &Function, std::placeholders::_1);
853+ assert (llvm::all_of (JT->Parents , isSibling) &&
868854 " cannot re-use jump table of a different function" );
855+ if (opts::Verbosity > 2 ) {
856+ this ->outs () << " BOLT-INFO: Multiple fragments access same jump table: "
857+ << JT->Parents [0 ]->getPrintName () << " ; "
858+ << Function.getPrintName () << " \n " ;
859+ JT->print (this ->outs ());
860+ }
861+ if (JT->Parents .size () == 1 )
862+ JT->Parents .front ()->setHasIndirectTargetToSplitFragment (true );
863+ Function.setHasIndirectTargetToSplitFragment (true );
864+ // Duplicate the entry for the parent function for easy access
865+ JT->Parents .push_back (&Function);
866+ Function.JumpTables .emplace (Address, JT);
869867 return JT->getFirstLabel ();
870868 }
871869
0 commit comments