@@ -496,7 +496,7 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
496
496
const MemoryContentsType MemType = analyzeMemoryAt (Address, BF);
497
497
if (MemType == MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE && IsPCRel) {
498
498
const MCSymbol *Symbol =
499
- getOrCreateJumpTable (BF, Address, JumpTable::JTT_PIC );
499
+ getOrCreateJumpTable (BF, Address, JumpTable::JTT_X86_64_PIC4 );
500
500
501
501
return std::make_pair (Symbol, 0 );
502
502
}
@@ -540,10 +540,10 @@ MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
540
540
541
541
// Start with checking for PIC jump table. We expect non-PIC jump tables
542
542
// 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))
544
544
return MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE;
545
545
546
- if (analyzeJumpTable (Address, JumpTable::JTT_NORMAL , BF))
546
+ if (analyzeJumpTable (Address, JumpTable::JTT_X86_64_ABS , BF))
547
547
return MemoryContentsType::POSSIBLE_JUMP_TABLE;
548
548
549
549
return MemoryContentsType::UNKNOWN;
@@ -553,8 +553,7 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
553
553
const JumpTable::JumpTableType Type,
554
554
const BinaryFunction &BF,
555
555
const uint64_t NextJTAddress,
556
- JumpTable::AddressesType *EntriesAsAddress,
557
- bool *HasEntryInFragment) const {
556
+ JumpTable *JT) const {
558
557
// Target address of __builtin_unreachable.
559
558
const uint64_t UnreachableAddress = BF.getAddress () + BF.getSize ();
560
559
@@ -571,11 +570,11 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
571
570
size_t TrimmedSize = 0 ;
572
571
573
572
auto addEntryAddress = [&](uint64_t EntryAddress, bool Unreachable = false ) {
574
- if (!EntriesAsAddress )
573
+ if (!JT )
575
574
return ;
576
- EntriesAsAddress-> emplace_back (EntryAddress);
575
+ JT-> EntriesAsAddress . emplace_back (EntryAddress);
577
576
if (!Unreachable)
578
- TrimmedSize = EntriesAsAddress-> size ();
577
+ TrimmedSize = JT-> EntriesAsAddress . size ();
579
578
};
580
579
581
580
ErrorOr<const BinarySection &> Section = getSectionForAddress (Address);
@@ -594,37 +593,39 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
594
593
if (NextJTAddress)
595
594
UpperBound = std::min (NextJTAddress, UpperBound);
596
595
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)));
603
599
const uint64_t EntrySize = getJumpTableEntrySize (Type);
604
600
for (uint64_t EntryAddress = Address; EntryAddress <= UpperBound - EntrySize;
605
601
EntryAddress += EntrySize) {
606
602
LLVM_DEBUG (dbgs () << " * Checking 0x" << Twine::utohexstr (EntryAddress)
607
603
<< " -> " );
608
604
// Check if there's a proper relocation against the jump table entry.
609
605
if (HasRelocations) {
610
- if (Type == JumpTable::JTT_PIC &&
606
+ if (Type == JumpTable::JTT_X86_64_PIC4 &&
611
607
!DataPCRelocations.count (EntryAddress)) {
612
608
LLVM_DEBUG (
613
609
dbgs () << " FAIL: JTT_PIC table, no relocation for this address\n " );
614
610
break ;
615
611
}
616
- if (Type == JumpTable::JTT_NORMAL && !getRelocationAt (EntryAddress)) {
612
+ if (Type == JumpTable::JTT_X86_64_ABS && !getRelocationAt (EntryAddress)) {
617
613
LLVM_DEBUG (
618
614
dbgs ()
619
615
<< " FAIL: JTT_NORMAL table, no relocation for this address\n " );
620
616
break ;
621
617
}
622
618
}
623
619
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
+ }
628
629
629
630
// __builtin_unreachable() case.
630
631
if (Value == UnreachableAddress) {
@@ -645,24 +646,19 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
645
646
646
647
// Function or one of its fragments.
647
648
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)) {
652
650
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 ' ;
666
662
});
667
663
break ;
668
664
}
@@ -677,17 +673,17 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
677
673
++NumRealEntries;
678
674
LLVM_DEBUG (dbgs () << formatv (" OK: {0:x} real entry\n " , Value));
679
675
680
- if (TargetBF != &BF && HasEntryInFragment )
681
- *HasEntryInFragment = true ;
676
+ if (TargetBF != &BF && JT )
677
+ JT-> IsSplit = true ;
682
678
addEntryAddress (Value);
683
679
}
684
680
685
681
// Trim direct/normal jump table to exclude trailing unreachable entries that
686
682
// 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 () &&
689
685
getBinaryFunctionAtAddress (UnreachableAddress))
690
- EntriesAsAddress-> resize (TrimmedSize);
686
+ JT-> EntriesAsAddress . resize (TrimmedSize);
691
687
692
688
// It's a jump table if the number of real entries is more than 1, or there's
693
689
// one real entry and one or more special targets. If there are only multiple
@@ -702,20 +698,17 @@ void BinaryContext::populateJumpTables() {
702
698
++JTI) {
703
699
JumpTable *JT = JTI->second ;
704
700
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))
709
703
continue ;
710
704
711
705
uint64_t NextJTAddress = 0 ;
712
706
auto NextJTI = std::next (JTI);
713
707
if (NextJTI != JTE)
714
708
NextJTAddress = NextJTI->second ->getAddress ();
715
709
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);
719
712
if (!Success) {
720
713
LLVM_DEBUG ({
721
714
dbgs () << " failed to analyze " ;
@@ -743,7 +736,7 @@ void BinaryContext::populateJumpTables() {
743
736
744
737
// In strict mode, erase PC-relative relocation record. Later we check that
745
738
// 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 ) {
747
740
for (uint64_t Address = JT->getAddress ();
748
741
Address < JT->getAddress () + JT->getSize ();
749
742
Address += JT->EntrySize ) {
@@ -839,33 +832,26 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
839
832
assert (JT->Type == Type && " jump table types have to match" );
840
833
assert (Address == JT->getAddress () && " unexpected non-empty jump table" );
841
834
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 ();
861
837
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) &&
868
842
" 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);
869
855
return JT->getFirstLabel ();
870
856
}
871
857
0 commit comments