LLVM API Documentation

ASanStackFrameLayout.cpp
Go to the documentation of this file.
00001 //===-- ASanStackFrameLayout.cpp - helper for AddressSanitizer ------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Definition of ComputeASanStackFrameLayout (see ASanStackFrameLayout.h).
00011 //
00012 //===----------------------------------------------------------------------===//
00013 #include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
00014 #include "llvm/ADT/SmallString.h"
00015 #include "llvm/Support/raw_ostream.h"
00016 #include <algorithm>
00017 
00018 namespace llvm {
00019 
00020 // We sort the stack variables by alignment (largest first) to minimize
00021 // unnecessary large gaps due to alignment.
00022 // It is tempting to also sort variables by size so that larger variables
00023 // have larger redzones at both ends. But reordering will make report analysis
00024 // harder, especially when temporary unnamed variables are present.
00025 // So, until we can provide more information (type, line number, etc)
00026 // for the stack variables we avoid reordering them too much.
00027 static inline bool CompareVars(const ASanStackVariableDescription &a,
00028                                const ASanStackVariableDescription &b) {
00029   return a.Alignment > b.Alignment;
00030 }
00031 
00032 // We also force minimal alignment for all vars to kMinAlignment so that vars
00033 // with e.g. alignment 1 and alignment 16 do not get reordered by CompareVars.
00034 static const size_t kMinAlignment = 16;
00035 
00036 static size_t RoundUpTo(size_t X, size_t RoundTo) {
00037   assert((RoundTo & (RoundTo - 1)) == 0);
00038   return (X + RoundTo - 1) & ~(RoundTo - 1);
00039 }
00040 
00041 // The larger the variable Size the larger is the redzone.
00042 // The resulting frame size is a multiple of Alignment.
00043 static size_t VarAndRedzoneSize(size_t Size, size_t Alignment) {
00044   size_t Res = 0;
00045   if (Size <= 4)  Res = 16;
00046   else if (Size <= 16) Res = 32;
00047   else if (Size <= 128) Res = Size + 32;
00048   else if (Size <= 512) Res = Size + 64;
00049   else if (Size <= 4096) Res = Size + 128;
00050   else                   Res = Size + 256;
00051   return RoundUpTo(Res, Alignment);
00052 }
00053 
00054 void
00055 ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars,
00056                             size_t Granularity, size_t MinHeaderSize,
00057                             ASanStackFrameLayout *Layout) {
00058   assert(Granularity >= 8 && Granularity <= 64 &&
00059          (Granularity & (Granularity - 1)) == 0);
00060   assert(MinHeaderSize >= 16 && (MinHeaderSize & (MinHeaderSize - 1)) == 0 &&
00061          MinHeaderSize >= Granularity);
00062   size_t NumVars = Vars.size();
00063   assert(NumVars > 0);
00064   for (size_t i = 0; i < NumVars; i++)
00065     Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment);
00066 
00067   std::stable_sort(Vars.begin(), Vars.end(), CompareVars);
00068   SmallString<2048> StackDescriptionStorage;
00069   raw_svector_ostream StackDescription(StackDescriptionStorage);
00070   StackDescription << NumVars;
00071   Layout->FrameAlignment = std::max(Granularity, Vars[0].Alignment);
00072   SmallVector<uint8_t, 64> &SB(Layout->ShadowBytes);
00073   SB.clear();
00074   size_t Offset = std::max(std::max(MinHeaderSize, Granularity),
00075      Vars[0].Alignment);
00076   assert((Offset % Granularity) == 0);
00077   SB.insert(SB.end(), Offset / Granularity, kAsanStackLeftRedzoneMagic);
00078   for (size_t i = 0; i < NumVars; i++) {
00079     bool IsLast = i == NumVars - 1;
00080     size_t Alignment = std::max(Granularity, Vars[i].Alignment);
00081     (void)Alignment;  // Used only in asserts.
00082     size_t Size = Vars[i].Size;
00083     const char *Name = Vars[i].Name;
00084     assert((Alignment & (Alignment - 1)) == 0);
00085     assert(Layout->FrameAlignment >= Alignment);
00086     assert((Offset % Alignment) == 0);
00087     assert(Size > 0);
00088     StackDescription << " " << Offset << " " << Size << " " << strlen(Name)
00089                      << " " << Name;
00090     size_t NextAlignment = IsLast ? Granularity
00091                    : std::max(Granularity, Vars[i + 1].Alignment);
00092     size_t SizeWithRedzone = VarAndRedzoneSize(Vars[i].Size, NextAlignment);
00093     SB.insert(SB.end(), Size / Granularity, 0);
00094     if (Size % Granularity)
00095       SB.insert(SB.end(), Size % Granularity);
00096     SB.insert(SB.end(), (SizeWithRedzone - Size) / Granularity,
00097         IsLast ? kAsanStackRightRedzoneMagic
00098         : kAsanStackMidRedzoneMagic);
00099     Vars[i].Offset = Offset;
00100     Offset += SizeWithRedzone;
00101   }
00102   if (Offset % MinHeaderSize) {
00103     size_t ExtraRedzone = MinHeaderSize - (Offset % MinHeaderSize);
00104     SB.insert(SB.end(), ExtraRedzone / Granularity,
00105               kAsanStackRightRedzoneMagic);
00106     Offset += ExtraRedzone;
00107   }
00108   Layout->DescriptionString = StackDescription.str();
00109   Layout->FrameSize = Offset;
00110   assert((Layout->FrameSize % MinHeaderSize) == 0);
00111   assert(Layout->FrameSize / Granularity == Layout->ShadowBytes.size());
00112 }
00113 
00114 } // llvm namespace