]> granicus.if.org Git - llvm/commitdiff
[asan] Simplify calculation of stack frame layout extraction calculation of stack...
authorVitaly Buka <vitalybuka@google.com>
Tue, 18 Oct 2016 23:29:52 +0000 (23:29 +0000)
committerVitaly Buka <vitalybuka@google.com>
Tue, 18 Oct 2016 23:29:52 +0000 (23:29 +0000)
Reviewers: eugenis

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D25754

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284547 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/ASanStackFrameLayout.h
lib/Transforms/Instrumentation/AddressSanitizer.cpp
lib/Transforms/Utils/ASanStackFrameLayout.cpp
unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp

index 8c9f48b2c4fe500a547a2277b3240298d99f7a69..eaad06a108190d58e4c44378cba365c80fe9072d 100644 (file)
@@ -43,9 +43,7 @@ struct ASanStackVariableDescription {
 
 // Output data struct for ComputeASanStackFrameLayout.
 struct ASanStackFrameLayout {
-  size_t Granularity;
-  // Frame description, see DescribeAddressIfStack in ASan runtime.
-  SmallString<64> DescriptionString;
+  size_t Granularity;     // Shadow granularity.
   size_t FrameAlignment;  // Alignment for the entire frame.
   size_t FrameSize;       // Size of the frame in bytes.
 };
@@ -60,6 +58,10 @@ ASanStackFrameLayout ComputeASanStackFrameLayout(
     // The resulting FrameSize should be multiple of MinHeaderSize.
     size_t MinHeaderSize);
 
+// Compute frame description, see DescribeAddressIfStack in ASan runtime.
+SmallString<64> ComputeASanStackFrameDescription(
+    const SmallVectorImpl<ASanStackVariableDescription> &Vars);
+
 // Returns shadow bytes with marked red zones. This shadow represents the state
 // if the stack frame when all local variables are inside of the own scope.
 SmallVector<uint8_t, 64>
index 507776a4cb834377f4fc029459ef9c06411db509..586c399dbca567abfb4168223dfe071a23467e98 100644 (file)
@@ -2246,26 +2246,6 @@ void FunctionStackPoisoner::processStaticAllocas() {
   // If we have a call to llvm.localescape, keep it in the entry block.
   if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore);
 
-  // Find static allocas with lifetime analysis.
-  DenseMap<const AllocaInst *,
-           std::pair<const ASanStackVariableDescription *, unsigned>>
-      AllocaToSVDMap;
-  for (const auto &APC : StaticAllocaPoisonCallVec) {
-    assert(APC.InsBefore);
-    assert(APC.AI);
-    assert(ASan.isInterestingAlloca(*APC.AI));
-    assert(APC.AI->isStaticAlloca());
-
-    auto &Pair = AllocaToSVDMap[APC.AI];
-    if (const DILocation *FnLoc = EntryDebugLocation.get()) {
-      if (const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
-        if (LifetimeLoc->getFile() == FnLoc->getFile())
-          if (unsigned Line = LifetimeLoc->getLine())
-            Pair.second = std::min(Pair.second ? Pair.second : Line, Line);
-      }
-    }
-  }
-
   SmallVector<ASanStackVariableDescription, 16> SVD;
   SVD.reserve(AllocaVec.size());
   for (AllocaInst *AI : AllocaVec) {
@@ -2276,20 +2256,40 @@ void FunctionStackPoisoner::processStaticAllocas() {
                                       AI,
                                       0,
                                       0};
-    auto It = AllocaToSVDMap.find(AI);
-    if (It != AllocaToSVDMap.end()) {
-      D.LifetimeSize = D.Size;
-      D.Line = It->second.second;
-    }
     SVD.push_back(D);
   }
+
   // Minimal header size (left redzone) is 4 pointers,
   // i.e. 32 bytes on 64-bit platforms and 16 bytes in 32-bit platforms.
   size_t MinHeaderSize = ASan.LongSize / 2;
   const ASanStackFrameLayout &L =
       ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize);
 
-  DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n");
+  // Build AllocaToSVDMap for ASanStackVariableDescription lookup.
+  DenseMap<const AllocaInst *, ASanStackVariableDescription *> AllocaToSVDMap;
+  for (auto &Desc : SVD)
+    AllocaToSVDMap[Desc.AI] = &Desc;
+
+  // Update SVD with information from lifetime intrinsics.
+  for (const auto &APC : StaticAllocaPoisonCallVec) {
+    assert(APC.InsBefore);
+    assert(APC.AI);
+    assert(ASan.isInterestingAlloca(*APC.AI));
+    assert(APC.AI->isStaticAlloca());
+
+    ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI];
+    Desc.LifetimeSize = Desc.Size;
+    if (const DILocation *FnLoc = EntryDebugLocation.get()) {
+      if (const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
+        if (LifetimeLoc->getFile() == FnLoc->getFile())
+          if (unsigned Line = LifetimeLoc->getLine())
+            Desc.Line = std::min(Desc.Line ? Desc.Line : Line, Line);
+      }
+    }
+  }
+
+  auto DescriptionString = ComputeASanStackFrameDescription(SVD);
+  DEBUG(dbgs() << DescriptionString << " --- " << L.FrameSize << "\n");
   uint64_t LocalStackSize = L.FrameSize;
   bool DoStackMalloc = ClUseAfterReturn && !ASan.CompileKernel &&
                        LocalStackSize <= kMaxStackMallocSize;
@@ -2372,7 +2372,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
                     ConstantInt::get(IntptrTy, ASan.LongSize / 8)),
       IntptrPtrTy);
   GlobalVariable *StackDescriptionGlobal =
-      createPrivateGlobalForString(*F.getParent(), L.DescriptionString,
+      createPrivateGlobalForString(*F.getParent(), DescriptionString,
                                    /*AllowMerging*/ true);
   Value *Description = IRB.CreatePointerCast(StackDescriptionGlobal, IntptrTy);
   IRB.CreateStore(Description, BasePlus1);
@@ -2392,21 +2392,11 @@ void FunctionStackPoisoner::processStaticAllocas() {
   copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
 
   if (!StaticAllocaPoisonCallVec.empty()) {
-    // Complete AllocaToSVDMap
-    for (const auto &Desc : SVD) {
-      auto It = AllocaToSVDMap.find(Desc.AI);
-      if (It != AllocaToSVDMap.end()) {
-        It->second.first = &Desc;
-      }
-    }
-
     const auto &ShadowInScope = GetShadowBytes(SVD, L);
 
     // Poison static allocas near lifetime intrinsics.
     for (const auto &APC : StaticAllocaPoisonCallVec) {
-      // Must be already set.
-      assert(AllocaToSVDMap[APC.AI].first);
-      const auto &Desc = *AllocaToSVDMap[APC.AI].first;
+      const ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI];
       assert(Desc.Offset % L.Granularity == 0);
       size_t Begin = Desc.Offset / L.Granularity;
       size_t End = Begin + (APC.Size + L.Granularity - 1) / L.Granularity;
index dc226b2e2cc161a10b6b24e1a78239c79e2d0ea7..86d7ce87745cad1c159977901622cd58a1570037 100644 (file)
@@ -61,9 +61,6 @@ ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars,
     Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment);
 
   std::stable_sort(Vars.begin(), Vars.end(), CompareVars);
-  SmallString<2048> StackDescriptionStorage;
-  raw_svector_ostream StackDescription(StackDescriptionStorage);
-  StackDescription << NumVars;
 
   ASanStackFrameLayout Layout;
   Layout.Granularity = Granularity;
@@ -76,34 +73,42 @@ ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars,
     size_t Alignment = std::max(Granularity, Vars[i].Alignment);
     (void)Alignment;  // Used only in asserts.
     size_t Size = Vars[i].Size;
-    std::string Name = Vars[i].Name;
     assert((Alignment & (Alignment - 1)) == 0);
     assert(Layout.FrameAlignment >= Alignment);
     assert((Offset % Alignment) == 0);
     assert(Size > 0);
-    assert(Vars[i].LifetimeSize <= Size);
-    if (Vars[i].Line) {
-      Name += ":";
-      Name += std::to_string(Vars[i].Line);
-    }
-    StackDescription << " " << Offset << " " << Size << " " << Name.size()
-                     << " " << Name;
     size_t NextAlignment = IsLast ? Granularity
                    : std::max(Granularity, Vars[i + 1].Alignment);
-    size_t SizeWithRedzone = VarAndRedzoneSize(Vars[i].Size, NextAlignment);
+    size_t SizeWithRedzone = VarAndRedzoneSize(Size, NextAlignment);
     Vars[i].Offset = Offset;
     Offset += SizeWithRedzone;
   }
   if (Offset % MinHeaderSize) {
     Offset += MinHeaderSize - (Offset % MinHeaderSize);
   }
-  Layout.DescriptionString = StackDescription.str();
   Layout.FrameSize = Offset;
   assert((Layout.FrameSize % MinHeaderSize) == 0);
-
   return Layout;
 }
 
+SmallString<64> ComputeASanStackFrameDescription(
+    const SmallVectorImpl<ASanStackVariableDescription> &Vars) {
+  SmallString<2048> StackDescriptionStorage;
+  raw_svector_ostream StackDescription(StackDescriptionStorage);
+  StackDescription << Vars.size();
+
+  for (const auto &Var : Vars) {
+    std::string Name = Var.Name;
+    if (Var.Line) {
+      Name += ":";
+      Name += std::to_string(Var.Line);
+    }
+    StackDescription << " " << Var.Offset << " " << Var.Size << " "
+                     << Name.size() << " " << Name;
+  }
+  return StackDescription.str();
+}
+
 SmallVector<uint8_t, 64>
 GetShadowBytes(const SmallVectorImpl<ASanStackVariableDescription> &Vars,
                const ASanStackFrameLayout &Layout) {
@@ -130,6 +135,7 @@ SmallVector<uint8_t, 64> GetShadowBytesAfterScope(
   const size_t Granularity = Layout.Granularity;
 
   for (const auto &Var : Vars) {
+    assert(Var.LifetimeSize <= Var.Size);
     const size_t LifetimeShadowSize =
         (Var.LifetimeSize + Granularity - 1) / Granularity;
     const size_t Offset = Var.Offset / Granularity;
index a241482c18e00b42a686f798ddb4e16263a610c6..2337ec04776a184add21097e0352c53d8a311cb3 100644 (file)
@@ -37,7 +37,8 @@ ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) {
     SmallVector<ASanStackVariableDescription, 10> Vars = V;                    \
     ASanStackFrameLayout L =                                                   \
         ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize);         \
-    EXPECT_STREQ(ExpectedDescr, L.DescriptionString.c_str());                  \
+    EXPECT_STREQ(ExpectedDescr,                                                \
+                 ComputeASanStackFrameDescription(Vars).c_str());              \
     EXPECT_EQ(ExpectedShadow, ShadowBytesToString(GetShadowBytes(Vars, L)));   \
     EXPECT_EQ(ExpectedShadowAfterScope,                                        \
               ShadowBytesToString(GetShadowBytesAfterScope(Vars, L)));         \