#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
bool runOnFunction(Function &Fn) override;
};
-
-/// Diagnostic information for why SSP was applied.
-class DiagnosticInfoSSP : public DiagnosticInfoWithDebugLocBase {
-public:
- enum SSPReason {
- Alloca = 0,
- BufferOrStruct = 1,
- AddressTaken = 2,
- Attribute = 3,
- LastUsedValue = 3
- };
-
- /// \p Fn is the function where the diagnostic is being emitted. \p Reason is
- /// an enum value representing why the function has stack protection.
- DiagnosticInfoSSP(const Function &Fn, SSPReason Reason)
- : DiagnosticInfoWithDebugLocBase(DK_SSPReason, DS_Remark, Fn, DebugLoc()),
- Func(Fn), Why(Reason) {}
-
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_SSPReason;
- }
-
- void print(DiagnosticPrinter &DP) const override;
-
- SSPReason Reason() const { return Why; }
-
-private:
- const Function &Func;
- const SSPReason Why;
-};
} // end namespace llvm
#endif // LLVM_CODEGEN_STACKPROTECTOR_H
DK_MIRParser,
DK_PGOProfile,
DK_Unsupported,
- DK_SSPReason,
DK_FirstPluginKind
};
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
char StackProtector::ID = 0;
INITIALIZE_TM_PASS(StackProtector, "stack-protector", "Insert stack protectors",
- false, true)
+ false, true)
FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
return new StackProtector(TM);
return false;
if (F->hasFnAttribute(Attribute::StackProtectReq)) {
- F->getContext().diagnose(
- DiagnosticInfoSSP(*F, DiagnosticInfoSSP::SSPReason::Attribute));
NeedsProtector = true;
Strong = true; // Use the same heuristic as strong to determine SSPLayout
} else if (F->hasFnAttribute(Attribute::StackProtectStrong))
// A call to alloca with size >= SSPBufferSize requires
// stack protectors.
Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
- F->getContext().diagnose(
- DiagnosticInfoSSP(*F, DiagnosticInfoSSP::SSPReason::Alloca));
NeedsProtector = true;
} else if (Strong) {
// Require protectors for all alloca calls in strong mode.
Layout.insert(std::make_pair(AI, SSPLK_SmallArray));
- F->getContext().diagnose(
- DiagnosticInfoSSP(*F, DiagnosticInfoSSP::SSPReason::Alloca));
NeedsProtector = true;
}
} else {
// A call to alloca with a variable size requires protectors.
Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
- F->getContext().diagnose(
- DiagnosticInfoSSP(*F, DiagnosticInfoSSP::SSPReason::Alloca));
NeedsProtector = true;
}
continue;
if (ContainsProtectableArray(AI->getAllocatedType(), IsLarge, Strong)) {
Layout.insert(std::make_pair(AI, IsLarge ? SSPLK_LargeArray
: SSPLK_SmallArray));
- F->getContext().diagnose(DiagnosticInfoSSP(
- *F, DiagnosticInfoSSP::SSPReason::BufferOrStruct));
NeedsProtector = true;
continue;
}
if (Strong && HasAddressTaken(AI)) {
++NumAddrTaken;
Layout.insert(std::make_pair(AI, SSPLK_AddrOf));
- F->getContext().diagnose(DiagnosticInfoSSP(
- *F, DiagnosticInfoSSP::SSPReason::AddressTaken));
NeedsProtector = true;
}
}
bool StackProtector::shouldEmitSDCheck(const BasicBlock &BB) const {
return HasPrologue && !HasIRCheck && dyn_cast<ReturnInst>(BB.getTerminator());
}
-
-void DiagnosticInfoSSP::print(DiagnosticPrinter &DP) const {
- std::string Str;
- raw_string_ostream OS(Str);
-
- StringRef ReasonStr;
- switch (Reason())
- {
- case Alloca:
- ReasonStr = "a call to alloca or use of a variable length array";
- break;
- case BufferOrStruct:
- ReasonStr = "a stack allocated buffer or struct containing a buffer";
- break;
- case AddressTaken:
- ReasonStr = "the address of a local variable being taken";
- break;
- case Attribute:
- ReasonStr = "a function attribute or command-line switch";
- break;
- }
-
- OS << getLocationStr() << ": SSP applied to function " << Func.getName()
- << " due to " << ReasonStr << '\n';
- OS.flush();
- DP << Str;
-}
+++ /dev/null
-; RUN: llc %s -o /dev/null 2>&1 | FileCheck %s
-; CHECK-NOT: nossp
-; CHECK-NOT: alloca_fixed_small_nossp
-; CHECK: function attribute_ssp
-; CHECK-SAME: a function attribute or command-line switch
-; CHECK: function alloca_fixed_small_ssp
-; CHECK-SAME: a call to alloca or use of a variable length array
-; CHECK: function alloca_fixed_large_ssp
-; CHECK-SAME: a call to alloca or use of a variable length array
-; CHECK: function alloca_variable_ssp
-; CHECK-SAME: a call to alloca or use of a variable length array
-; CHECK: function buffer_ssp
-; CHECK-SAME: a stack allocated buffer or struct containing a buffer
-; CHECK: function struct_ssp
-; CHECK-SAME: a stack allocated buffer or struct containing a buffer
-; CHECK: function address_ssp
-; CHECK-SAME: the address of a local variable being taken
-; CHECK: function multiple_ssp
-; CHECK-SAME: a function attribute or command-line switch
-; CHECK: function multiple_ssp
-; CHECK-SAME: a stack allocated buffer or struct containing a buffer
-; CHECK: function multiple_ssp
-; CHECK-SAME: a stack allocated buffer or struct containing a buffer
-; CHECK: function multiple_ssp
-; CHECK-SAME: the address of a local variable being taken
-; CHECK: function multiple_ssp
-; CHECK-SAME: a call to alloca or use of a variable length array
-
-define void @nossp() sspstrong {
- ret void
-}
-
-define void @attribute_ssp() sspreq {
- ret void
-}
-
-define void @alloca_fixed_small_nossp() ssp {
- %1 = alloca i8, i64 2, align 16
- ret void
-}
-
-define void @alloca_fixed_small_ssp() sspstrong {
- %1 = alloca i8, i64 2, align 16
- ret void
-}
-
-define void @alloca_fixed_large_ssp() ssp {
- %1 = alloca i8, i64 64, align 16
- ret void
-}
-
-define void @alloca_variable_ssp(i64 %x) ssp {
- %1 = alloca i8, i64 %x, align 16
- ret void
-}
-
-define void @buffer_ssp() sspstrong {
- %x = alloca [64 x i32], align 16
- ret void
-}
-
-%struct.X = type { [64 x i32] }
-define void @struct_ssp() sspstrong {
- %x = alloca %struct.X, align 4
- ret void
-}
-
-define void @address_ssp() sspstrong {
-entry:
- %x = alloca i32, align 4
- %y = alloca i32*, align 8
- store i32 32, i32* %x, align 4
- store i32* %x, i32** %y, align 8
- ret void
-}
-
-define void @multiple_ssp() sspreq {
-entry:
- %x = alloca %struct.X, align 4
- %y = alloca [64 x i32], align 16
- %a = alloca i32, align 4
- %b = alloca i32*, align 8
- %0 = alloca i8, i64 2, align 16
- store i32 32, i32* %a, align 4
- store i32* %a, i32** %b, align 8
- ret void
-}