Skip to content

Commit f5401c6

Browse files
authored
[BOLT] Gadget scanner: analyze functions without CFG information (#133461)
Support simple analysis of the functions for which BOLT is unable to reconstruct the CFG. This patch is inspired by the approach implemented by Kristof Beyls in the original prototype of gadget scanner, but a CFG-unaware counterpart of the data-flow analysis is implemented instead of separate version of gadget detector, as multiple gadget kinds are detected now.
1 parent f10a905 commit f5401c6

File tree

6 files changed

+1028
-89
lines changed

6 files changed

+1028
-89
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,19 @@ class BinaryFunction {
804804
return iterator_range<const_cfi_iterator>(cie_begin(), cie_end());
805805
}
806806

807+
/// Iterate over instructions (only if CFG is unavailable or not built yet).
808+
iterator_range<InstrMapType::iterator> instrs() {
809+
assert(!hasCFG() && "Iterate over basic blocks instead");
810+
return make_range(Instructions.begin(), Instructions.end());
811+
}
812+
iterator_range<InstrMapType::const_iterator> instrs() const {
813+
assert(!hasCFG() && "Iterate over basic blocks instead");
814+
return make_range(Instructions.begin(), Instructions.end());
815+
}
816+
817+
/// Returns whether there are any labels at Offset.
818+
bool hasLabelAt(unsigned Offset) const { return Labels.count(Offset) != 0; }
819+
807820
/// Iterate over all jump tables associated with this function.
808821
iterator_range<std::map<uint64_t, JumpTable *>::const_iterator>
809822
jumpTables() const {

bolt/include/bolt/Passes/PAuthGadgetScanner.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ struct MCInstInBFReference {
6565
uint64_t Offset;
6666
MCInstInBFReference(BinaryFunction *BF, uint64_t Offset)
6767
: BF(BF), Offset(Offset) {}
68+
69+
static MCInstInBFReference get(const MCInst *Inst, BinaryFunction &BF) {
70+
for (auto &I : BF.instrs())
71+
if (Inst == &I.second)
72+
return MCInstInBFReference(&BF, I.first);
73+
return {};
74+
}
75+
6876
MCInstInBFReference() : BF(nullptr), Offset(0) {}
6977
bool operator==(const MCInstInBFReference &RHS) const {
7078
return BF == RHS.BF && Offset == RHS.Offset;
@@ -104,6 +112,12 @@ struct MCInstReference {
104112
MCInstReference(BinaryFunction *BF, uint32_t Offset)
105113
: MCInstReference(MCInstInBFReference(BF, Offset)) {}
106114

115+
static MCInstReference get(const MCInst *Inst, BinaryFunction &BF) {
116+
if (BF.hasCFG())
117+
return MCInstInBBReference::get(Inst, BF);
118+
return MCInstInBFReference::get(Inst, BF);
119+
}
120+
107121
bool operator<(const MCInstReference &RHS) const {
108122
if (ParentKind != RHS.ParentKind)
109123
return ParentKind < RHS.ParentKind;
@@ -138,6 +152,16 @@ struct MCInstReference {
138152
llvm_unreachable("");
139153
}
140154

155+
operator bool() const {
156+
switch (ParentKind) {
157+
case BasicBlockParent:
158+
return U.BBRef.BB != nullptr;
159+
case FunctionParent:
160+
return U.BFRef.BF != nullptr;
161+
}
162+
llvm_unreachable("");
163+
}
164+
141165
uint64_t getAddress() const {
142166
switch (ParentKind) {
143167
case BasicBlockParent:

0 commit comments

Comments
 (0)