/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/Utils/ASanStackFrameLayout.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ASanStackFrameLayout.cpp - helper for AddressSanitizer ------------===// |
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 | | // Definition of ComputeASanStackFrameLayout (see ASanStackFrameLayout.h). |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | #include "llvm/Transforms/Utils/ASanStackFrameLayout.h" |
14 | | #include "llvm/ADT/SmallString.h" |
15 | | #include "llvm/IR/DebugInfo.h" |
16 | | #include "llvm/Support/MathExtras.h" |
17 | | #include "llvm/Support/ScopedPrinter.h" |
18 | | #include "llvm/Support/raw_ostream.h" |
19 | | #include <algorithm> |
20 | | |
21 | | namespace llvm { |
22 | | |
23 | | // We sort the stack variables by alignment (largest first) to minimize |
24 | | // unnecessary large gaps due to alignment. |
25 | | // It is tempting to also sort variables by size so that larger variables |
26 | | // have larger redzones at both ends. But reordering will make report analysis |
27 | | // harder, especially when temporary unnamed variables are present. |
28 | | // So, until we can provide more information (type, line number, etc) |
29 | | // for the stack variables we avoid reordering them too much. |
30 | | static inline bool CompareVars(const ASanStackVariableDescription &a, |
31 | 60 | const ASanStackVariableDescription &b) { |
32 | 60 | return a.Alignment > b.Alignment; |
33 | 60 | } |
34 | | |
35 | | // We also force minimal alignment for all vars to kMinAlignment so that vars |
36 | | // with e.g. alignment 1 and alignment 16 do not get reordered by CompareVars. |
37 | | static const size_t kMinAlignment = 16; |
38 | | |
39 | | // The larger the variable Size the larger is the redzone. |
40 | | // The resulting frame size is a multiple of Alignment. |
41 | 150 | static size_t VarAndRedzoneSize(size_t Size, size_t Alignment) { |
42 | 150 | size_t Res = 0; |
43 | 150 | if (Size <= 4150 ) Res = 1668 ; |
44 | 82 | else if (82 Size <= 1682 ) Res = 3226 ; |
45 | 56 | else if (56 Size <= 12856 ) Res = Size + 3246 ; |
46 | 10 | else if (10 Size <= 51210 ) Res = Size + 642 ; |
47 | 8 | else if (8 Size <= 40968 ) Res = Size + 1288 ; |
48 | 0 | else Res = Size + 256; |
49 | 150 | return alignTo(Res, Alignment); |
50 | 150 | } |
51 | | |
52 | | ASanStackFrameLayout |
53 | | ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars, |
54 | 92 | size_t Granularity, size_t MinHeaderSize) { |
55 | 92 | assert(Granularity >= 8 && Granularity <= 64 && |
56 | 92 | (Granularity & (Granularity - 1)) == 0); |
57 | 92 | assert(MinHeaderSize >= 16 && (MinHeaderSize & (MinHeaderSize - 1)) == 0 && |
58 | 92 | MinHeaderSize >= Granularity); |
59 | 92 | const size_t NumVars = Vars.size(); |
60 | 92 | assert(NumVars > 0); |
61 | 242 | for (size_t i = 0; i < NumVars242 ; i++150 ) |
62 | 150 | Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment); |
63 | 92 | |
64 | 92 | std::stable_sort(Vars.begin(), Vars.end(), CompareVars); |
65 | 92 | |
66 | 92 | ASanStackFrameLayout Layout; |
67 | 92 | Layout.Granularity = Granularity; |
68 | 92 | Layout.FrameAlignment = std::max(Granularity, Vars[0].Alignment); |
69 | 92 | size_t Offset = std::max(std::max(MinHeaderSize, Granularity), |
70 | 92 | Vars[0].Alignment); |
71 | 92 | assert((Offset % Granularity) == 0); |
72 | 242 | for (size_t i = 0; i < NumVars242 ; i++150 ) { |
73 | 150 | bool IsLast = i == NumVars - 1; |
74 | 150 | size_t Alignment = std::max(Granularity, Vars[i].Alignment); |
75 | 150 | (void)Alignment; // Used only in asserts. |
76 | 150 | size_t Size = Vars[i].Size; |
77 | 150 | assert((Alignment & (Alignment - 1)) == 0); |
78 | 150 | assert(Layout.FrameAlignment >= Alignment); |
79 | 150 | assert((Offset % Alignment) == 0); |
80 | 150 | assert(Size > 0); |
81 | 92 | size_t NextAlignment = IsLast ? Granularity |
82 | 58 | : std::max(Granularity, Vars[i + 1].Alignment); |
83 | 150 | size_t SizeWithRedzone = VarAndRedzoneSize(Size, NextAlignment); |
84 | 150 | Vars[i].Offset = Offset; |
85 | 150 | Offset += SizeWithRedzone; |
86 | 150 | } |
87 | 92 | if (Offset % MinHeaderSize92 ) { |
88 | 44 | Offset += MinHeaderSize - (Offset % MinHeaderSize); |
89 | 44 | } |
90 | 92 | Layout.FrameSize = Offset; |
91 | 92 | assert((Layout.FrameSize % MinHeaderSize) == 0); |
92 | 92 | return Layout; |
93 | 92 | } |
94 | | |
95 | | SmallString<64> ComputeASanStackFrameDescription( |
96 | 92 | const SmallVectorImpl<ASanStackVariableDescription> &Vars) { |
97 | 92 | SmallString<2048> StackDescriptionStorage; |
98 | 92 | raw_svector_ostream StackDescription(StackDescriptionStorage); |
99 | 92 | StackDescription << Vars.size(); |
100 | 92 | |
101 | 150 | for (const auto &Var : Vars) { |
102 | 150 | std::string Name = Var.Name; |
103 | 150 | if (Var.Line150 ) { |
104 | 11 | Name += ":"; |
105 | 11 | Name += to_string(Var.Line); |
106 | 11 | } |
107 | 150 | StackDescription << " " << Var.Offset << " " << Var.Size << " " |
108 | 150 | << Name.size() << " " << Name; |
109 | 150 | } |
110 | 92 | return StackDescription.str(); |
111 | 92 | } |
112 | | |
113 | | SmallVector<uint8_t, 64> |
114 | | GetShadowBytes(const SmallVectorImpl<ASanStackVariableDescription> &Vars, |
115 | 127 | const ASanStackFrameLayout &Layout) { |
116 | 127 | assert(Vars.size() > 0); |
117 | 127 | SmallVector<uint8_t, 64> SB; |
118 | 127 | SB.clear(); |
119 | 127 | const size_t Granularity = Layout.Granularity; |
120 | 127 | SB.resize(Vars[0].Offset / Granularity, kAsanStackLeftRedzoneMagic); |
121 | 198 | for (const auto &Var : Vars) { |
122 | 198 | SB.resize(Var.Offset / Granularity, kAsanStackMidRedzoneMagic); |
123 | 198 | |
124 | 198 | SB.resize(SB.size() + Var.Size / Granularity, 0); |
125 | 198 | if (Var.Size % Granularity) |
126 | 142 | SB.push_back(Var.Size % Granularity); |
127 | 198 | } |
128 | 127 | SB.resize(Layout.FrameSize / Granularity, kAsanStackRightRedzoneMagic); |
129 | 127 | return SB; |
130 | 127 | } |
131 | | |
132 | | SmallVector<uint8_t, 64> GetShadowBytesAfterScope( |
133 | | const SmallVectorImpl<ASanStackVariableDescription> &Vars, |
134 | 92 | const ASanStackFrameLayout &Layout) { |
135 | 92 | SmallVector<uint8_t, 64> SB = GetShadowBytes(Vars, Layout); |
136 | 92 | const size_t Granularity = Layout.Granularity; |
137 | 92 | |
138 | 150 | for (const auto &Var : Vars) { |
139 | 150 | assert(Var.LifetimeSize <= Var.Size); |
140 | 150 | const size_t LifetimeShadowSize = |
141 | 150 | (Var.LifetimeSize + Granularity - 1) / Granularity; |
142 | 150 | const size_t Offset = Var.Offset / Granularity; |
143 | 150 | std::fill(SB.begin() + Offset, SB.begin() + Offset + LifetimeShadowSize, |
144 | 150 | kAsanStackUseAfterScopeMagic); |
145 | 150 | } |
146 | 92 | |
147 | 92 | return SB; |
148 | 92 | } |
149 | | |
150 | | } // llvm namespace |