From 8842da8e070866d9e09dd19e2869f395ffd1d7da Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Thu, 8 Mar 2018 21:02:18 +0000 Subject: [PATCH] [asan] Fix a false positive ODR violation due to LTO ConstantMerge pass [llvm part, take 3] 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: 327061 --- .../Instrumentation/AddressSanitizer.cpp | 10 +++++++ .../AddressSanitizer/global_lto_merge.ll | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 87576996d7b38..57672f3d15c91 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2158,6 +2158,16 @@ 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. + SmallVector GlobalsToAddToUsedList; + for (size_t i = 0; i < n; i++) { + GlobalVariable *G = NewGlobals[i]; + if (G->getName().empty()) continue; + GlobalsToAddToUsedList.push_back(G); + } + appendToCompilerUsed(M, ArrayRef(GlobalsToAddToUsedList)); + 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 index 0000000000000..aa02553f4416a --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll @@ -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)