[BOLT] Gadget scanner: streamline issue reporting (#131896)
In preparation for adding more gadget kinds to detect, streamline issue reporting. Rename classes representing issue reports. In particular, rename `Annotation` base class to `Report`, as it has nothing to do with "annotations" in `MCPlus` terms anymore. Remove references to "return instructions" from variable names and report messages, use generic terms instead. Rename NonPacProtectedRetAnalysis to PAuthGadgetScanner. Remove `GeneralDiagnostic` as a separate class, make `GenericReport` (former `GenDiag`) store `std::string Text` directly. Remove unused `operator=` and `operator==` methods, as `Report`s are created on the heap and referenced via `shared_ptr`s. Introduce `GadgetKind` class - currently, it only wraps a `const char *` description to display to the user. This description is intended to be a per-gadget-kind constant (or a few hard-coded constants), so no need to store it to `std::string` field in each report instance. To handle both free-form `GenericReport`s and statically-allocated messages without unnecessary overhead, move printing of the report header to the base class (and take the message argument as a `StringRef`).
This commit is contained in:
parent
29e1a7673c
commit
03557169e0
@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/NonPacProtectedRetAnalysis.h -----------------*- C++ -*-===//
|
||||
//===- bolt/Passes/PAuthGadgetScanner.h -------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -6,8 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BOLT_PASSES_NONPACPROTECTEDRETANALYSIS_H
|
||||
#define BOLT_PASSES_NONPACPROTECTEDRETANALYSIS_H
|
||||
#ifndef BOLT_PASSES_PAUTHGADGETSCANNER_H
|
||||
#define BOLT_PASSES_PAUTHGADGETSCANNER_H
|
||||
|
||||
#include "bolt/Core/BinaryContext.h"
|
||||
#include "bolt/Core/BinaryFunction.h"
|
||||
@ -173,63 +173,59 @@ struct MCInstReference {
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &);
|
||||
|
||||
struct GeneralDiagnostic {
|
||||
std::string Text;
|
||||
GeneralDiagnostic(const std::string &Text) : Text(Text) {}
|
||||
bool operator==(const GeneralDiagnostic &RHS) const {
|
||||
return Text == RHS.Text;
|
||||
}
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const GeneralDiagnostic &Diag);
|
||||
|
||||
namespace NonPacProtectedRetAnalysis {
|
||||
struct Annotation {
|
||||
MCInstReference RetInst;
|
||||
Annotation(MCInstReference RetInst) : RetInst(RetInst) {}
|
||||
virtual bool operator==(const Annotation &RHS) const {
|
||||
return RetInst == RHS.RetInst;
|
||||
}
|
||||
Annotation &operator=(const Annotation &Other) {
|
||||
if (this == &Other)
|
||||
return *this;
|
||||
RetInst = Other.RetInst;
|
||||
return *this;
|
||||
}
|
||||
virtual ~Annotation() {}
|
||||
virtual void generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const = 0;
|
||||
};
|
||||
|
||||
struct Gadget : public Annotation {
|
||||
std::vector<MCInstReference> OverwritingRetRegInst;
|
||||
virtual bool operator==(const Gadget &RHS) const {
|
||||
return Annotation::operator==(RHS) &&
|
||||
OverwritingRetRegInst == RHS.OverwritingRetRegInst;
|
||||
}
|
||||
Gadget(MCInstReference RetInst,
|
||||
const std::vector<MCInstReference> &OverwritingRetRegInst)
|
||||
: Annotation(RetInst), OverwritingRetRegInst(OverwritingRetRegInst) {}
|
||||
virtual void generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const override;
|
||||
};
|
||||
|
||||
struct GenDiag : public Annotation {
|
||||
GeneralDiagnostic Diag;
|
||||
virtual bool operator==(const GenDiag &RHS) const {
|
||||
return Annotation::operator==(RHS) && Diag == RHS.Diag;
|
||||
}
|
||||
GenDiag(MCInstReference RetInst, const std::string &Text)
|
||||
: Annotation(RetInst), Diag(Text) {}
|
||||
virtual void generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const override;
|
||||
};
|
||||
namespace PAuthGadgetScanner {
|
||||
|
||||
class PacRetAnalysis;
|
||||
struct State;
|
||||
|
||||
/// Description of a gadget kind that can be detected. Intended to be
|
||||
/// statically allocated to be attached to reports by reference.
|
||||
class GadgetKind {
|
||||
const char *Description;
|
||||
|
||||
public:
|
||||
GadgetKind(const char *Description) : Description(Description) {}
|
||||
|
||||
const StringRef getDescription() const { return Description; }
|
||||
};
|
||||
|
||||
/// Base report located at some instruction, without any additional information.
|
||||
struct Report {
|
||||
MCInstReference Location;
|
||||
|
||||
Report(MCInstReference Location) : Location(Location) {}
|
||||
virtual ~Report() {}
|
||||
|
||||
virtual void generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const = 0;
|
||||
|
||||
void printBasicInfo(raw_ostream &OS, const BinaryContext &BC,
|
||||
StringRef IssueKind) const;
|
||||
};
|
||||
|
||||
struct GadgetReport : public Report {
|
||||
const GadgetKind &Kind;
|
||||
std::vector<MCInstReference> OverwritingInstrs;
|
||||
|
||||
GadgetReport(const GadgetKind &Kind, MCInstReference Location,
|
||||
std::vector<MCInstReference> OverwritingInstrs)
|
||||
: Report(Location), Kind(Kind), OverwritingInstrs(OverwritingInstrs) {}
|
||||
|
||||
void generateReport(raw_ostream &OS, const BinaryContext &BC) const override;
|
||||
};
|
||||
|
||||
/// Report with a free-form message attached.
|
||||
struct GenericReport : public Report {
|
||||
std::string Text;
|
||||
GenericReport(MCInstReference Location, const std::string &Text)
|
||||
: Report(Location), Text(Text) {}
|
||||
virtual void generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const override;
|
||||
};
|
||||
|
||||
struct FunctionAnalysisResult {
|
||||
SmallSet<MCPhysReg, 1> RegistersAffected;
|
||||
std::vector<std::shared_ptr<Annotation>> Diagnostics;
|
||||
std::vector<std::shared_ptr<Report>> Diagnostics;
|
||||
};
|
||||
|
||||
class Analysis : public BinaryFunctionPass {
|
||||
@ -245,13 +241,13 @@ class Analysis : public BinaryFunctionPass {
|
||||
public:
|
||||
explicit Analysis() : BinaryFunctionPass(false) {}
|
||||
|
||||
const char *getName() const override { return "non-pac-protected-rets"; }
|
||||
const char *getName() const override { return "pauth-gadget-scanner"; }
|
||||
|
||||
/// Pass entry point
|
||||
Error runOnFunctions(BinaryContext &BC) override;
|
||||
};
|
||||
|
||||
} // namespace NonPacProtectedRetAnalysis
|
||||
} // namespace PAuthGadgetScanner
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
@ -23,8 +23,8 @@ add_llvm_library(LLVMBOLTPasses
|
||||
LoopInversionPass.cpp
|
||||
LivenessAnalysis.cpp
|
||||
MCF.cpp
|
||||
NonPacProtectedRetAnalysis.cpp
|
||||
PatchEntries.cpp
|
||||
PAuthGadgetScanner.cpp
|
||||
PettisAndHansen.cpp
|
||||
PLTCall.cpp
|
||||
ProfileQualityStats.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/NonPacProtectedRetAnalysis.cpp -------------------------===//
|
||||
//===- bolt/Passes/PAuthGadgetScanner.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -11,7 +11,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "bolt/Passes/NonPacProtectedRetAnalysis.h"
|
||||
#include "bolt/Passes/PAuthGadgetScanner.h"
|
||||
#include "bolt/Core/ParallelUtilities.h"
|
||||
#include "bolt/Passes/DataflowAnalysis.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -20,7 +20,7 @@
|
||||
#include "llvm/Support/Format.h"
|
||||
#include <memory>
|
||||
|
||||
#define DEBUG_TYPE "bolt-nonpacprotectedret"
|
||||
#define DEBUG_TYPE "bolt-pauth-scanner"
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
@ -57,7 +57,7 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &Ref) {
|
||||
llvm_unreachable("");
|
||||
}
|
||||
|
||||
namespace NonPacProtectedRetAnalysis {
|
||||
namespace PAuthGadgetScanner {
|
||||
|
||||
[[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label,
|
||||
const MCInst &MI) {
|
||||
@ -395,7 +395,7 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
|
||||
if (BC.MIB->isReturn(Inst)) {
|
||||
ErrorOr<MCPhysReg> MaybeRetReg = BC.MIB->getRegUsedAsRetDest(Inst);
|
||||
if (MaybeRetReg.getError()) {
|
||||
Result.Diagnostics.push_back(std::make_shared<GenDiag>(
|
||||
Result.Diagnostics.push_back(std::make_shared<GenericReport>(
|
||||
MCInstInBBReference(&BB, I),
|
||||
"Warning: pac-ret analysis could not analyze this return "
|
||||
"instruction"));
|
||||
@ -416,9 +416,10 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
|
||||
LLVM_DEBUG(
|
||||
{ traceRegMask(BC, "Intersection with RetReg", UsedDirtyRegs); });
|
||||
if (UsedDirtyRegs.any()) {
|
||||
static const GadgetKind RetKind("non-protected ret found");
|
||||
// This return instruction needs to be reported
|
||||
Result.Diagnostics.push_back(std::make_shared<Gadget>(
|
||||
MCInstInBBReference(&BB, I),
|
||||
Result.Diagnostics.push_back(std::make_shared<GadgetReport>(
|
||||
RetKind, MCInstInBBReference(&BB, I),
|
||||
PRA.getLastClobberingInsts(Inst, BF, UsedDirtyRegs)));
|
||||
for (MCPhysReg RetRegWithGadget : UsedDirtyRegs.set_bits())
|
||||
Result.RegistersAffected.insert(RetRegWithGadget);
|
||||
@ -480,54 +481,61 @@ static void printBB(const BinaryContext &BC, const BinaryBasicBlock *BB,
|
||||
|
||||
static void reportFoundGadgetInSingleBBSingleOverwInst(
|
||||
raw_ostream &OS, const BinaryContext &BC, const MCInstReference OverwInst,
|
||||
const MCInstReference RetInst) {
|
||||
BinaryBasicBlock *BB = RetInst.getBasicBlock();
|
||||
const MCInstReference Location) {
|
||||
BinaryBasicBlock *BB = Location.getBasicBlock();
|
||||
assert(OverwInst.ParentKind == MCInstReference::BasicBlockParent);
|
||||
assert(RetInst.ParentKind == MCInstReference::BasicBlockParent);
|
||||
assert(Location.ParentKind == MCInstReference::BasicBlockParent);
|
||||
MCInstInBBReference OverwInstBB = OverwInst.U.BBRef;
|
||||
if (BB == OverwInstBB.BB) {
|
||||
// overwriting inst and ret instruction are in the same basic block.
|
||||
assert(OverwInstBB.BBIndex < RetInst.U.BBRef.BBIndex);
|
||||
assert(OverwInstBB.BBIndex < Location.U.BBRef.BBIndex);
|
||||
OS << " This happens in the following basic block:\n";
|
||||
printBB(BC, BB);
|
||||
}
|
||||
}
|
||||
|
||||
void Gadget::generateReport(raw_ostream &OS, const BinaryContext &BC) const {
|
||||
GenDiag(RetInst, "non-protected ret found").generateReport(OS, BC);
|
||||
void Report::printBasicInfo(raw_ostream &OS, const BinaryContext &BC,
|
||||
StringRef IssueKind) const {
|
||||
BinaryFunction *BF = Location.getFunction();
|
||||
BinaryBasicBlock *BB = Location.getBasicBlock();
|
||||
|
||||
BinaryFunction *BF = RetInst.getFunction();
|
||||
OS << " The " << OverwritingRetRegInst.size()
|
||||
<< " instructions that write to the return register after any "
|
||||
"authentication are:\n";
|
||||
// Sort by address to ensure output is deterministic.
|
||||
std::vector<MCInstReference> ORRI = OverwritingRetRegInst;
|
||||
llvm::sort(ORRI, [](const MCInstReference &A, const MCInstReference &B) {
|
||||
return A.getAddress() < B.getAddress();
|
||||
});
|
||||
for (unsigned I = 0; I < ORRI.size(); ++I) {
|
||||
MCInstReference InstRef = ORRI[I];
|
||||
OS << " " << (I + 1) << ". ";
|
||||
BC.printInstruction(OS, InstRef, InstRef.getAddress(), BF);
|
||||
};
|
||||
if (OverwritingRetRegInst.size() == 1) {
|
||||
const MCInstReference OverwInst = OverwritingRetRegInst[0];
|
||||
assert(OverwInst.ParentKind == MCInstReference::BasicBlockParent);
|
||||
reportFoundGadgetInSingleBBSingleOverwInst(OS, BC, OverwInst, RetInst);
|
||||
}
|
||||
}
|
||||
|
||||
void GenDiag::generateReport(raw_ostream &OS, const BinaryContext &BC) const {
|
||||
BinaryFunction *BF = RetInst.getFunction();
|
||||
BinaryBasicBlock *BB = RetInst.getBasicBlock();
|
||||
|
||||
OS << "\nGS-PACRET: " << Diag.Text;
|
||||
OS << "\nGS-PAUTH: " << IssueKind;
|
||||
OS << " in function " << BF->getPrintName();
|
||||
if (BB)
|
||||
OS << ", basic block " << BB->getName();
|
||||
OS << ", at address " << llvm::format("%x", RetInst.getAddress()) << "\n";
|
||||
OS << " The return instruction is ";
|
||||
BC.printInstruction(OS, RetInst, RetInst.getAddress(), BF);
|
||||
OS << ", at address " << llvm::format("%x", Location.getAddress()) << "\n";
|
||||
OS << " The instruction is ";
|
||||
BC.printInstruction(OS, Location, Location.getAddress(), BF);
|
||||
}
|
||||
|
||||
void GadgetReport::generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const {
|
||||
printBasicInfo(OS, BC, Kind.getDescription());
|
||||
|
||||
BinaryFunction *BF = Location.getFunction();
|
||||
OS << " The " << OverwritingInstrs.size()
|
||||
<< " instructions that write to the affected registers after any "
|
||||
"authentication are:\n";
|
||||
// Sort by address to ensure output is deterministic.
|
||||
std::vector<MCInstReference> OI = OverwritingInstrs;
|
||||
llvm::sort(OI, [](const MCInstReference &A, const MCInstReference &B) {
|
||||
return A.getAddress() < B.getAddress();
|
||||
});
|
||||
for (unsigned I = 0; I < OI.size(); ++I) {
|
||||
MCInstReference InstRef = OI[I];
|
||||
OS << " " << (I + 1) << ". ";
|
||||
BC.printInstruction(OS, InstRef, InstRef.getAddress(), BF);
|
||||
};
|
||||
if (OverwritingInstrs.size() == 1) {
|
||||
const MCInstReference OverwInst = OverwritingInstrs[0];
|
||||
assert(OverwInst.ParentKind == MCInstReference::BasicBlockParent);
|
||||
reportFoundGadgetInSingleBBSingleOverwInst(OS, BC, OverwInst, Location);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericReport::generateReport(raw_ostream &OS,
|
||||
const BinaryContext &BC) const {
|
||||
printBasicInfo(OS, BC, Text);
|
||||
}
|
||||
|
||||
Error Analysis::runOnFunctions(BinaryContext &BC) {
|
||||
@ -542,17 +550,16 @@ Error Analysis::runOnFunctions(BinaryContext &BC) {
|
||||
|
||||
ParallelUtilities::runOnEachFunctionWithUniqueAllocId(
|
||||
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
|
||||
SkipFunc, "NonPacProtectedRetAnalysis");
|
||||
SkipFunc, "PAuthGadgetScanner");
|
||||
|
||||
for (BinaryFunction *BF : BC.getAllBinaryFunctions())
|
||||
if (AnalysisResults.count(BF) > 0) {
|
||||
for (const std::shared_ptr<Annotation> &A :
|
||||
AnalysisResults[BF].Diagnostics)
|
||||
A->generateReport(outs(), BC);
|
||||
for (const std::shared_ptr<Report> &R : AnalysisResults[BF].Diagnostics)
|
||||
R->generateReport(outs(), BC);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
} // namespace NonPacProtectedRetAnalysis
|
||||
} // namespace PAuthGadgetScanner
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
@ -20,7 +20,7 @@
|
||||
#include "bolt/Passes/BinaryPasses.h"
|
||||
#include "bolt/Passes/CacheMetrics.h"
|
||||
#include "bolt/Passes/IdenticalCodeFolding.h"
|
||||
#include "bolt/Passes/NonPacProtectedRetAnalysis.h"
|
||||
#include "bolt/Passes/PAuthGadgetScanner.h"
|
||||
#include "bolt/Passes/ReorderFunctions.h"
|
||||
#include "bolt/Profile/BoltAddressTranslation.h"
|
||||
#include "bolt/Profile/DataAggregator.h"
|
||||
@ -3544,8 +3544,7 @@ void RewriteInstance::runBinaryAnalyses() {
|
||||
opts::GadgetScannersToRun.addValue(GSK::GS_ALL);
|
||||
for (GSK ScannerToRun : opts::GadgetScannersToRun) {
|
||||
if (ScannerToRun == GSK::GS_PACRET || ScannerToRun == GSK::GS_ALL)
|
||||
Manager.registerPass(
|
||||
std::make_unique<NonPacProtectedRetAnalysis::Analysis>());
|
||||
Manager.registerPass(std::make_unique<PAuthGadgetScanner::Analysis>());
|
||||
}
|
||||
|
||||
BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());
|
||||
|
@ -13,9 +13,9 @@ f1:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
// autiasp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f1, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f1, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -35,9 +35,9 @@ f_intermediate_overwrite1:
|
||||
add x0, x0, #3
|
||||
autiasp
|
||||
ldp x29, x30, [sp], #16
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_intermediate_overwrite1, basic block {{[0-9a-zA-Z.]+}}
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite1, basic block {{[0-9a-zA-Z.]+}}
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -58,9 +58,9 @@ f_intermediate_overwrite2:
|
||||
ldp x29, x30, [sp], #16
|
||||
autiasp
|
||||
mov x30, x0
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_intermediate_overwrite2, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite2, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov x30, x0
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -97,9 +97,9 @@ f_intermediate_overwrite3:
|
||||
ldp x29, x30, [sp], #16
|
||||
autiasp
|
||||
mov w30, w0
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_intermediate_overwrite3, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite3, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w30, w0
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -121,9 +121,9 @@ f_nonx30_ret:
|
||||
ldp x29, x30, [sp], #16
|
||||
mov x16, x30
|
||||
autiasp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_nonx30_ret, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret x16
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_nonx30_ret, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret x16
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov x16, x30
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -202,9 +202,9 @@ f_nonx30_ret_non_auted:
|
||||
.type f_callclobbered_x30,@function
|
||||
f_callclobbered_x30:
|
||||
bl g
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_callclobbered_x30, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_callclobbered_x30, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl
|
||||
ret
|
||||
.size f_callclobbered_x30, .-f_callclobbered_x30
|
||||
@ -213,9 +213,9 @@ f_callclobbered_x30:
|
||||
.type f_callclobbered_calleesaved,@function
|
||||
f_callclobbered_calleesaved:
|
||||
bl g
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_callclobbered_calleesaved, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret x19
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_callclobbered_calleesaved, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret x19
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl
|
||||
// x19, according to the Arm ABI (AAPCS) is a callee-saved register.
|
||||
// Therefore, if function g respects the AAPCS, it should not write
|
||||
@ -299,9 +299,9 @@ f_autia1716:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autia1716
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autia1716, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autia1716, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -321,9 +321,9 @@ f_autib1716:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autib1716
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autib1716, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autib1716, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -343,9 +343,9 @@ f_autiax12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autia x12, sp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autiax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autiax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -365,9 +365,9 @@ f_autibx12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autib x12, sp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autibx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autibx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -416,9 +416,9 @@ f_autdax12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autda x12, sp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autdax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -438,9 +438,9 @@ f_autdbx12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autdb x12, sp
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autdbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -489,9 +489,9 @@ f_autizax12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autiza x12
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autizax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autizax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -511,9 +511,9 @@ f_autizbx12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autizb x12
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autizbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autizbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -562,9 +562,9 @@ f_autdzax12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autdza x12
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autdzax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdzax12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -584,9 +584,9 @@ f_autdzbx12:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autdzb x12
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autdzbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdzbx12, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -659,8 +659,8 @@ f_eretaa:
|
||||
bl g
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
// CHECK-LABEL: GS-PACRET: Warning: pac-ret analysis could not analyze this return instruction in function f_eretaa, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: eretaa
|
||||
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eretaa, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: eretaa
|
||||
eretaa
|
||||
.size f_eretaa, .-f_eretaa
|
||||
|
||||
@ -673,8 +673,8 @@ f_eretab:
|
||||
bl g
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
// CHECK-LABEL: GS-PACRET: Warning: pac-ret analysis could not analyze this return instruction in function f_eretab, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: eretab
|
||||
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eretab, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: eretab
|
||||
eretab
|
||||
.size f_eretab, .-f_eretab
|
||||
|
||||
@ -687,17 +687,17 @@ f_eret:
|
||||
bl g
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
// CHECK-LABEL: GS-PACRET: Warning: pac-ret analysis could not analyze this return instruction in function f_eret, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: eret
|
||||
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eret, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: eret
|
||||
eret
|
||||
.size f_eret, .-f_eret
|
||||
|
||||
.globl f_movx30reg
|
||||
.type f_movx30reg,@function
|
||||
f_movx30reg:
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_movx30reg, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_movx30reg, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov x30, x22
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: mov x30, x22
|
||||
@ -842,9 +842,9 @@ f_autia171615:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autia171615
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autia171615, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autia171615, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
@ -864,9 +864,9 @@ f_autib171615:
|
||||
add x0, x0, #3
|
||||
ldp x29, x30, [sp], #16
|
||||
autib171615
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_autib171615, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autib171615, basic block {{[0-9a-zA-Z.]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: This happens in the following basic block:
|
||||
// CHECK-NEXT: {{[0-9a-f]+}}: add x0, x0, #0x3
|
||||
|
@ -15,9 +15,9 @@ f_crossbb1:
|
||||
1:
|
||||
ret
|
||||
.size f_crossbb1, .-f_crossbb1
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_crossbb1, basic block {{[^,]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 2 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_crossbb1, basic block {{[^,]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 2 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
// CHECK-NEXT: 2. {{[0-9a-f]+}}: autiasp
|
||||
|
||||
@ -37,9 +37,9 @@ f_mergebb1:
|
||||
1:
|
||||
ret
|
||||
.size f_mergebb1, .-f_mergebb1
|
||||
// CHECK-LABEL: GS-PACRET: non-protected ret found in function f_mergebb1, basic block {{[^,]+}}, at address
|
||||
// CHECK-NEXT: The return instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the return register after any authentication are:
|
||||
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_mergebb1, basic block {{[^,]+}}, at address
|
||||
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
|
||||
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
||||
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
||||
|
||||
.globl f_shrinkwrapping
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
|
||||
// RUN: llvm-bolt-binary-analysis --scanners=pacret -no-threads \
|
||||
// RUN: -debug-only bolt-nonpacprotectedret %t.exe 2>&1 | FileCheck %s
|
||||
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck %s
|
||||
|
||||
// Check the debug output generated by PAuth gadget scanner to make sure the
|
||||
// that output is kept meaningful and to provide an overview of what happens
|
||||
|
Loading…
x
Reference in New Issue
Block a user