[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:
Anatoly Trosinenko 2025-03-21 11:19:53 +03:00 committed by GitHub
parent 29e1a7673c
commit 03557169e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 183 additions and 181 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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