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: |
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 | |
112 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
113 | |
114 | // Return true if StackProtector is supposed to be handled by SelectionDAG. |
115 | bool shouldEmitSDCheck(const BasicBlock &BB) const { |
116 | return LayoutInfo.shouldEmitSDCheck(BB); |
117 | } |
118 | |
119 | bool runOnFunction(Function &Fn) override; |
120 | |
121 | void copyToMachineFrameInfo(MachineFrameInfo &MFI) const { |
122 | LayoutInfo.copyToMachineFrameInfo(MFI); |
123 | } |
124 | |
125 | /// Check whether or not \p F needs a stack protector based upon the stack |
126 | /// protector level. |
127 | static bool requiresStackProtector(Function *F, |
128 | SSPLayoutMap *Layout = nullptr) { |
129 | return SSPLayoutAnalysis::requiresStackProtector(F, Layout); |
130 | } |
131 | }; |
132 | |
133 | } // end namespace llvm |
134 | |
135 | #endif // LLVM_CODEGEN_STACKPROTECTOR_H |
136 | |