From 7c78db5065a34dd91b294fc68ad1b1ea0df13cba Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Tue, 9 Dec 2014 17:55:48 +0000 Subject: [PATCH] Correctly handle complex locations expressions in replaceDbgDeclareForAlloca() replaceDbgDeclareForAlloca() replaces an alloca by a value storing the address of what was the alloca. If there is a dbg.declare corresponding to that alloca, we need to lower it to a dbg.value describing the additional dereference operation to be performed to get to the underlying variable. This is done by adding a DW_OP_deref to the complex location part of the location description. This deref was added to the end of the operation list, which is wrong. The expression applies to what is described by the dbg.{declare,value}, and as we are changing this, we need to apply the DW_OP_deref as the first operation in the list. Part of the fix for rdar://19162268. llvm-svn: 223799 --- llvm/lib/Transforms/Utils/Local.cpp | 4 +- llvm/test/DebugInfo/block-asan.ll | 87 +++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 llvm/test/DebugInfo/block-asan.ll diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index c963c51..f8f62a9 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1111,7 +1111,7 @@ bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, if (!DIVar) return false; - // Create a copy of the original DIDescriptor for user variable, appending + // Create a copy of the original DIDescriptor for user variable, prepending // "deref" operation to a list of address elements, as new llvm.dbg.declare // will take a value storing address of the memory for variable, not // alloca itself. @@ -1121,7 +1121,7 @@ bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, NewDIExpr.push_back(DIExpr.getElement(i)); } } - NewDIExpr.push_back(dwarf::DW_OP_deref); + NewDIExpr.insert(NewDIExpr.begin(), dwarf::DW_OP_deref); // Insert llvm.dbg.declare in the same basic block as the original alloca, // and remove old llvm.dbg.declare. diff --git a/llvm/test/DebugInfo/block-asan.ll b/llvm/test/DebugInfo/block-asan.ll new file mode 100644 index 0000000..43f9e7f --- /dev/null +++ b/llvm/test/DebugInfo/block-asan.ll @@ -0,0 +1,87 @@ +; RUN: opt -S -asan %s | FileCheck %s + +; The IR of this testcase is generated from the following C code: +; void bar (int); +; +; void foo() { +; __block int x; +; bar(x); +; } +; by compiling it with 'clang -emit-llvm -g -S' and then by manually +; adding the sanitize_address attribute to the @foo() function (so +; that ASAN accepts to instrument the function in the above opt run). + +; Check that the location of the ASAN instrumented __block variable is +; correct. +; CHECK: [ DW_TAG_expression ] [DW_OP_deref] [DW_OP_plus 8] [DW_OP_deref] [DW_OP_plus 24] + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +%struct.__block_byref_x = type { i8*, %struct.__block_byref_x*, i32, i32, i32 } + +; Function Attrs: nounwind ssp uwtable +define void @foo() #0 { +entry: + %x = alloca %struct.__block_byref_x, align 8 + call void @llvm.dbg.declare(metadata !{%struct.__block_byref_x* %x}, metadata !12, metadata !22), !dbg !23 + %byref.isa = getelementptr inbounds %struct.__block_byref_x* %x, i32 0, i32 0, !dbg !24 + store i8* null, i8** %byref.isa, !dbg !24 + %byref.forwarding = getelementptr inbounds %struct.__block_byref_x* %x, i32 0, i32 1, !dbg !24 + store %struct.__block_byref_x* %x, %struct.__block_byref_x** %byref.forwarding, !dbg !24 + %byref.flags = getelementptr inbounds %struct.__block_byref_x* %x, i32 0, i32 2, !dbg !24 + store i32 0, i32* %byref.flags, !dbg !24 + %byref.size = getelementptr inbounds %struct.__block_byref_x* %x, i32 0, i32 3, !dbg !24 + store i32 32, i32* %byref.size, !dbg !24 + %forwarding = getelementptr inbounds %struct.__block_byref_x* %x, i32 0, i32 1, !dbg !25 + %0 = load %struct.__block_byref_x** %forwarding, !dbg !25 + %x1 = getelementptr inbounds %struct.__block_byref_x* %0, i32 0, i32 4, !dbg !25 + %1 = load i32* %x1, align 4, !dbg !25 + call void @bar(i32 %1), !dbg !25 + %2 = bitcast %struct.__block_byref_x* %x to i8*, !dbg !26 + call void @_Block_object_dispose(i8* %2, i32 8) #3, !dbg !26 + ret void, !dbg !26 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +declare void @bar(i32) #2 + +declare void @_Block_object_dispose(i8*, i32) + +attributes #0 = { nounwind ssp uwtable sanitize_address "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = metadata !{metadata !"0x11\0012\00clang version 3.6.0 (trunk 223120) (llvm/trunk 223119)\000\00\000\00\001", metadata !1, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2} ; [ DW_TAG_compile_unit ] [/tmp/block.c] [DW_LANG_C99] +!1 = metadata !{metadata !"block.c", metadata !"/tmp"} +!2 = metadata !{} +!3 = metadata !{metadata !4} +!4 = metadata !{metadata !"0x2e\00foo\00foo\00\003\000\001\000\000\000\000\003", metadata !1, metadata !5, metadata !6, null, void ()* @foo, null, null, metadata !2} ; [ DW_TAG_subprogram ] [line 3] [def] [foo] +!5 = metadata !{metadata !"0x29", metadata !1} ; [ DW_TAG_file_type ] [/tmp/block.c] +!6 = metadata !{metadata !"0x15\00\000\000\000\000\000\000", null, null, null, metadata !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = metadata !{null} +!8 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} +!9 = metadata !{i32 2, metadata !"Debug Info Version", i32 2} +!10 = metadata !{i32 1, metadata !"PIC Level", i32 2} +!11 = metadata !{metadata !"clang version 3.6.0 (trunk 223120) (llvm/trunk 223119)"} +!12 = metadata !{metadata !"0x100\00x\004\000", metadata !4, metadata !5, metadata !13} ; [ DW_TAG_auto_variable ] [x] [line 4] +!13 = metadata !{metadata !"0x13\00\000\00224\000\000\0016\000", metadata !1, metadata !5, null, metadata !14, null, null, null} ; [ DW_TAG_structure_type ] [line 0, size 224, align 0, offset 0] [def] [from ] +!14 = metadata !{metadata !15, metadata !17, metadata !18, metadata !20, metadata !21} +!15 = metadata !{metadata !"0xd\00__isa\000\0064\0064\000\000", metadata !1, metadata !5, metadata !16} ; [ DW_TAG_member ] [__isa] [line 0, size 64, align 64, offset 0] [from ] +!16 = metadata !{metadata !"0xf\00\000\0064\0064\000\000", null, null, null} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ] +!17 = metadata !{metadata !"0xd\00__forwarding\000\0064\0064\0064\000", metadata !1, metadata !5, metadata !16} ; [ DW_TAG_member ] [__forwarding] [line 0, size 64, align 64, offset 64] [from ] +!18 = metadata !{metadata !"0xd\00__flags\000\0032\0032\00128\000", metadata !1, metadata !5, metadata !19} ; [ DW_TAG_member ] [__flags] [line 0, size 32, align 32, offset 128] [from int] +!19 = metadata !{metadata !"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!20 = metadata !{metadata !"0xd\00__size\000\0032\0032\00160\000", metadata !1, metadata !5, metadata !19} ; [ DW_TAG_member ] [__size] [line 0, size 32, align 32, offset 160] [from int] +!21 = metadata !{metadata !"0xd\00x\000\0032\0032\00192\000", metadata !1, metadata !5, metadata !19} ; [ DW_TAG_member ] [x] [line 0, size 32, align 32, offset 192] [from int] +!22 = metadata !{metadata !"0x102\0034\008\006\0034\0024"} ; [ DW_TAG_expression ] [DW_OP_plus 8] [DW_OP_deref] [DW_OP_plus 24] +!23 = metadata !{i32 4, i32 15, metadata !4, null} +!24 = metadata !{i32 4, i32 3, metadata !4, null} +!25 = metadata !{i32 5, i32 3, metadata !4, null} +!26 = metadata !{i32 6, i32 1, metadata !4, null} -- 2.7.4