|
1 | | -//===- bolt/Passes/NonPacProtectedRetAnalysis.h -----------------*- C++ -*-===// |
| 1 | +//===- bolt/Passes/PAuthGadgetScanner.h -------------------------*- C++ -*-===// |
2 | 2 | // |
3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | 4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | 6 | // |
7 | 7 | //===----------------------------------------------------------------------===// |
8 | 8 |
|
9 | | -#ifndef BOLT_PASSES_NONPACPROTECTEDRETANALYSIS_H |
10 | | -#define BOLT_PASSES_NONPACPROTECTEDRETANALYSIS_H |
| 9 | +#ifndef BOLT_PASSES_PAUTHGADGETSCANNER_H |
| 10 | +#define BOLT_PASSES_PAUTHGADGETSCANNER_H |
11 | 11 |
|
12 | 12 | #include "bolt/Core/BinaryContext.h" |
13 | 13 | #include "bolt/Core/BinaryFunction.h" |
@@ -173,85 +173,104 @@ struct MCInstReference { |
173 | 173 |
|
174 | 174 | raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &); |
175 | 175 |
|
176 | | -struct GeneralDiagnostic { |
177 | | - std::string Text; |
178 | | - GeneralDiagnostic(const std::string &Text) : Text(Text) {} |
179 | | - bool operator==(const GeneralDiagnostic &RHS) const { |
180 | | - return Text == RHS.Text; |
181 | | - } |
| 176 | +namespace PAuthGadgetScanner { |
| 177 | + |
| 178 | +class PacRetAnalysis; |
| 179 | +struct State; |
| 180 | + |
| 181 | +/// Description of a gadget kind that can be detected. Intended to be |
| 182 | +/// statically allocated to be attached to reports by reference. |
| 183 | +class GadgetKind { |
| 184 | + const char *Description; |
| 185 | + |
| 186 | +public: |
| 187 | + GadgetKind(const char *Description) : Description(Description) {} |
| 188 | + |
| 189 | + const StringRef getDescription() const { return Description; } |
182 | 190 | }; |
183 | 191 |
|
184 | | -raw_ostream &operator<<(raw_ostream &OS, const GeneralDiagnostic &Diag); |
| 192 | +/// Base report located at some instruction, without any additional information. |
| 193 | +struct Report { |
| 194 | + MCInstReference Location; |
| 195 | + |
| 196 | + Report(MCInstReference Location) : Location(Location) {} |
| 197 | + virtual ~Report() {} |
185 | 198 |
|
186 | | -namespace NonPacProtectedRetAnalysis { |
187 | | -struct Annotation { |
188 | | - MCInstReference RetInst; |
189 | | - Annotation(MCInstReference RetInst) : RetInst(RetInst) {} |
190 | | - virtual bool operator==(const Annotation &RHS) const { |
191 | | - return RetInst == RHS.RetInst; |
192 | | - } |
193 | | - Annotation &operator=(const Annotation &Other) { |
194 | | - if (this == &Other) |
195 | | - return *this; |
196 | | - RetInst = Other.RetInst; |
197 | | - return *this; |
198 | | - } |
199 | | - virtual ~Annotation() {} |
200 | 199 | virtual void generateReport(raw_ostream &OS, |
201 | 200 | const BinaryContext &BC) const = 0; |
| 201 | + |
| 202 | + // The two methods below are called by Analysis::computeDetailedInfo when |
| 203 | + // iterating over the reports. |
| 204 | + virtual const ArrayRef<MCPhysReg> getAffectedRegisters() const { return {}; } |
| 205 | + virtual void setOverwritingInstrs(const ArrayRef<MCInstReference> Instrs) {} |
| 206 | + |
| 207 | + void printBasicInfo(raw_ostream &OS, const BinaryContext &BC, |
| 208 | + StringRef IssueKind) const; |
202 | 209 | }; |
203 | 210 |
|
204 | | -struct Gadget : public Annotation { |
205 | | - std::vector<MCInstReference> OverwritingRetRegInst; |
206 | | - virtual bool operator==(const Gadget &RHS) const { |
207 | | - return Annotation::operator==(RHS) && |
208 | | - OverwritingRetRegInst == RHS.OverwritingRetRegInst; |
| 211 | +struct GadgetReport : public Report { |
| 212 | + // The particular kind of gadget that is detected. |
| 213 | + const GadgetKind &Kind; |
| 214 | + // The set of registers related to this gadget report (possibly empty). |
| 215 | + SmallVector<MCPhysReg> AffectedRegisters; |
| 216 | + // The instructions that clobber the affected registers. |
| 217 | + // There is no one-to-one correspondence with AffectedRegisters: for example, |
| 218 | + // the same register can be overwritten by different instructions in different |
| 219 | + // preceding basic blocks. |
| 220 | + SmallVector<MCInstReference> OverwritingInstrs; |
| 221 | + |
| 222 | + GadgetReport(const GadgetKind &Kind, MCInstReference Location, |
| 223 | + const BitVector &AffectedRegisters) |
| 224 | + : Report(Location), Kind(Kind), |
| 225 | + AffectedRegisters(AffectedRegisters.set_bits()) {} |
| 226 | + |
| 227 | + void generateReport(raw_ostream &OS, const BinaryContext &BC) const override; |
| 228 | + |
| 229 | + const ArrayRef<MCPhysReg> getAffectedRegisters() const override { |
| 230 | + return AffectedRegisters; |
209 | 231 | } |
210 | | - Gadget(MCInstReference RetInst, |
211 | | - const std::vector<MCInstReference> &OverwritingRetRegInst) |
212 | | - : Annotation(RetInst), OverwritingRetRegInst(OverwritingRetRegInst) {} |
213 | | - virtual void generateReport(raw_ostream &OS, |
214 | | - const BinaryContext &BC) const override; |
215 | | -}; |
216 | 232 |
|
217 | | -struct GenDiag : public Annotation { |
218 | | - GeneralDiagnostic Diag; |
219 | | - virtual bool operator==(const GenDiag &RHS) const { |
220 | | - return Annotation::operator==(RHS) && Diag == RHS.Diag; |
| 233 | + void setOverwritingInstrs(const ArrayRef<MCInstReference> Instrs) override { |
| 234 | + OverwritingInstrs.assign(Instrs.begin(), Instrs.end()); |
221 | 235 | } |
222 | | - GenDiag(MCInstReference RetInst, const std::string &Text) |
223 | | - : Annotation(RetInst), Diag(Text) {} |
| 236 | +}; |
| 237 | + |
| 238 | +/// Report with a free-form message attached. |
| 239 | +struct GenericReport : public Report { |
| 240 | + std::string Text; |
| 241 | + GenericReport(MCInstReference Location, const std::string &Text) |
| 242 | + : Report(Location), Text(Text) {} |
224 | 243 | virtual void generateReport(raw_ostream &OS, |
225 | 244 | const BinaryContext &BC) const override; |
226 | 245 | }; |
227 | 246 |
|
228 | | -class PacRetAnalysis; |
229 | | - |
230 | 247 | struct FunctionAnalysisResult { |
231 | | - SmallSet<MCPhysReg, 1> RegistersAffected; |
232 | | - std::vector<std::shared_ptr<Annotation>> Diagnostics; |
| 248 | + std::vector<std::shared_ptr<Report>> Diagnostics; |
233 | 249 | }; |
234 | 250 |
|
235 | 251 | class Analysis : public BinaryFunctionPass { |
236 | 252 | void runOnFunction(BinaryFunction &Function, |
237 | 253 | MCPlusBuilder::AllocatorIdTy AllocatorId); |
238 | | - FunctionAnalysisResult |
239 | | - computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF, |
240 | | - MCPlusBuilder::AllocatorIdTy AllocatorId); |
| 254 | + FunctionAnalysisResult findGadgets(BinaryFunction &BF, |
| 255 | + MCPlusBuilder::AllocatorIdTy AllocatorId); |
| 256 | + |
| 257 | + void computeDetailedInfo(BinaryFunction &BF, |
| 258 | + MCPlusBuilder::AllocatorIdTy AllocatorId, |
| 259 | + FunctionAnalysisResult &Result); |
241 | 260 |
|
242 | 261 | std::map<const BinaryFunction *, FunctionAnalysisResult> AnalysisResults; |
243 | 262 | std::mutex AnalysisResultsMutex; |
244 | 263 |
|
245 | 264 | public: |
246 | 265 | explicit Analysis() : BinaryFunctionPass(false) {} |
247 | 266 |
|
248 | | - const char *getName() const override { return "non-pac-protected-rets"; } |
| 267 | + const char *getName() const override { return "pauth-gadget-scanner"; } |
249 | 268 |
|
250 | 269 | /// Pass entry point |
251 | 270 | Error runOnFunctions(BinaryContext &BC) override; |
252 | 271 | }; |
253 | 272 |
|
254 | | -} // namespace NonPacProtectedRetAnalysis |
| 273 | +} // namespace PAuthGadgetScanner |
255 | 274 | } // namespace bolt |
256 | 275 | } // namespace llvm |
257 | 276 |
|
|
0 commit comments