Skip to content

Commit 9d2fa17

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.4
2 parents 9925359 + 78e4597 commit 9d2fa17

File tree

8 files changed

+93
-69
lines changed

8 files changed

+93
-69
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,18 @@ class BinaryContext {
435435

436436
/// Return size of an entry for the given jump table \p Type.
437437
uint64_t getJumpTableEntrySize(JumpTable::JumpTableType Type) const {
438-
return Type == JumpTable::JTT_PIC ? 4 : AsmInfo->getCodePointerSize();
438+
switch (Type) {
439+
case JumpTable::JTT_X86_64_PIC4:
440+
return 4;
441+
case JumpTable::JTT_X86_64_ABS:
442+
return AsmInfo->getCodePointerSize();
443+
case JumpTable::JTT_AARCH64_REL1:
444+
return 1;
445+
case JumpTable::JTT_AARCH64_REL2:
446+
return 2;
447+
case JumpTable::JTT_AARCH64_REL4:
448+
return 4;
449+
}
439450
}
440451

441452
/// Return JumpTable containing a given \p Address.

bolt/include/bolt/Core/JumpTable.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,34 @@ class JumpTable : public BinaryData {
4747

4848
public:
4949
enum JumpTableType : char {
50-
JTT_NORMAL,
51-
JTT_PIC,
50+
JTT_X86_64_FIRST = 0,
51+
JTT_X86_64_ABS = JTT_X86_64_FIRST,
52+
JTT_X86_64_PIC4,
53+
JTT_X86_64_LAST = JTT_X86_64_PIC4,
54+
JTT_AARCH64_FIRST,
55+
JTT_AARCH64_REL1 = JTT_AARCH64_FIRST,
56+
JTT_AARCH64_REL2,
57+
JTT_AARCH64_REL4,
58+
JTT_AARCH64_LAST = JTT_AARCH64_REL4
5259
};
5360

61+
static StringRef getTypeStr(JumpTableType Type) {
62+
switch (Type) {
63+
case JTT_X86_64_ABS:
64+
return "X86_64_ABS";
65+
case JTT_X86_64_PIC4:
66+
return "X86_64_PIC4";
67+
case JTT_AARCH64_REL1:
68+
return "AARCH64_REL1";
69+
case JTT_AARCH64_REL2:
70+
return "AARCH64_REL2";
71+
case JTT_AARCH64_REL4:
72+
return "AARCH64_REL4";
73+
}
74+
}
75+
76+
const StringRef getTypeStr() { return getTypeStr(Type); }
77+
5478
/// Branch statistics for jump table entries.
5579
struct JumpInfo {
5680
uint64_t Mispreds{0};

bolt/lib/Core/BinaryContext.cpp

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
@@ -607,13 +607,13 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
607607
<< " -> ");
608608
// Check if there's a proper relocation against the jump table entry.
609609
if (HasRelocations) {
610-
if (Type == JumpTable::JTT_PIC &&
610+
if (Type == JumpTable::JTT_X86_64_PIC4 &&
611611
!DataPCRelocations.count(EntryAddress)) {
612612
LLVM_DEBUG(
613613
dbgs() << "FAIL: JTT_PIC table, no relocation for this address\n");
614614
break;
615615
}
616-
if (Type == JumpTable::JTT_NORMAL && !getRelocationAt(EntryAddress)) {
616+
if (Type == JumpTable::JTT_X86_64_ABS && !getRelocationAt(EntryAddress)) {
617617
LLVM_DEBUG(
618618
dbgs()
619619
<< "FAIL: JTT_NORMAL table, no relocation for this address\n");
@@ -645,24 +645,19 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
645645

646646
// Function or one of its fragments.
647647
const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value);
648-
const bool DoesBelongToFunction =
649-
BF.containsAddress(Value) ||
650-
(TargetBF && areRelatedFragments(TargetBF, &BF));
651-
if (!DoesBelongToFunction) {
648+
if (!TargetBF || !areRelatedFragments(TargetBF, &BF)) {
652649
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-
}
650+
dbgs() << "FAIL: function doesn't contain this address\n";
651+
if (!TargetBF)
652+
break;
653+
dbgs() << " ! function containing this address: " << *TargetBF << '\n';
654+
if (!TargetBF->isFragment())
655+
break;
656+
dbgs() << " ! is a fragment with parents: ";
657+
ListSeparator LS;
658+
for (BinaryFunction *Parent : TargetBF->ParentFragments)
659+
dbgs() << LS << *Parent;
660+
dbgs() << '\n';
666661
});
667662
break;
668663
}
@@ -702,10 +697,8 @@ void BinaryContext::populateJumpTables() {
702697
++JTI) {
703698
JumpTable *JT = JTI->second;
704699

705-
bool NonSimpleParent = false;
706-
for (BinaryFunction *BF : JT->Parents)
707-
NonSimpleParent |= !BF->isSimple();
708-
if (NonSimpleParent)
700+
auto isSimple = std::bind(&BinaryFunction::isSimple, std::placeholders::_1);
701+
if (!llvm::all_of(JT->Parents, isSimple))
709702
continue;
710703

711704
uint64_t NextJTAddress = 0;
@@ -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

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
850850
}
851851
LastLabel = LI->second;
852852
}
853-
if (JT.Type == JumpTable::JTT_NORMAL) {
853+
if (JT.Type == JumpTable::JTT_X86_64_ABS) {
854854
Streamer.emitSymbolValue(Entry, JT.OutputEntrySize);
855855
} else { // JTT_PIC
856856
const MCSymbolRefExpr *JTExpr =

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
912912
"Invalid memory instruction");
913913
const MCExpr *FixedEntryDispExpr = FixedEntryDispOperand->getExpr();
914914
const uint64_t EntryAddress = getExprValue(FixedEntryDispExpr);
915-
uint64_t EntrySize = BC.getJumpTableEntrySize(JumpTable::JTT_PIC);
915+
uint64_t EntrySize = BC.getJumpTableEntrySize(JumpTable::JTT_X86_64_PIC4);
916916
ErrorOr<int64_t> Value =
917917
BC.getSignedValueAtAddress(EntryAddress, EntrySize);
918918
if (!Value)
@@ -982,12 +982,14 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
982982
MemoryContentsType MemType;
983983
if (JumpTable *JT = BC.getJumpTableContainingAddress(ArrayStart)) {
984984
switch (JT->Type) {
985-
case JumpTable::JTT_NORMAL:
985+
case JumpTable::JTT_X86_64_ABS:
986986
MemType = MemoryContentsType::POSSIBLE_JUMP_TABLE;
987987
break;
988-
case JumpTable::JTT_PIC:
988+
case JumpTable::JTT_X86_64_PIC4:
989989
MemType = MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE;
990990
break;
991+
default:
992+
llvm_unreachable("Unhandled jump table type");
991993
}
992994
} else {
993995
MemType = BC.analyzeMemoryAt(ArrayStart, *this);
@@ -998,7 +1000,7 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
9981000
if (BranchType == IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE) {
9991001
if (MemType != MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE)
10001002
return IndirectBranchType::UNKNOWN;
1001-
JTType = JumpTable::JTT_PIC;
1003+
JTType = JumpTable::JTT_X86_64_PIC4;
10021004
} else {
10031005
if (MemType == MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE)
10041006
return IndirectBranchType::UNKNOWN;
@@ -1007,7 +1009,7 @@ BinaryFunction::processIndirectBranch(MCInst &Instruction, unsigned Size,
10071009
return IndirectBranchType::POSSIBLE_TAIL_CALL;
10081010

10091011
BranchType = IndirectBranchType::POSSIBLE_JUMP_TABLE;
1010-
JTType = JumpTable::JTT_NORMAL;
1012+
JTType = JumpTable::JTT_X86_64_ABS;
10111013
}
10121014

10131015
// Convert the instruction into jump table branch.
@@ -1779,7 +1781,8 @@ void BinaryFunction::postProcessJumpTables() {
17791781
// Create labels for all entries.
17801782
for (auto &JTI : JumpTables) {
17811783
JumpTable &JT = *JTI.second;
1782-
if (JT.Type == JumpTable::JTT_PIC && opts::JumpTables == JTS_BASIC) {
1784+
if (JT.Type == JumpTable::JTT_X86_64_PIC4 &&
1785+
opts::JumpTables == JTS_BASIC) {
17831786
opts::JumpTables = JTS_MOVE;
17841787
BC.outs() << "BOLT-INFO: forcing -jump-tables=move as PIC jump table was "
17851788
"detected in function "
@@ -1974,7 +1977,7 @@ bool BinaryFunction::postProcessIndirectBranches(
19741977
BC.MIB->unsetJumpTable(Instr);
19751978

19761979
JumpTable *JT = BC.getJumpTableContainingAddress(LastJT);
1977-
if (JT->Type == JumpTable::JTT_NORMAL) {
1980+
if (JT->Type == JumpTable::JTT_X86_64_ABS) {
19781981
// Invalidating the jump table may also invalidate other jump table
19791982
// boundaries. Until we have/need a support for this, mark the
19801983
// function as non-simple.

bolt/lib/Core/JumpTable.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ void bolt::JumpTable::updateOriginal() {
8585
uint64_t EntryOffset = BaseOffset;
8686
for (MCSymbol *Entry : Entries) {
8787
const uint64_t RelType =
88-
Type == JTT_NORMAL ? ELF::R_X86_64_64 : ELF::R_X86_64_PC32;
88+
Type == JTT_X86_64_ABS ? ELF::R_X86_64_64 : ELF::R_X86_64_PC32;
8989
const uint64_t RelAddend =
90-
Type == JTT_NORMAL ? 0 : EntryOffset - BaseOffset;
90+
Type == JTT_X86_64_ABS ? 0 : EntryOffset - BaseOffset;
9191
// Replace existing relocation with the new one to allow any modifications
9292
// to the original jump table.
9393
if (BC.HasRelocations)
@@ -99,7 +99,7 @@ void bolt::JumpTable::updateOriginal() {
9999

100100
void bolt::JumpTable::print(raw_ostream &OS) const {
101101
uint64_t Offset = 0;
102-
if (Type == JTT_PIC)
102+
if (Type == JTT_X86_64_PIC4)
103103
OS << "PIC ";
104104
ListSeparator LS;
105105

bolt/lib/Passes/IndirectCallPromotion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ IndirectCallPromotion::getCallTargets(BinaryBasicBlock &BB,
246246

247247
if (const JumpTable *JT = BF.getJumpTable(Inst)) {
248248
// Don't support PIC jump tables for now
249-
if (!opts::ICPJumpTablesByTarget && JT->Type == JumpTable::JTT_PIC)
249+
if (!opts::ICPJumpTablesByTarget && JT->Type == JumpTable::JTT_X86_64_PIC4)
250250
return Targets;
251251
const Location From(BF.getSymbol());
252252
const std::pair<size_t, size_t> Range =
@@ -256,7 +256,7 @@ IndirectCallPromotion::getCallTargets(BinaryBasicBlock &BB,
256256
const JumpTable::JumpInfo *JI =
257257
JT->Counts.empty() ? &DefaultJI : &JT->Counts[Range.first];
258258
const size_t JIAdj = JT->Counts.empty() ? 0 : 1;
259-
assert(JT->Type == JumpTable::JTT_PIC ||
259+
assert(JT->Type == JumpTable::JTT_X86_64_PIC4 ||
260260
JT->EntrySize == BC.AsmInfo->getCodePointerSize());
261261
for (size_t I = Range.first; I < Range.second; ++I, JI += JIAdj) {
262262
MCSymbol *Entry = JT->Entries[I];

bolt/lib/Passes/JTFootprintReduction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ bool JTFootprintReduction::tryOptimizePIC(BinaryContext &BC,
202202

203203
JumpTable->OutputEntrySize = 4;
204204
// DePICify
205-
JumpTable->Type = JumpTable::JTT_NORMAL;
205+
JumpTable->Type = JumpTable::JTT_X86_64_ABS;
206206

207207
BB.replaceInstruction(Inst, NewFrag.begin(), NewFrag.end());
208208
return true;

0 commit comments

Comments
 (0)