LLVM  14.0.0git
ASanStackFrameLayout.cpp
Go to the documentation of this file.
1 //===-- ASanStackFrameLayout.cpp - helper for AddressSanitizer ------------===//
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 // Definition of ComputeASanStackFrameLayout (see ASanStackFrameLayout.h).
10 //
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/IR/DebugInfo.h"
18 #include <algorithm>
19 
20 namespace llvm {
21 
22 // We sort the stack variables by alignment (largest first) to minimize
23 // unnecessary large gaps due to alignment.
24 // It is tempting to also sort variables by size so that larger variables
25 // have larger redzones at both ends. But reordering will make report analysis
26 // harder, especially when temporary unnamed variables are present.
27 // So, until we can provide more information (type, line number, etc)
28 // for the stack variables we avoid reordering them too much.
29 static inline bool CompareVars(const ASanStackVariableDescription &a,
31  return a.Alignment > b.Alignment;
32 }
33 
34 // We also force minimal alignment for all vars to kMinAlignment so that vars
35 // with e.g. alignment 1 and alignment 16 do not get reordered by CompareVars.
36 static const size_t kMinAlignment = 16;
37 
38 // We want to add a full redzone after every variable.
39 // The larger the variable Size the larger is the redzone.
40 // The resulting frame size is a multiple of Alignment.
41 static size_t VarAndRedzoneSize(size_t Size, size_t Granularity,
42  size_t Alignment) {
43  size_t Res = 0;
44  if (Size <= 4) Res = 16;
45  else if (Size <= 16) Res = 32;
46  else if (Size <= 128) Res = Size + 32;
47  else if (Size <= 512) Res = Size + 64;
48  else if (Size <= 4096) Res = Size + 128;
49  else Res = Size + 256;
50  return alignTo(std::max(Res, 2 * Granularity), Alignment);
51 }
52 
53 ASanStackFrameLayout
55  size_t Granularity, size_t MinHeaderSize) {
56  assert(Granularity >= 8 && Granularity <= 64 &&
57  (Granularity & (Granularity - 1)) == 0);
58  assert(MinHeaderSize >= 16 && (MinHeaderSize & (MinHeaderSize - 1)) == 0 &&
59  MinHeaderSize >= Granularity);
60  const size_t NumVars = Vars.size();
61  assert(NumVars > 0);
62  for (size_t i = 0; i < NumVars; i++)
63  Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment);
64 
66 
67  ASanStackFrameLayout Layout;
68  Layout.Granularity = Granularity;
69  Layout.FrameAlignment = std::max(Granularity, Vars[0].Alignment);
70  size_t Offset = std::max(std::max(MinHeaderSize, Granularity),
71  Vars[0].Alignment);
72  assert((Offset % Granularity) == 0);
73  for (size_t i = 0; i < NumVars; i++) {
74  bool IsLast = i == NumVars - 1;
75  size_t Alignment = std::max(Granularity, Vars[i].Alignment);
76  (void)Alignment; // Used only in asserts.
77  size_t Size = Vars[i].Size;
78  assert((Alignment & (Alignment - 1)) == 0);
79  assert(Layout.FrameAlignment >= Alignment);
80  assert((Offset % Alignment) == 0);
81  assert(Size > 0);
82  size_t NextAlignment = IsLast ? Granularity
83  : std::max(Granularity, Vars[i + 1].Alignment);
84  size_t SizeWithRedzone = VarAndRedzoneSize(Size, Granularity,
85  NextAlignment);
86  Vars[i].Offset = Offset;
87  Offset += SizeWithRedzone;
88  }
89  if (Offset % MinHeaderSize) {
90  Offset += MinHeaderSize - (Offset % MinHeaderSize);
91  }
92  Layout.FrameSize = Offset;
93  assert((Layout.FrameSize % MinHeaderSize) == 0);
94  return Layout;
95 }
96 
99  SmallString<2048> StackDescriptionStorage;
100  raw_svector_ostream StackDescription(StackDescriptionStorage);
101  StackDescription << Vars.size();
102 
103  for (const auto &Var : Vars) {
104  std::string Name = Var.Name;
105  if (Var.Line) {
106  Name += ":";
107  Name += to_string(Var.Line);
108  }
109  StackDescription << " " << Var.Offset << " " << Var.Size << " "
110  << Name.size() << " " << Name;
111  }
112  return StackDescription.str();
113 }
114 
115 SmallVector<uint8_t, 64>
117  const ASanStackFrameLayout &Layout) {
118  assert(Vars.size() > 0);
120  SB.clear();
121  const size_t Granularity = Layout.Granularity;
122  SB.resize(Vars[0].Offset / Granularity, kAsanStackLeftRedzoneMagic);
123  for (const auto &Var : Vars) {
124  SB.resize(Var.Offset / Granularity, kAsanStackMidRedzoneMagic);
125 
126  SB.resize(SB.size() + Var.Size / Granularity, 0);
127  if (Var.Size % Granularity)
128  SB.push_back(Var.Size % Granularity);
129  }
130  SB.resize(Layout.FrameSize / Granularity, kAsanStackRightRedzoneMagic);
131  return SB;
132 }
133 
136  const ASanStackFrameLayout &Layout) {
137  SmallVector<uint8_t, 64> SB = GetShadowBytes(Vars, Layout);
138  const size_t Granularity = Layout.Granularity;
139 
140  for (const auto &Var : Vars) {
141  assert(Var.LifetimeSize <= Var.Size);
142  const size_t LifetimeShadowSize =
143  (Var.LifetimeSize + Granularity - 1) / Granularity;
144  const size_t Offset = Var.Offset / Granularity;
145  std::fill(SB.begin() + Offset, SB.begin() + Offset + LifetimeShadowSize,
147  }
148 
149  return SB;
150 }
151 
152 } // llvm namespace
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
MathExtras.h
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::ASanStackFrameLayout::FrameSize
size_t FrameSize
Definition: ASanStackFrameLayout.h:47
llvm::ASanStackFrameLayout::Granularity
size_t Granularity
Definition: ASanStackFrameLayout.h:45
llvm::kMinAlignment
static const size_t kMinAlignment
Definition: ASanStackFrameLayout.cpp:36
llvm::GetShadowBytesAfterScope
SmallVector< uint8_t, 64 > GetShadowBytesAfterScope(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
Definition: ASanStackFrameLayout.cpp:134
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::GetShadowBytes
SmallVector< uint8_t, 64 > GetShadowBytes(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
Definition: ASanStackFrameLayout.cpp:116
llvm::VarAndRedzoneSize
static size_t VarAndRedzoneSize(size_t Size, size_t Granularity, size_t Alignment)
Definition: ASanStackFrameLayout.cpp:41
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
ASanStackFrameLayout.h
a
=0.0 ? 0.0 :(a > 0.0 ? 1.0 :-1.0) a
Definition: README.txt:489
SmallString.h
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
llvm::ASanStackFrameLayout::FrameAlignment
size_t FrameAlignment
Definition: ASanStackFrameLayout.h:46
llvm::SmallVectorImpl::resize
void resize(size_type N)
Definition: SmallVector.h:606
llvm::SmallString< 64 >
llvm::CompareVars
static bool CompareVars(const ASanStackVariableDescription &a, const ASanStackVariableDescription &b)
Definition: ASanStackFrameLayout.cpp:29
llvm::kAsanStackUseAfterScopeMagic
static const int kAsanStackUseAfterScopeMagic
Definition: ASanStackFrameLayout.h:27
llvm::kAsanStackLeftRedzoneMagic
static const int kAsanStackLeftRedzoneMagic
Definition: ASanStackFrameLayout.h:23
DebugInfo.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ASanStackVariableDescription
Definition: ASanStackFrameLayout.h:30
llvm::raw_svector_ostream::str
StringRef str() const
Return a StringRef for the vector contents.
Definition: raw_ostream.h:683
llvm::ComputeASanStackFrameLayout
ASanStackFrameLayout ComputeASanStackFrameLayout(SmallVectorImpl< ASanStackVariableDescription > &Vars, size_t Granularity, size_t MinHeaderSize)
Definition: ASanStackFrameLayout.cpp:54
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1684
llvm::kAsanStackRightRedzoneMagic
static const int kAsanStackRightRedzoneMagic
Definition: ASanStackFrameLayout.h:25
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:585
llvm::ComputeASanStackFrameDescription
SmallString< 64 > ComputeASanStackFrameDescription(const SmallVectorImpl< ASanStackVariableDescription > &Vars)
Definition: ASanStackFrameLayout.cpp:97
llvm::to_string
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:63
llvm::kAsanStackMidRedzoneMagic
static const int kAsanStackMidRedzoneMagic
Definition: ASanStackFrameLayout.h:24
llvm::max
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:340
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:658
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
raw_ostream.h
llvm::ASanStackFrameLayout
Definition: ASanStackFrameLayout.h:44
ScopedPrinter.h