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 uint64_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.
42  uint64_t Alignment) {
43  uint64_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  uint64_t Granularity, uint64_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);
71  std::max(std::max(MinHeaderSize, Granularity), Vars[0].Alignment);
72  assert((Offset % Granularity) == 0);
73  for (size_t i = 0; i < NumVars; i++) {
74  bool IsLast = i == NumVars - 1;
75  uint64_t Alignment = std::max(Granularity, Vars[i].Alignment);
76  (void)Alignment; // Used only in asserts.
77  uint64_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  uint64_t NextAlignment =
83  IsLast ? Granularity : std::max(Granularity, Vars[i + 1].Alignment);
84  uint64_t SizeWithRedzone =
85  VarAndRedzoneSize(Size, Granularity, 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 uint64_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 uint64_t Granularity = Layout.Granularity;
139 
140  for (const auto &Var : Vars) {
141  assert(Var.LifetimeSize <= Var.Size);
142  const uint64_t LifetimeShadowSize =
143  (Var.LifetimeSize + Granularity - 1) / Granularity;
144  const uint64_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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::VarAndRedzoneSize
static uint64_t VarAndRedzoneSize(uint64_t Size, uint64_t Granularity, uint64_t Alignment)
Definition: ASanStackFrameLayout.cpp:41
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:1177
llvm::GetShadowBytes
SmallVector< uint8_t, 64 > GetShadowBytes(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
Definition: ASanStackFrameLayout.cpp:116
llvm::kMinAlignment
static const uint64_t kMinAlignment
Definition: ASanStackFrameLayout.cpp:36
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:80
llvm::ASanStackFrameLayout::Granularity
uint64_t Granularity
Definition: ASanStackFrameLayout.h:45
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::SmallVectorImpl::resize
void resize(size_type N)
Definition: SmallVector.h:609
llvm::SmallString< 64 >
llvm::CompareVars
static bool CompareVars(const ASanStackVariableDescription &a, const ASanStackVariableDescription &b)
Definition: ASanStackFrameLayout.cpp:29
uint64_t
llvm::kAsanStackUseAfterScopeMagic
static const int kAsanStackUseAfterScopeMagic
Definition: ASanStackFrameLayout.h:27
llvm::kAsanStackLeftRedzoneMagic
static const int kAsanStackLeftRedzoneMagic
Definition: ASanStackFrameLayout.h:23
DebugInfo.h
llvm::ASanStackFrameLayout::FrameSize
uint64_t FrameSize
Definition: ASanStackFrameLayout.h:47
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ASanStackVariableDescription
Definition: ASanStackFrameLayout.h:30
llvm::ASanStackFrameLayout::FrameAlignment
uint64_t FrameAlignment
Definition: ASanStackFrameLayout.h:46
llvm::raw_svector_ostream::str
StringRef str() const
Return a StringRef for the vector contents.
Definition: raw_ostream.h:686
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1784
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:581
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:87
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:661
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
llvm::ComputeASanStackFrameLayout
ASanStackFrameLayout ComputeASanStackFrameLayout(SmallVectorImpl< ASanStackVariableDescription > &Vars, uint64_t Granularity, uint64_t MinHeaderSize)
Definition: ASanStackFrameLayout.cpp:54
raw_ostream.h
llvm::ASanStackFrameLayout
Definition: ASanStackFrameLayout.h:44
ScopedPrinter.h