Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -132,7 +132,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -141,6 +140,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -170,6 +170,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include #include @@ -3272,6 +3273,23 @@ StackDescription.str()); } + DILocation *getLocalVarDILocation(AllocaInst &I) { + SmallVector Users; + findDbgUsers(Users, &I); + for (auto DVI : Users) { + if (DVI) { + // Check for DW_OP_deref to make sure this intrinsic is referencing + // a variable, not a function argument. + if ((isa(DVI) && + DVI->getExpression()->startsWithDeref()) || + (isa(DVI) || isa(DVI))) { + return DVI->getDebugLoc(); + } + } + } + return nullptr; + } + void instrumentAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) { if (PoisonStack && ClPoisonStackWithCall) { IRB.CreateCall(MS.MsanPoisonStackFn, @@ -3287,19 +3305,27 @@ if (PoisonStack && MS.TrackOrigins) { Value *Descr = getLocalVarDescription(I); - IRB.CreateCall(MS.MsanSetAllocaOrigin4Fn, - {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, - IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy()), - IRB.CreatePointerCast(&F, MS.IntptrTy)}); + DILocation *Loc = getLocalVarDILocation(I); + CallInst *Call = + IRB.CreateCall(MS.MsanSetAllocaOrigin4Fn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy()), + IRB.CreatePointerCast(&F, MS.IntptrTy)}); + if (Loc) + Call->setDebugLoc(Loc); } } void instrumentAllocaKmsan(AllocaInst &I, IRBuilder<> &IRB, Value *Len) { Value *Descr = getLocalVarDescription(I); if (PoisonStack) { - IRB.CreateCall(MS.MsanPoisonAllocaFn, - {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, - IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())}); + DILocation *Loc = getLocalVarDILocation(I); + CallInst *Call = + IRB.CreateCall(MS.MsanPoisonAllocaFn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())}); + if (Loc) + Call->setDebugLoc(Loc); } else { IRB.CreateCall(MS.MsanUnpoisonAllocaFn, {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len}); Index: test/Instrumentation/MemorySanitizer/alloca-dbginfo.ll =================================================================== --- test/Instrumentation/MemorySanitizer/alloca-dbginfo.ll +++ test/Instrumentation/MemorySanitizer/alloca-dbginfo.ll @@ -0,0 +1,67 @@ +; RUN: opt < %s -msan -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN +; RUN: opt < %s -msan -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN +; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN + +; Check that hooks poisoning an alloca retain its debug info. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define dso_local i32 @foo(i32 %index) local_unnamed_addr sanitize_memory #0 !dbg !7 { +entry: + %buf = alloca [10 x i8], align 1 + call void @llvm.dbg.value(metadata i32 %index, metadata !12, metadata !DIExpression()), !dbg !19 + %0 = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 0, !dbg !20 + call void @llvm.dbg.declare(metadata [10 x i8]* %buf, metadata !13, metadata !DIExpression()), !dbg !21 + store volatile i8 0, i8* %0, align 1, !dbg !22, !tbaa !23 + %idxprom = sext i32 %index to i64, !dbg !26 + %arrayidx1 = getelementptr inbounds [10 x i8], [10 x i8]* %buf, i64 0, i64 %idxprom, !dbg !26 + %1 = load volatile i8, i8* %arrayidx1, align 1, !dbg !26, !tbaa !23 + %conv = sext i8 %1 to i32, !dbg !26 + ret i32 %conv, !dbg !27 +} + +; ORIGIN: __msan_set_alloca_origin4{{.*}}, !dbg [[DBG:![_0-9a-z]+]] +; KMSAN: __msan_poison_alloca{{.*}}, !dbg [[DBG:![_0-9a-z]+]] +; CHECK: call void @llvm.dbg.declare{{.*}}, !dbg [[DBG]] + +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind readnone speculatable } +attributes #2 = { argmemonly nounwind } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 341642)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "p.c", directory: "./") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 341642)"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !13} +!12 = !DILocalVariable(name: "index", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DILocalVariable(name: "buf", scope: !7, file: !1, line: 2, type: !14) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 80, elements: !17) +!15 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !16) +!16 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!17 = !{!18} +!18 = !DISubrange(count: 10) +!19 = !DILocation(line: 1, column: 13, scope: !7) +!20 = !DILocation(line: 2, column: 3, scope: !7) +!21 = !DILocation(line: 2, column: 17, scope: !7) +!22 = !DILocation(line: 3, column: 10, scope: !7) +!23 = !{!24, !24, i64 0} +!24 = !{!"omnipotent char", !25, i64 0} +!25 = !{!"Simple C/C++ TBAA"} +!26 = !DILocation(line: 4, column: 10, scope: !7) +!27 = !DILocation(line: 4, column: 3, scope: !7)