[asan] Fix a false positive ODR violation due to LTO ConstantMerge pass [llvm part]
authorKuba Mracek <mracek@apple.com>
Thu, 8 Mar 2018 17:24:06 +0000 (17:24 +0000)
committerKuba Mracek <mracek@apple.com>
Thu, 8 Mar 2018 17:24:06 +0000 (17:24 +0000)
This fixes a false positive ODR violation that is reported by ASan when using LTO. In cases, where two constant globals have the same value, LTO will merge them, which breaks ASan's ODR detection.

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

llvm-svn: 327029

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll [new file with mode: 0644]

index 8757699..6a8ba6f 100644 (file)
@@ -2158,6 +2158,12 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M, bool
     Initializers[i] = Initializer;
   }
 
+  // Add instrumented globals to llvm.compiler.used list to avoid LTO from
+  // ConstantMerge'ing them.
+  appendToCompilerUsed(
+      M, ArrayRef<GlobalValue *>(cast<GlobalValue *>(NewGlobals.data()),
+                                 NewGlobals.size()));
+
   std::string ELFUniqueModuleId =
       (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) ? getUniqueModuleId(&M)
                                                         : "";
diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll b/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll
new file mode 100644 (file)
index 0000000..aa02553
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: opt < %s -asan -asan-module -S | FileCheck %s
+; RUN: opt < %s -asan -asan-module -constmerge -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+%struct = type { i64, i64 }
+
+@a = private unnamed_addr constant %struct { i64 16, i64 16 }, align 8
+@b = private unnamed_addr constant %struct { i64 16, i64 16 }, align 8
+
+; CHECK: @a = {{.*}} %struct
+; CHECK: @b = {{.*}} %struct
+
+; CHECK: @llvm.compiler.used =
+; CHECK-SAME: i8* bitcast ({ %struct, [48 x i8] }* @a to i8*)
+; CHECK-SAME: i8* bitcast ({ %struct, [48 x i8] }* @b to i8*)
+
+define i32 @main(i32, i8** nocapture readnone) {
+  %3 = alloca %struct, align 8
+  %4 = alloca %struct, align 8
+  %5 = bitcast %struct* %3 to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull %5, i8* bitcast (%struct* @a to i8*), i64 16, i32 8, i1 false)
+  %6 = bitcast %struct* %4 to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull %6, i8* bitcast (%struct* @b to i8*), i64 16, i32 8, i1 false)
+  call void asm sideeffect "", "r,r,~{dirflag},~{fpsr},~{flags}"(%struct* nonnull %3, %struct* nonnull %4)
+  ret i32 0
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1)