xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/StackProtector.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass inserts stack protectors into functions which need them. A variable
10 // with a random value in it is stored onto the stack before the local variables
11 // are allocated. Upon exiting the block, the stored value is checked. If it's
12 // changed, then there was some sort of violation and the program aborts.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_CODEGEN_STACKPROTECTOR_H
17 #define LLVM_CODEGEN_STACKPROTECTOR_H
18 
19 #include "llvm/Analysis/DomTreeUpdater.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/PassManager.h"
23 #include "llvm/Pass.h"
24 #include "llvm/TargetParser/Triple.h"
25 
26 namespace llvm {
27 
28 class BasicBlock;
29 class Function;
30 class Module;
31 class TargetLoweringBase;
32 class TargetMachine;
33 
34 class SSPLayoutInfo {
35   friend class StackProtectorPass;
36   friend class SSPLayoutAnalysis;
37   friend class StackProtector;
38   static constexpr unsigned DefaultSSPBufferSize = 8;
39 
40   /// A mapping of AllocaInsts to their required SSP layout.
41   using SSPLayoutMap =
42       DenseMap<const AllocaInst *, MachineFrameInfo::SSPLayoutKind>;
43 
44   /// Layout - Mapping of allocations to the required SSPLayoutKind.
45   /// StackProtector analysis will update this map when determining if an
46   /// AllocaInst triggers a stack protector.
47   SSPLayoutMap Layout;
48 
49   /// The minimum size of buffers that will receive stack smashing
50   /// protection when -fstack-protection is used.
51   unsigned SSPBufferSize = DefaultSSPBufferSize;
52 
53   bool RequireStackProtector = false;
54 
55   // A prologue is generated.
56   bool HasPrologue = false;
57 
58   // IR checking code is generated.
59   bool HasIRCheck = false;
60 
61 public:
62   // Return true if StackProtector is supposed to be handled by SelectionDAG.
63   bool shouldEmitSDCheck(const BasicBlock &BB) const;
64 
65   void copyToMachineFrameInfo(MachineFrameInfo &MFI) const;
66 };
67 
68 class SSPLayoutAnalysis : public AnalysisInfoMixin<SSPLayoutAnalysis> {
69   friend AnalysisInfoMixin<SSPLayoutAnalysis>;
70   using SSPLayoutMap = SSPLayoutInfo::SSPLayoutMap;
71 
72   static AnalysisKey Key;
73 
74 public:
75   using Result = SSPLayoutInfo;
76 
77   Result run(Function &F, FunctionAnalysisManager &FAM);
78 
79   /// Check whether or not \p F needs a stack protector based upon the stack
80   /// protector level.
81   static bool requiresStackProtector(Function *F,
82                                      SSPLayoutMap *Layout = nullptr);
83 };
84 
85 class StackProtectorPass : public PassInfoMixin<StackProtectorPass> {
86   const TargetMachine *TM;
87 
88 public:
StackProtectorPass(const TargetMachine * TM)89   explicit StackProtectorPass(const TargetMachine *TM) : TM(TM) {}
90   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
91 };
92 
93 class StackProtector : public FunctionPass {
94 private:
95   /// A mapping of AllocaInsts to their required SSP layout.
96   using SSPLayoutMap = SSPLayoutInfo::SSPLayoutMap;
97 
98   const TargetMachine *TM = nullptr;
99 
100   Function *F = nullptr;
101   Module *M = nullptr;
102 
103   std::optional<DomTreeUpdater> DTU;
104 
105   SSPLayoutInfo LayoutInfo;
106 
107 public:
108   static char ID; // Pass identification, replacement for typeid.
109 
110   StackProtector();
111 
getLayoutInfo()112   SSPLayoutInfo &getLayoutInfo() { return LayoutInfo; }
113 
114   void getAnalysisUsage(AnalysisUsage &AU) const override;
115 
116   // Return true if StackProtector is supposed to be handled by SelectionDAG.
shouldEmitSDCheck(const BasicBlock & BB)117   bool shouldEmitSDCheck(const BasicBlock &BB) const {
118     return LayoutInfo.shouldEmitSDCheck(BB);
119   }
120 
121   bool runOnFunction(Function &Fn) override;
122 
copyToMachineFrameInfo(MachineFrameInfo & MFI)123   void copyToMachineFrameInfo(MachineFrameInfo &MFI) const {
124     LayoutInfo.copyToMachineFrameInfo(MFI);
125   }
126 
127   /// Check whether or not \p F needs a stack protector based upon the stack
128   /// protector level.
129   static bool requiresStackProtector(Function *F,
130                                      SSPLayoutMap *Layout = nullptr) {
131     return SSPLayoutAnalysis::requiresStackProtector(F, Layout);
132   }
133 };
134 
135 } // end namespace llvm
136 
137 #endif // LLVM_CODEGEN_STACKPROTECTOR_H
138