[llvm] r279982 - [asan] Separate calculation of ShadowBytes from calculating ASanStackFrameLayout

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 29 10:41:29 PDT 2016


Author: vitalybuka
Date: Mon Aug 29 12:41:29 2016
New Revision: 279982

URL: http://llvm.org/viewvc/llvm-project?rev=279982&view=rev
Log:
[asan] Separate calculation of ShadowBytes from calculating ASanStackFrameLayout

Summary: No functional changes, just refactoring to make D23947 simpler.

Reviewers: eugenis

Subscribers: llvm-commits

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

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

Modified: llvm/trunk/include/llvm/Transforms/Utils/ASanStackFrameLayout.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/ASanStackFrameLayout.h?rev=279982&r1=279981&r2=279982&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/ASanStackFrameLayout.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/ASanStackFrameLayout.h Mon Aug 29 12:41:29 2016
@@ -42,16 +42,14 @@ struct ASanStackVariableDescription {
 
 // Output data struct for ComputeASanStackFrameLayout.
 struct ASanStackFrameLayout {
+  size_t Granularity;
   // Frame description, see DescribeAddressIfStack in ASan runtime.
   SmallString<64> DescriptionString;
-  // The contents of the shadow memory for the stack frame that we need
-  // to set at function entry.
-  SmallVector<uint8_t, 64> ShadowBytes;
   size_t FrameAlignment;  // Alignment for the entire frame.
   size_t FrameSize;       // Size of the frame in bytes.
 };
 
-void ComputeASanStackFrameLayout(
+ASanStackFrameLayout ComputeASanStackFrameLayout(
     // The array of stack variables. The elements may get reordered and changed.
     SmallVectorImpl<ASanStackVariableDescription> &Vars,
     // AddressSanitizer's shadow granularity. Usually 8, may also be 16, 32, 64.
@@ -59,9 +57,21 @@ void ComputeASanStackFrameLayout(
     // The minimal size of the left-most redzone (header).
     // At least 4 pointer sizes, power of 2, and >= Granularity.
     // The resulting FrameSize should be multiple of MinHeaderSize.
-    size_t MinHeaderSize,
-    // The result is put here.
-    ASanStackFrameLayout *Layout);
+    size_t MinHeaderSize);
+
+// 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>
+GetShadowBytes(const SmallVectorImpl<ASanStackVariableDescription> &Vars,
+               const ASanStackFrameLayout &Layout);
+
+// Returns shadow bytes with marked red zones and after scope. This shadow
+// represents the state if the stack frame when all local variables are outside
+// of the own scope.
+SmallVector<uint8_t, 64> GetShadowBytesAfterScope(
+    // The array of stack variables. The elements may get reordered and changed.
+    const SmallVectorImpl<ASanStackVariableDescription> &Vars,
+    const ASanStackFrameLayout &Layout);
 
 } // llvm namespace
 

Modified: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp?rev=279982&r1=279981&r2=279982&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp Mon Aug 29 12:41:29 2016
@@ -2180,8 +2180,10 @@ void FunctionStackPoisoner::processStati
   // 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;
-  ASanStackFrameLayout L;
-  ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize, &L);
+  const ASanStackFrameLayout &L =
+      ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize);
+  const SmallVector<uint8_t, 64> &ShadowBytes =
+      GetShadowBytesAfterScope(SVD, L);
   DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n");
   uint64_t LocalStackSize = L.FrameSize;
   bool DoStackMalloc = ClUseAfterReturn && !ASan.CompileKernel &&
@@ -2278,12 +2280,12 @@ void FunctionStackPoisoner::processStati
 
   // Poison the stack redzones at the entry.
   Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
-  poisonStackFrame(L.ShadowBytes, IRB, ShadowBase, true);
+  poisonStackFrame(ShadowBytes, IRB, ShadowBase, true);
 
   auto UnpoisonStack = [&](IRBuilder<> &IRB) {
     // Do this always as poisonAlloca can be disabled with
     // detect_stack_use_after_scope=0.
-    poisonStackFrame(L.ShadowBytes, IRB, ShadowBase, false);
+    poisonStackFrame(ShadowBytes, IRB, ShadowBase, false);
     if (!StaticAllocaPoisonCallVec.empty()) {
       // If we poisoned some allocas in llvm.lifetime analysis,
       // unpoison whole stack frame now.

Modified: llvm/trunk/lib/Transforms/Utils/ASanStackFrameLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ASanStackFrameLayout.cpp?rev=279982&r1=279981&r2=279982&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/ASanStackFrameLayout.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/ASanStackFrameLayout.cpp Mon Aug 29 12:41:29 2016
@@ -47,15 +47,14 @@ static size_t VarAndRedzoneSize(size_t S
   return alignTo(Res, Alignment);
 }
 
-void
+ASanStackFrameLayout
 ComputeASanStackFrameLayout(SmallVectorImpl<ASanStackVariableDescription> &Vars,
-                            size_t Granularity, size_t MinHeaderSize,
-                            ASanStackFrameLayout *Layout) {
+                            size_t Granularity, size_t MinHeaderSize) {
   assert(Granularity >= 8 && Granularity <= 64 &&
          (Granularity & (Granularity - 1)) == 0);
   assert(MinHeaderSize >= 16 && (MinHeaderSize & (MinHeaderSize - 1)) == 0 &&
          MinHeaderSize >= Granularity);
-  size_t NumVars = Vars.size();
+  const size_t NumVars = Vars.size();
   assert(NumVars > 0);
   for (size_t i = 0; i < NumVars; i++)
     Vars[i].Alignment = std::max(Vars[i].Alignment, kMinAlignment);
@@ -64,13 +63,13 @@ ComputeASanStackFrameLayout(SmallVectorI
   SmallString<2048> StackDescriptionStorage;
   raw_svector_ostream StackDescription(StackDescriptionStorage);
   StackDescription << NumVars;
-  Layout->FrameAlignment = std::max(Granularity, Vars[0].Alignment);
-  SmallVector<uint8_t, 64> &SB(Layout->ShadowBytes);
-  SB.clear();
+
+  ASanStackFrameLayout Layout;
+  Layout.Granularity = Granularity;
+  Layout.FrameAlignment = std::max(Granularity, Vars[0].Alignment);
   size_t Offset = std::max(std::max(MinHeaderSize, Granularity),
      Vars[0].Alignment);
   assert((Offset % Granularity) == 0);
-  SB.insert(SB.end(), Offset / Granularity, kAsanStackLeftRedzoneMagic);
   for (size_t i = 0; i < NumVars; i++) {
     bool IsLast = i == NumVars - 1;
     size_t Alignment = std::max(Granularity, Vars[i].Alignment);
@@ -78,7 +77,7 @@ ComputeASanStackFrameLayout(SmallVectorI
     size_t Size = Vars[i].Size;
     const char *Name = Vars[i].Name;
     assert((Alignment & (Alignment - 1)) == 0);
-    assert(Layout->FrameAlignment >= Alignment);
+    assert(Layout.FrameAlignment >= Alignment);
     assert((Offset % Alignment) == 0);
     assert(Size > 0);
     assert(Vars[i].LifetimeSize <= Size);
@@ -87,31 +86,54 @@ ComputeASanStackFrameLayout(SmallVectorI
     size_t NextAlignment = IsLast ? Granularity
                    : std::max(Granularity, Vars[i + 1].Alignment);
     size_t SizeWithRedzone = VarAndRedzoneSize(Vars[i].Size, NextAlignment);
-    size_t LifetimeShadowSize =
-        (Vars[i].LifetimeSize + Granularity - 1) / Granularity;
-    SB.insert(SB.end(), LifetimeShadowSize, kAsanStackUseAfterScopeMagic);
-    if (Size / Granularity >= LifetimeShadowSize) {
-      SB.insert(SB.end(), Size / Granularity - LifetimeShadowSize, 0);
-      if (Size % Granularity)
-        SB.insert(SB.end(), Size % Granularity);
-    }
-    SB.insert(SB.end(), (SizeWithRedzone - Size) / Granularity,
-        IsLast ? kAsanStackRightRedzoneMagic
-        : kAsanStackMidRedzoneMagic);
     Vars[i].Offset = Offset;
     Offset += SizeWithRedzone;
-    assert(Offset == SB.size() * Granularity);
   }
   if (Offset % MinHeaderSize) {
-    size_t ExtraRedzone = MinHeaderSize - (Offset % MinHeaderSize);
-    SB.insert(SB.end(), ExtraRedzone / Granularity,
-              kAsanStackRightRedzoneMagic);
-    Offset += ExtraRedzone;
+    Offset += MinHeaderSize - (Offset % MinHeaderSize);
+  }
+  Layout.DescriptionString = StackDescription.str();
+  Layout.FrameSize = Offset;
+  assert((Layout.FrameSize % MinHeaderSize) == 0);
+
+  return Layout;
+}
+
+SmallVector<uint8_t, 64>
+GetShadowBytes(const SmallVectorImpl<ASanStackVariableDescription> &Vars,
+               const ASanStackFrameLayout &Layout) {
+  SmallVector<uint8_t, 64> SB;
+  SB.clear();
+  const size_t NumVars = Vars.size();
+  assert(NumVars > 0);
+  const size_t Granularity = Layout.Granularity;
+  SB.resize(Vars[0].Offset / Granularity, kAsanStackLeftRedzoneMagic);
+  for (const auto &Var : Vars) {
+    SB.resize(Var.Offset / Granularity, kAsanStackMidRedzoneMagic);
+
+    SB.resize(SB.size() + Var.Size / Granularity, 0);
+    if (Var.Size % Granularity)
+      SB.push_back(Var.Size % Granularity);
   }
-  Layout->DescriptionString = StackDescription.str();
-  Layout->FrameSize = Offset;
-  assert((Layout->FrameSize % MinHeaderSize) == 0);
-  assert(Layout->FrameSize / Granularity == Layout->ShadowBytes.size());
+  SB.resize(Layout.FrameSize / Granularity, kAsanStackRightRedzoneMagic);
+  return SB;
+}
+
+SmallVector<uint8_t, 64> GetShadowBytesAfterScope(
+    const SmallVectorImpl<ASanStackVariableDescription> &Vars,
+    const ASanStackFrameLayout &Layout) {
+  SmallVector<uint8_t, 64> SB = GetShadowBytes(Vars, Layout);
+  const size_t Granularity = Layout.Granularity;
+
+  for (const auto &Var : Vars) {
+    const size_t LifetimeShadowSize =
+        (Var.LifetimeSize + Granularity - 1) / Granularity;
+    const size_t Offset = Var.Offset / Granularity;
+    std::fill(SB.begin() + Offset, SB.begin() + Offset + LifetimeShadowSize,
+              kAsanStackUseAfterScopeMagic);
+  }
+
+  return SB;
 }
 
 } // llvm namespace

Modified: llvm/trunk/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp?rev=279982&r1=279981&r2=279982&view=diff
==============================================================================
--- llvm/trunk/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp (original)
+++ llvm/trunk/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp Mon Aug 29 12:41:29 2016
@@ -30,21 +30,20 @@ ShadowBytesToString(ArrayRef<uint8_t> Sh
   return os.str();
 }
 
-static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars,
-                       size_t Granularity, size_t MinHeaderSize,
-                       const std::string &ExpectedDescr,
-                       const std::string &ExpectedShadow) {
-  ASanStackFrameLayout L;
-  ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L);
-  EXPECT_EQ(ExpectedDescr, L.DescriptionString);
-  EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes));
-}
+// Use macro to preserve line information in EXPECT_EQ output.
+#define TEST_LAYOUT(V, Granularity, MinHeaderSize, ExpectedDescr,              \
+                    ExpectedShadow, ExpectedShadowAfterScope)                  \
+  {                                                                            \
+    SmallVector<ASanStackVariableDescription, 10> Vars = V;                    \
+    ASanStackFrameLayout L =                                                   \
+        ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize);         \
+    EXPECT_EQ(ExpectedDescr, L.DescriptionString);                             \
+    EXPECT_EQ(ExpectedShadow, ShadowBytesToString(GetShadowBytes(Vars, L)));   \
+    EXPECT_EQ(ExpectedShadowAfterScope,                                        \
+              ShadowBytesToString(GetShadowBytesAfterScope(Vars, L)));         \
+  }
 
 TEST(ASanStackFrameLayout, Test) {
-#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a)
-#define VEC(a)                                                                 \
-  SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0]))
-
 #define VAR(name, size, lifetime, alignment)                                   \
   ASanStackVariableDescription name##size##_##alignment = {                    \
     #name #size "_" #alignment,                                                \
@@ -64,41 +63,44 @@ TEST(ASanStackFrameLayout, Test) {
   VAR(a, 7, 0, 1);
   VAR(a, 8, 8, 1);
   VAR(a, 9, 0, 1);
-  VAR(a, 16, 0, 1);
+  VAR(a, 16, 16, 1);
   VAR(a, 41, 9, 1);
   VAR(a, 105, 103, 1);
 
-  TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R");
-  TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1");
-  TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR");
-  TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR");
-
-  TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR");
-  TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR");
-  TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR");
-  TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR");
-  TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR");
-  TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLLSRRR");
-  TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR");
-  TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR");
-  TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256",
-             "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
-  TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLLSS0001RRRRRR");
-  TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1",
-             "LLLLSSSSSSSSSSSSS1RRRRRR");
+  TEST_LAYOUT({a1_1}, 8, 16, "1 16 1 4 a1_1", "LL1R", "LL1R");
+  TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1", "L1");
+  TEST_LAYOUT({p1_32}, 8, 32, "1 32 1 5 p1_32", "LLLL1RRR", "LLLL1RRR");
+  TEST_LAYOUT({p1_32}, 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR",
+              "LLLLLLLL1RRRRRRR");
+
+  TEST_LAYOUT({a1_1}, 8, 32, "1 32 1 4 a1_1", "LLLL1RRR", "LLLL1RRR");
+  TEST_LAYOUT({a2_1}, 8, 32, "1 32 2 4 a2_1", "LLLL2RRR", "LLLL2RRR");
+  TEST_LAYOUT({a3_1}, 8, 32, "1 32 3 4 a3_1", "LLLL3RRR", "LLLL3RRR");
+  TEST_LAYOUT({a4_1}, 8, 32, "1 32 4 4 a4_1", "LLLL4RRR", "LLLL4RRR");
+  TEST_LAYOUT({a7_1}, 8, 32, "1 32 7 4 a7_1", "LLLL7RRR", "LLLL7RRR");
+  TEST_LAYOUT({a8_1}, 8, 32, "1 32 8 4 a8_1", "LLLL0RRR", "LLLLSRRR");
+  TEST_LAYOUT({a9_1}, 8, 32, "1 32 9 4 a9_1", "LLLL01RR", "LLLL01RR");
+  TEST_LAYOUT({a16_1}, 8, 32, "1 32 16 5 a16_1", "LLLL00RR", "LLLLSSRR");
+  TEST_LAYOUT({p1_256}, 8, 32, "1 256 1 6 p1_256",
+              "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR",
+              "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
+  TEST_LAYOUT({a41_1}, 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR",
+              "LLLLSS0001RRRRRR");
+  TEST_LAYOUT({a105_1}, 8, 32, "1 32 105 6 a105_1", "LLLL00000000000001RRRRRR",
+              "LLLLSSSSSSSSSSSSS1RRRRRR");
 
   {
-    ASanStackVariableDescription t[] = {a1_1, p1_256};
-    TestLayout(VEC(t), 8, 32, "2 256 1 6 p1_256 272 1 4 a1_1",
-               "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R");
+    SmallVector<ASanStackVariableDescription, 10> t = {a1_1, p1_256};
+    TEST_LAYOUT(t, 8, 32, "2 256 1 6 p1_256 272 1 4 a1_1",
+                "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R",
+                "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R");
   }
 
   {
-    ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1};
-    TestLayout(VEC(t), 8, 32, "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1",
-               "LLLL1M00MMSS0001RRRR");
+    SmallVector<ASanStackVariableDescription, 10> t = {a1_1, a16_1, a41_1};
+    TEST_LAYOUT(t, 8, 32, "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1",
+                "LLLL1M00MM000001RRRR", "LLLL1MSSMMSS0001RRRR");
   }
-#undef VEC1
-#undef VEC
 #undef VAR
+#undef TEST_LAYOUT
 }




More information about the llvm-commits mailing list