Skip to content

Commit 7743262

Browse files
committed
[BOLT] Gadget scanner: analyze functions without CFG information
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 b54b3e8 commit 7743262

File tree

6 files changed

+1028
-89
lines changed

6 files changed

+1028
-89
lines changed

bolt/include/bolt/Core/BinaryFunction.h

+13
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,19 @@ class BinaryFunction {
799799
return iterator_range<const_cfi_iterator>(cie_begin(), cie_end());
800800
}
801801

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

bolt/include/bolt/Passes/PAuthGadgetScanner.h

+24
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ struct MCInstInBFReference {
6767
uint64_t Offset;
6868
MCInstInBFReference(BinaryFunction *BF, uint64_t Offset)
6969
: BF(BF), Offset(Offset) {}
70+
71+
static MCInstInBFReference get(const MCInst *Inst, BinaryFunction &BF) {
72+
for (auto &I : BF.instrs())
73+
if (Inst == &I.second)
74+
return MCInstInBFReference(&BF, I.first);
75+
return {};
76+
}
77+
7078
MCInstInBFReference() : BF(nullptr), Offset(0) {}
7179
bool operator==(const MCInstInBFReference &RHS) const {
7280
return BF == RHS.BF && Offset == RHS.Offset;
@@ -106,6 +114,12 @@ struct MCInstReference {
106114
MCInstReference(BinaryFunction *BF, uint32_t Offset)
107115
: MCInstReference(MCInstInBFReference(BF, Offset)) {}
108116

117+
static MCInstReference get(const MCInst *Inst, BinaryFunction &BF) {
118+
if (BF.hasCFG())
119+
return MCInstInBBReference::get(Inst, BF);
120+
return MCInstInBFReference::get(Inst, BF);
121+
}
122+
109123
bool operator<(const MCInstReference &RHS) const {
110124
if (ParentKind != RHS.ParentKind)
111125
return ParentKind < RHS.ParentKind;
@@ -140,6 +154,16 @@ struct MCInstReference {
140154
llvm_unreachable("");
141155
}
142156

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

0 commit comments

Comments
 (0)