summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2017-12-11 20:43:21 +0000
committerAdrian Prantl <aprantl@apple.com>2017-12-11 20:43:21 +0000
commit3c6c14d14b40adfb581940859ede1ac7d8ceae7a (patch)
treef8888ef8915fdf92cdfd287f3e1f07c21dfc17fa
parent3b49dc548fd25b4b8aa3d4a90bd05f5d596abeb1 (diff)
downloadbcm5719-llvm-3c6c14d14b40adfb581940859ede1ac7d8ceae7a.tar.gz
bcm5719-llvm-3c6c14d14b40adfb581940859ede1ac7d8ceae7a.zip
ASAN: Provide reliable debug info for local variables at -O0.
The function stack poisioner conditionally stores local variables either in an alloca or in malloc'ated memory, which has the unfortunate side-effect, that the actual address of the variable is only materialized when the variable is accessed, which means that those variables are mostly invisible to the debugger even when compiling without optimizations. This patch stores the address of the local stack base into an alloca, which can be referred to by the debug info and is available throughout the function. This adds one extra pointer-sized alloca to each stack frame (but mem2reg can optimize it away again when optimizations are enabled, yielding roughly the same debug info quality as before in optimized code). rdar://problem/30433661 Differential Revision: https://reviews.llvm.org/D41034 llvm-svn: 320415
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp14
-rw-r--r--llvm/test/DebugInfo/Generic/block-asan.ll2
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/basic.ll1
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/debug_info.ll4
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll54
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll3
6 files changed, 73 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index f626c2c0b16..8328d403194 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -2869,8 +2869,12 @@ void FunctionStackPoisoner::processStaticAllocas() {
Value *FakeStack;
Value *LocalStackBase;
+ Value *LocalStackBaseAlloca;
+ bool Deref;
if (DoStackMalloc) {
+ LocalStackBaseAlloca =
+ IRB.CreateAlloca(IntptrTy, nullptr, "asan_local_stack_base");
// void *FakeStack = __asan_option_detect_stack_use_after_return
// ? __asan_stack_malloc_N(LocalStackSize)
// : nullptr;
@@ -2901,25 +2905,31 @@ void FunctionStackPoisoner::processStaticAllocas() {
IRBIf.SetCurrentDebugLocation(EntryDebugLocation);
Value *AllocaValue =
DoDynamicAlloca ? createAllocaForLayout(IRBIf, L, true) : StaticAlloca;
+
IRB.SetInsertPoint(InsBefore);
IRB.SetCurrentDebugLocation(EntryDebugLocation);
LocalStackBase = createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStack);
+ IRB.SetCurrentDebugLocation(EntryDebugLocation);
+ IRB.CreateStore(LocalStackBase, LocalStackBaseAlloca);
+ Deref = true;
} else {
// void *FakeStack = nullptr;
// void *LocalStackBase = alloca(LocalStackSize);
FakeStack = ConstantInt::get(IntptrTy, 0);
LocalStackBase =
DoDynamicAlloca ? createAllocaForLayout(IRB, L, true) : StaticAlloca;
+ LocalStackBaseAlloca = LocalStackBase;
+ Deref = false;
}
// Replace Alloca instructions with base+offset.
for (const auto &Desc : SVD) {
AllocaInst *AI = Desc.AI;
+ replaceDbgDeclareForAlloca(AI, LocalStackBaseAlloca, DIB, Deref,
+ Desc.Offset, DIExpression::NoDeref);
Value *NewAllocaPtr = IRB.CreateIntToPtr(
IRB.CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy, Desc.Offset)),
AI->getType());
- replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB, DIExpression::NoDeref,
- 0, DIExpression::NoDeref);
AI->replaceAllUsesWith(NewAllocaPtr);
}
diff --git a/llvm/test/DebugInfo/Generic/block-asan.ll b/llvm/test/DebugInfo/Generic/block-asan.ll
index 73df59bf3d5..c3f71e742b2 100644
--- a/llvm/test/DebugInfo/Generic/block-asan.ll
+++ b/llvm/test/DebugInfo/Generic/block-asan.ll
@@ -13,7 +13,7 @@
; Check that the location of the ASAN instrumented __block variable is
; correct.
-; CHECK: !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
+; CHECK: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32, DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic.ll b/llvm/test/Instrumentation/AddressSanitizer/basic.ll
index 2385341387d..f684f9927fa 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/basic.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/basic.ll
@@ -91,6 +91,7 @@ entry:
}
; CHECK-LABEL: define void @alloca_test()
+; CHECK: %asan_local_stack_base = alloca
; CHECK: = alloca
; CHECK-NOT: = alloca
; CHECK: ret void
diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
index 37829b0053f..544082d0da3 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
@@ -24,9 +24,9 @@ entry:
; CHECK: entry:
; Verify that llvm.dbg.declare calls are in the entry basic block.
; CHECK-NOT: %entry
-; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[ARG_ID:[0-9]+]], metadata !DIExpression())
+; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[ARG_ID:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 32))
; CHECK-NOT: %entry
-; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[VAR_ID:[0-9]+]], metadata !DIExpression())
+; CHECK: call void @llvm.dbg.declare(metadata {{.*}}, metadata ![[VAR_ID:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 48))
declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
diff --git a/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll
new file mode 100644
index 00000000000..f440410599e
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll
@@ -0,0 +1,54 @@
+; RUN: opt -S -asan -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s
+; Generated from:
+; int bar(int y) {
+; return y + 2;
+; }
+
+source_filename = "/tmp/t.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.13.0"
+
+; Function Attrs: noinline nounwind optnone sanitize_address ssp uwtable
+define i32 @foo(i32 %i) #0 !dbg !8 {
+entry:
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !12, metadata !DIExpression()), !dbg !13
+
+ ; CHECK: %asan_local_stack_base = alloca i64
+ ; CHECK: %[[ALLOCA:.*]] = ptrtoint i8* %MyAlloca to i64
+ ; CHECK: %[[PHI:.*]] = phi i64 {{.*}} %[[ALLOCA]],
+ ; CHECK: store i64 %[[PHI]], i64* %asan_local_stack_base, !dbg
+ ; CHECK: call void @llvm.dbg.declare(metadata i64* %asan_local_stack_base, metadata !13, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32)), !dbg !14
+ %0 = load i32, i32* %i.addr, align 4, !dbg !14
+ %add = add nsw i32 %0, 2, !dbg !15
+ ret i32 %add, !dbg !16
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { noinline nounwind optnone sanitize_address ssp uwtable }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 (trunk 320115) (llvm/trunk 320116)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "/tmp/t.c", directory: "/Data/llvm")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 6.0.0 (trunk 320115) (llvm/trunk 320116)"}
+!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DILocalVariable(name: "i", arg: 1, scope: !8, file: !1, line: 1, type: !11)
+!13 = !DILocation(line: 1, column: 13, scope: !8)
+!14 = !DILocation(line: 2, column: 10, scope: !8)
+!15 = !DILocation(line: 2, column: 12, scope: !8)
+!16 = !DILocation(line: 2, column: 3, scope: !8)
diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
index 4e756f9ab2f..85169d523b6 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
@@ -22,6 +22,7 @@ entry:
; CHECK-LABEL: Func1
; CHECK-STATIC: alloca [192 x i8]
+; CHECK-STATIC: %asan_local_stack_base = alloca i64
; CHECK-DYNAMIC: alloca i8, i64 192
; CHECK-NOT: alloca
@@ -43,6 +44,7 @@ entry:
; CHECK-LABEL: Func2
; CHECK-STATIC: alloca [864 x i8]
+; CHECK-STATIC: %asan_local_stack_base = alloca i64
; CHECK-DYNAMIC: alloca i8, i64 864
; CHECK-NOT: alloca
@@ -65,6 +67,7 @@ entry:
; CHECK-LABEL: Func3
; CHECK-STATIC: alloca [768 x i8]
+; CHECK-STATIC: %asan_local_stack_base = alloca i64
; CHECK-DYNAMIC: alloca i8, i64 768
; CHECK-NOT: alloca
OpenPOWER on IntegriCloud