@@ -219,39 +219,18 @@ struct Report {
219219 virtual void generateReport (raw_ostream &OS,
220220 const BinaryContext &BC) const = 0;
221221
222- // The two methods below are called by Analysis::computeDetailedInfo when
223- // iterating over the reports.
224- virtual const ArrayRef<MCPhysReg> getAffectedRegisters () const { return {}; }
225- virtual void setOverwritingInstrs (const ArrayRef<MCInstReference> Instrs) {}
226-
227222 void printBasicInfo (raw_ostream &OS, const BinaryContext &BC,
228223 StringRef IssueKind) const ;
229224};
230225
231226struct GadgetReport : public Report {
232227 // The particular kind of gadget that is detected.
233228 const GadgetKind &Kind;
234- // The set of registers related to this gadget report (possibly empty).
235- SmallVector<MCPhysReg, 1 > AffectedRegisters;
236- // The instructions that clobber the affected registers.
237- // There is no one-to-one correspondence with AffectedRegisters: for example,
238- // the same register can be overwritten by different instructions in different
239- // preceding basic blocks.
240- SmallVector<MCInstReference> OverwritingInstrs;
241-
242- GadgetReport (const GadgetKind &Kind, MCInstReference Location,
243- MCPhysReg AffectedRegister)
244- : Report(Location), Kind(Kind), AffectedRegisters({AffectedRegister}) {}
245-
246- void generateReport (raw_ostream &OS, const BinaryContext &BC) const override ;
247229
248- const ArrayRef<MCPhysReg> getAffectedRegisters () const override {
249- return AffectedRegisters;
250- }
230+ GadgetReport (const GadgetKind &Kind, MCInstReference Location)
231+ : Report(Location), Kind(Kind) {}
251232
252- void setOverwritingInstrs (const ArrayRef<MCInstReference> Instrs) override {
253- OverwritingInstrs.assign (Instrs.begin (), Instrs.end ());
254- }
233+ void generateReport (raw_ostream &OS, const BinaryContext &BC) const override ;
255234};
256235
257236// / Report with a free-form message attached.
@@ -263,8 +242,75 @@ struct GenericReport : public Report {
263242 const BinaryContext &BC) const override ;
264243};
265244
245+ // / An information about an issue collected on the slower, detailed,
246+ // / run of an analysis.
247+ class ExtraInfo {
248+ public:
249+ virtual void print (raw_ostream &OS, const MCInstReference Location) const = 0;
250+
251+ virtual ~ExtraInfo () {}
252+ };
253+
254+ class ClobberingInfo : public ExtraInfo {
255+ SmallVector<MCInstReference> ClobberingInstrs;
256+
257+ public:
258+ ClobberingInfo (const ArrayRef<MCInstReference> Instrs)
259+ : ClobberingInstrs(Instrs) {}
260+
261+ void print (raw_ostream &OS, const MCInstReference Location) const override ;
262+ };
263+
264+ // / A brief version of a report that can be further augmented with the details.
265+ // /
266+ // / It is common for a particular type of gadget detector to be tied to some
267+ // / specific kind of analysis. If an issue is returned by that detector, it may
268+ // / be further augmented with the detailed info in an analysis-specific way,
269+ // / or just be left as-is (f.e. if a free-form warning was reported).
270+ template <typename T> struct BriefReport {
271+ BriefReport (std::shared_ptr<Report> Issue,
272+ const std::optional<T> RequestedDetails)
273+ : Issue(Issue), RequestedDetails(RequestedDetails) {}
274+
275+ std::shared_ptr<Report> Issue;
276+ std::optional<T> RequestedDetails;
277+ };
278+
279+ // / A detailed version of a report.
280+ struct DetailedReport {
281+ DetailedReport (std::shared_ptr<Report> Issue,
282+ std::shared_ptr<ExtraInfo> Details)
283+ : Issue(Issue), Details(Details) {}
284+
285+ std::shared_ptr<Report> Issue;
286+ std::shared_ptr<ExtraInfo> Details;
287+ };
288+
266289struct FunctionAnalysisResult {
267- std::vector<std::shared_ptr<Report>> Diagnostics;
290+ std::vector<DetailedReport> Diagnostics;
291+ };
292+
293+ // / A helper class storing per-function context to be instantiated by Analysis.
294+ class FunctionAnalysis {
295+ BinaryContext &BC;
296+ BinaryFunction &BF;
297+ MCPlusBuilder::AllocatorIdTy AllocatorId;
298+ FunctionAnalysisResult Result;
299+
300+ bool PacRetGadgetsOnly;
301+
302+ void findUnsafeUses (SmallVector<BriefReport<MCPhysReg>> &Reports);
303+ void augmentUnsafeUseReports (const ArrayRef<BriefReport<MCPhysReg>> Reports);
304+
305+ public:
306+ FunctionAnalysis (BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId,
307+ bool PacRetGadgetsOnly)
308+ : BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId),
309+ PacRetGadgetsOnly (PacRetGadgetsOnly) {}
310+
311+ void run ();
312+
313+ const FunctionAnalysisResult &getResult () const { return Result; }
268314};
269315
270316class Analysis : public BinaryFunctionPass {
@@ -273,12 +319,6 @@ class Analysis : public BinaryFunctionPass {
273319
274320 void runOnFunction (BinaryFunction &Function,
275321 MCPlusBuilder::AllocatorIdTy AllocatorId);
276- FunctionAnalysisResult findGadgets (BinaryFunction &BF,
277- MCPlusBuilder::AllocatorIdTy AllocatorId);
278-
279- void computeDetailedInfo (BinaryFunction &BF,
280- MCPlusBuilder::AllocatorIdTy AllocatorId,
281- FunctionAnalysisResult &Result);
282322
283323 std::map<const BinaryFunction *, FunctionAnalysisResult> AnalysisResults;
284324 std::mutex AnalysisResultsMutex;
0 commit comments