LLVM API Documentation
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