blob: 72de212d0df9a97399ef49208a91051b19683a80 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass inserts stack protectors into functions which need them. A variable
11// with a random value in it is stored onto the stack before the local variables
12// are allocated. Upon exiting the block, the stored value is checked. If it's
13// changed, then there was some sort of violation and the program aborts.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CODEGEN_STACKPROTECTOR_H
18#define LLVM_CODEGEN_STACKPROTECTOR_H
19
20#include "llvm/ADT/SmallPtrSet.h"
21#include "llvm/ADT/Triple.h"
22#include "llvm/IR/Instructions.h"
23#include "llvm/IR/ValueMap.h"
24#include "llvm/Pass.h"
25
26namespace llvm {
27
28class BasicBlock;
29class DominatorTree;
30class Function;
31class Instruction;
32class Module;
33class TargetLoweringBase;
34class TargetMachine;
35class Type;
36
37class StackProtector : public FunctionPass {
38public:
39 /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that
40 /// vulnerable stack allocations are located close the stack protector.
41 enum SSPLayoutKind {
42 SSPLK_None, ///< Did not trigger a stack protector. No effect on data
43 ///< layout.
44 SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest
45 ///< to the stack protector.
46 SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest
47 ///< to the stack protector.
48 SSPLK_AddrOf ///< The address of this allocation is exposed and
49 ///< triggered protection. 3rd closest to the protector.
50 };
51
52 /// A mapping of AllocaInsts to their required SSP layout.
53 using SSPLayoutMap = ValueMap<const AllocaInst *, SSPLayoutKind>;
54
55private:
56 const TargetMachine *TM = nullptr;
57
58 /// TLI - Keep a pointer of a TargetLowering to consult for determining
59 /// target type sizes.
60 const TargetLoweringBase *TLI = nullptr;
61 Triple Trip;
62
63 Function *F;
64 Module *M;
65
66 DominatorTree *DT;
67
68 /// Layout - Mapping of allocations to the required SSPLayoutKind.
69 /// StackProtector analysis will update this map when determining if an
70 /// AllocaInst triggers a stack protector.
71 SSPLayoutMap Layout;
72
73 /// \brief The minimum size of buffers that will receive stack smashing
74 /// protection when -fstack-protection is used.
75 unsigned SSPBufferSize = 0;
76
77 /// VisitedPHIs - The set of PHI nodes visited when determining
78 /// if a variable's reference has been taken. This set
79 /// is maintained to ensure we don't visit the same PHI node multiple
80 /// times.
81 SmallPtrSet<const PHINode *, 16> VisitedPHIs;
82
83 // A prologue is generated.
84 bool HasPrologue = false;
85
86 // IR checking code is generated.
87 bool HasIRCheck = false;
88
89 /// InsertStackProtectors - Insert code into the prologue and epilogue of
90 /// the function.
91 ///
92 /// - The prologue code loads and stores the stack guard onto the stack.
93 /// - The epilogue checks the value stored in the prologue against the
94 /// original value. It calls __stack_chk_fail if they differ.
95 bool InsertStackProtectors();
96
97 /// CreateFailBB - Create a basic block to jump to when the stack protector
98 /// check fails.
99 BasicBlock *CreateFailBB();
100
101 /// ContainsProtectableArray - Check whether the type either is an array or
102 /// contains an array of sufficient size so that we need stack protectors
103 /// for it.
104 /// \param [out] IsLarge is set to true if a protectable array is found and
105 /// it is "large" ( >= ssp-buffer-size). In the case of a structure with
106 /// multiple arrays, this gets set if any of them is large.
107 bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false,
108 bool InStruct = false) const;
109
110 /// \brief Check whether a stack allocation has its address taken.
111 bool HasAddressTaken(const Instruction *AI);
112
113 /// RequiresStackProtector - Check whether or not this function needs a
114 /// stack protector based upon the stack protector level.
115 bool RequiresStackProtector();
116
117public:
118 static char ID; // Pass identification, replacement for typeid.
119
120 StackProtector() : FunctionPass(ID), SSPBufferSize(8) {
121 initializeStackProtectorPass(*PassRegistry::getPassRegistry());
122 }
123
124 void getAnalysisUsage(AnalysisUsage &AU) const override;
125
126 SSPLayoutKind getSSPLayout(const AllocaInst *AI) const;
127
128 // Return true if StackProtector is supposed to be handled by SelectionDAG.
129 bool shouldEmitSDCheck(const BasicBlock &BB) const;
130
131 void adjustForColoring(const AllocaInst *From, const AllocaInst *To);
132
133 bool runOnFunction(Function &Fn) override;
134};
135
136} // end namespace llvm
137
138#endif // LLVM_CODEGEN_STACKPROTECTOR_H