[asan] Append line number to variable name if line is available and in the same file...
authorVitaly Buka <vitalybuka@google.com>
Tue, 18 Oct 2016 23:29:41 +0000 (23:29 +0000)
committerVitaly Buka <vitalybuka@google.com>
Tue, 18 Oct 2016 23:29:41 +0000 (23:29 +0000)
PR30498

Reviewers: eugenis

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

llvm-svn: 284546

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

index bf3fe11..8c9f48b 100644 (file)
@@ -38,6 +38,7 @@ struct ASanStackVariableDescription {
   AllocaInst *AI;      // The actual AllocaInst.
   size_t Offset;       // Offset from the beginning of the frame;
                        // set by ComputeASanStackFrameLayout.
+  unsigned Line;       // Line number.
 };
 
 // Output data struct for ComputeASanStackFrameLayout.
index e158302..507776a 100644 (file)
@@ -2247,7 +2247,8 @@ void FunctionStackPoisoner::processStaticAllocas() {
   if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore);
 
   // Find static allocas with lifetime analysis.
-  DenseMap<const AllocaInst *, const ASanStackVariableDescription *>
+  DenseMap<const AllocaInst *,
+           std::pair<const ASanStackVariableDescription *, unsigned>>
       AllocaToSVDMap;
   for (const auto &APC : StaticAllocaPoisonCallVec) {
     assert(APC.InsBefore);
@@ -2255,22 +2256,31 @@ void FunctionStackPoisoner::processStaticAllocas() {
     assert(ASan.isInterestingAlloca(*APC.AI));
     assert(APC.AI->isStaticAlloca());
 
-    AllocaToSVDMap[APC.AI] = nullptr;
+    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) {
-    size_t UseAfterScopePoisonSize =
-        AllocaToSVDMap.find(AI) != AllocaToSVDMap.end()
-            ? ASan.getAllocaSizeInBytes(*AI)
-            : 0;
     ASanStackVariableDescription D = {AI->getName().data(),
                                       ASan.getAllocaSizeInBytes(*AI),
-                                      UseAfterScopePoisonSize,
+                                      0,
                                       AI->getAlignment(),
                                       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,
@@ -2386,7 +2396,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
     for (const auto &Desc : SVD) {
       auto It = AllocaToSVDMap.find(Desc.AI);
       if (It != AllocaToSVDMap.end()) {
-        It->second = &Desc;
+        It->second.first = &Desc;
       }
     }
 
@@ -2395,8 +2405,8 @@ void FunctionStackPoisoner::processStaticAllocas() {
     // Poison static allocas near lifetime intrinsics.
     for (const auto &APC : StaticAllocaPoisonCallVec) {
       // Must be already set.
-      assert(AllocaToSVDMap[APC.AI]);
-      const auto &Desc = *AllocaToSVDMap[APC.AI];
+      assert(AllocaToSVDMap[APC.AI].first);
+      const auto &Desc = *AllocaToSVDMap[APC.AI].first;
       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 bdd55a2..dc226b2 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -75,13 +76,17 @@ 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;
-    const char *Name = Vars[i].Name;
+    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);
-    StackDescription << " " << Offset << " " << Size << " " << strlen(Name)
+    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);
index 6575dd6..96706f7 100644 (file)
@@ -1,18 +1,21 @@
 ; Test the ASan's stack layout.
 ; More tests in tests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
-; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=0 -S \
-; RUN:     | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STATIC
-; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=1 -S \
-; RUN:     | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DYNAMIC
+; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S \
+; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-STATIC
+; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S \
+; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 declare void @Use(i8*)
+declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
+declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
 
-; CHECK: private unnamed_addr constant{{.*}}3 32 10 3 XXX 64 20 3 YYY 128 30 3 ZZZ
-; CHECK: private unnamed_addr constant{{.*}}3 32 5 3 AAA 64 55 3 BBB 160 555 3 CCC
-; CHECK: private unnamed_addr constant{{.*}}3 256 128 3 CCC 448 128 3 BBB 608 128 3 AAA
+; CHECK: private unnamed_addr constant{{.*}}3 32 10 3 XXX 64 20 3 YYY 128 30 3 ZZZ\0
+; CHECK: private unnamed_addr constant{{.*}}3 32 5 3 AAA 64 55 3 BBB 160 555 3 CCC\0
+; CHECK: private unnamed_addr constant{{.*}}3 256 128 3 CCC 448 128 3 BBB 608 128 3 AAA\0
+; CHECK: private unnamed_addr constant{{.*}}2 32 4 3 AAA 48 4 5 BBB:7\0
 
 define void @Func1() sanitize_address {
 entry:
@@ -77,3 +80,36 @@ entry:
   store volatile i8 0, i8* %arr3.ptr
   ret void
 }
+
+; Check that line numbers are attached to variable names if variable
+; in the same file as a function.
+define void @Func5() sanitize_address #0 !dbg !11 {
+  %AAA = alloca i32, align 4  ; File is not the same as !11
+  %BBB = alloca i32, align 4  ; File is the same as !11
+  %BBB.ptr = bitcast i32* %BBB to i8*
+  call void @llvm.lifetime.start(i64 4, i8* nonnull %BBB.ptr), !dbg !12
+  store volatile i32 5, i32* %BBB, align 4
+  %AAA.ptr = bitcast i32* %AAA to i8*
+  call void @llvm.lifetime.start(i64 4, i8* nonnull %AAA.ptr), !dbg !14
+  store volatile i32 3, i32* %AAA, align 4
+  call void @llvm.lifetime.end(i64 4, i8* nonnull %AAA.ptr), !dbg !17
+  call void @llvm.lifetime.end(i64 4, i8* nonnull %BBB.ptr), !dbg !18
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
+!1 = !DIFile(filename: "../file1.c", directory: "/")
+!11 = distinct !DISubprogram(name: "Func5", scope: !1, file: !1, line: 6, unit: !0)
+!12 = !DILocation(line: 7, column: 3, scope: !11)
+!18 = !DILocation(line: 10, column: 1, scope: !11)
+
+!21 = !DIFile(filename: "../file2.c", directory: "/")
+!6 = distinct !DISubprogram(name: "Func4", scope: !1, file: !21, line: 2, unit: !0)
+!15 = distinct !DILocation(line: 8, column: 3, scope: !11)
+!14 = !DILocation(line: 3, column: 3, scope: !6, inlinedAt: !15)
+!17 = !DILocation(line: 4, column: 1, scope: !6, inlinedAt: !15)
index 4a8e15d..a241482 100644 (file)
@@ -37,40 +37,41 @@ ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) {
     SmallVector<ASanStackVariableDescription, 10> Vars = V;                    \
     ASanStackFrameLayout L =                                                   \
         ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize);         \
-    EXPECT_EQ(ExpectedDescr, L.DescriptionString);                             \
+    EXPECT_STREQ(ExpectedDescr, L.DescriptionString.c_str());                  \
     EXPECT_EQ(ExpectedShadow, ShadowBytesToString(GetShadowBytes(Vars, L)));   \
     EXPECT_EQ(ExpectedShadowAfterScope,                                        \
               ShadowBytesToString(GetShadowBytesAfterScope(Vars, L)));         \
   }
 
 TEST(ASanStackFrameLayout, Test) {
-#define VAR(name, size, lifetime, alignment)                                   \
+#define VAR(name, size, lifetime, alignment, line)                             \
   ASanStackVariableDescription name##size##_##alignment = {                    \
     #name #size "_" #alignment,                                                \
     size,                                                                      \
     lifetime,                                                                  \
     alignment,                                                                 \
     0,                                                                         \
-    0                                                                          \
+    0,                                                                         \
+    line,                                                                      \
   }
 
-  VAR(a, 1, 0, 1);
-  VAR(p, 1, 0, 32);
-  VAR(p, 1, 0, 256);
-  VAR(a, 2, 0, 1);
-  VAR(a, 3, 0, 1);
-  VAR(a, 4, 0, 1);
-  VAR(a, 7, 0, 1);
-  VAR(a, 8, 8, 1);
-  VAR(a, 9, 0, 1);
-  VAR(a, 16, 16, 1);
-  VAR(a, 41, 9, 1);
-  VAR(a, 105, 103, 1);
+  VAR(a, 1, 0, 1, 0);
+  VAR(p, 1, 0, 32, 15);
+  VAR(p, 1, 0, 256, 2700);
+  VAR(a, 2, 0, 1, 0);
+  VAR(a, 3, 0, 1, 0);
+  VAR(a, 4, 0, 1, 0);
+  VAR(a, 7, 0, 1, 0);
+  VAR(a, 8, 8, 1, 0);
+  VAR(a, 9, 0, 1, 0);
+  VAR(a, 16, 16, 1, 0);
+  VAR(a, 41, 9, 1, 7);
+  VAR(a, 105, 103, 1, 0);
 
   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",
+  TEST_LAYOUT({p1_32}, 8, 32, "1 32 1 8 p1_32:15", "LLLL1RRR", "LLLL1RRR");
+  TEST_LAYOUT({p1_32}, 8, 64, "1 64 1 8 p1_32:15", "LLLLLLLL1RRRRRRR",
               "LLLLLLLL1RRRRRRR");
 
   TEST_LAYOUT({a1_1}, 8, 32, "1 32 1 4 a1_1", "LLLL1RRR", "LLLL1RRR");
@@ -81,24 +82,24 @@ TEST(ASanStackFrameLayout, Test) {
   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",
+  TEST_LAYOUT({p1_256}, 8, 32, "1 256 1 11 p1_256:2700",
               "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR",
               "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
-  TEST_LAYOUT({a41_1}, 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR",
+  TEST_LAYOUT({a41_1}, 8, 32, "1 32 41 7 a41_1:7", "LLLL000001RRRRRR",
               "LLLLSS0001RRRRRR");
   TEST_LAYOUT({a105_1}, 8, 32, "1 32 105 6 a105_1", "LLLL00000000000001RRRRRR",
               "LLLLSSSSSSSSSSSSS1RRRRRR");
 
   {
     SmallVector<ASanStackVariableDescription, 10> t = {a1_1, p1_256};
-    TEST_LAYOUT(t, 8, 32, "2 256 1 6 p1_256 272 1 4 a1_1",
+    TEST_LAYOUT(t, 8, 32, "2 256 1 11 p1_256:2700 272 1 4 a1_1",
                 "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R",
                 "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R");
   }
 
   {
     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",
+    TEST_LAYOUT(t, 8, 32, "3 32 1 4 a1_1 48 16 5 a16_1 80 41 7 a41_1:7",
                 "LLLL1M00MM000001RRRR", "LLLL1MSSMMSS0001RRRR");
   }
 #undef VAR