Index: clang/test/CodeGen/asan-static-odr.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/asan-static-odr.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s | FileCheck %s --check-prefixes=CHECK,ALIAS1 + +// No alias on Windows but indicators should work. +// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-windows-msvc %s | FileCheck %s --check-prefixes=CHECK,ALIAS0 + +static int global; + +int main() { + return global; +} + +// CHECK-NOT: __odr_asan_gen +// CHECK-NOT: private alias +// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [60 x i8] } zeroinitializer, align 32 +// CHECK: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 -1 }] +// CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) +// CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1) Index: compiler-rt/lib/asan/asan_globals.cc =================================================================== --- compiler-rt/lib/asan/asan_globals.cc +++ compiler-rt/lib/asan/asan_globals.cc @@ -83,9 +83,11 @@ } static void ReportGlobal(const Global &g, const char *prefix) { - Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n", - prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, - g.module_name, g.has_dynamic_init); + Report( + "%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu " + "odr_indicator=%p\n", + prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, + g.module_name, g.has_dynamic_init, (void *)g.odr_indicator); if (g.location) { Report(" location (%p): name=%s[%p], %d %d\n", g.location, g.location->filename, g.location->filename, g.location->line_no, @@ -133,6 +135,9 @@ // this method in case compiler instruments global variables through their // local aliases. static void CheckODRViolationViaIndicator(const Global *g) { + // Instrumentation requests to skip ODR check. + if (g->odr_indicator == UINTPTR_MAX) + return; u8 *odr_indicator = reinterpret_cast(g->odr_indicator); if (*odr_indicator == UNREGISTERED) { *odr_indicator = REGISTERED; @@ -246,7 +251,7 @@ // implementation. It might not be worth doing anyway. // Release ODR indicator. - if (UseODRIndicator(g)) { + if (UseODRIndicator(g) && g->odr_indicator != UINTPTR_MAX) { u8 *odr_indicator = reinterpret_cast(g->odr_indicator); *odr_indicator = UNREGISTERED; } Index: compiler-rt/test/asan/TestCases/Linux/odr_indicators.cc =================================================================== --- /dev/null +++ compiler-rt/test/asan/TestCases/Linux/odr_indicators.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx_asan -fPIC %s -o %t +// RUN: %env_asan_opts=report_globals=2 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,INDICATOR0 + +// RUN: %clangxx_asan -fsanitize-address-use-odr-indicator -fPIC %s -o %t +// RUN: %env_asan_opts=report_globals=2 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,INDICATOR1 + +#include + +int test_global_1; +// INDICATOR0-DAG: Added Global{{.*}} name=test_global_1{{.*}} odr_indicator={{0x0+$}} +// INDICATOR1-DAG: Added Global{{.*}} name=test_global_1{{.*}} odr_indicator={{0x0*[^0]+.*$}} + +static int test_global_2; +// CHECK-DAG: Added Global{{.*}} name=test_global_2{{.*}} odr_indicator={{0xf+$}} + +namespace { +static int test_global_3; +// CHECK-DAG: Added Global{{.*}} name={{.*}}::test_global_3{{.*}} odr_indicator={{0xf+$}} +} // namespace + +int main() { + const char f[] = "%d %d %d\n"; + // CHECK-DAG: Added Global{{.*}} name=__const.main.f{{.*}} odr_indicator={{0xf+$}} + printf(f, test_global_1, test_global_2, test_global_3); + return 0; +} Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2190,7 +2190,13 @@ GlobalAlias::create(GlobalValue::PrivateLinkage, "", NewGlobal); } - if (UseOdrIndicator) { + // ODR check is not useful for the following, but we see false reports + // caused by linker optimizations. + if (NewGlobal->hasLocalLinkage() || NewGlobal->hasGlobalUnnamedAddr() || + NewGlobal->hasLinkOnceODRLinkage() || NewGlobal->hasWeakODRLinkage()) { + ODRIndicator = ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, -1), + IRB.getInt8PtrTy()); + } else if (UseOdrIndicator) { // With local aliases, we need to provide another externally visible // symbol __odr_asan_XXX to detect ODR violation. auto *ODRIndicatorSym = Index: llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll +++ llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll @@ -5,7 +5,9 @@ target triple = "x86_64-unknown-linux-gnu" ; no action should be taken for these globals @global_noinst = linkonce_odr constant [2 x i8] [i8 1, i8 2] +@global_weak_noinst = weak_odr constant [2 x i8] [i8 1, i8 2] @global_inst = private constant [2 x i8] [i8 1, i8 2] ; CHECK-NOT: {{asan_gen.*global_noinst}} +; CHECK-NOT: {{asan_gen.*global_weak_noinst}} ; CHECK: {{asan_gen.*global_inst}} ; CHECK: @asan.module_ctor Index: llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll +++ llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll @@ -22,7 +22,7 @@ ; CHECK: [[FILENAME:@___asan_gen_.[0-9]+]] = private unnamed_addr constant [22 x i8] c"/tmp/asan-globals.cpp\00", align 1 ; CHECK: [[LOCDESCR:@___asan_gen_.[0-9]+]] = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* [[FILENAME]], i32 5, i32 5 } ; CHECK: @__asan_global_global = {{.*}}i64 ptrtoint ({ i32, [60 x i8] }* @global to i64){{.*}} section "asan_globals"{{.*}}, !associated -; CHECK: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [50 x i8] }* @.str to i64){{.*}} section "asan_globals"{{.*}}, !associated +; CHECK: @__asan_global_.str = {{.*}}i64 ptrtoint ({ [14 x i8], [50 x i8] }* @{{.str|1}} to i64){{.*}} section "asan_globals"{{.*}}, !associated ; The metadata has to be inserted to llvm.compiler.used to avoid being stripped ; during LTO. Index: llvm/test/Instrumentation/AddressSanitizer/local_alias.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/local_alias.ll +++ llvm/test/Instrumentation/AddressSanitizer/local_alias.ll @@ -6,14 +6,21 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -@a = internal global [2 x i32] zeroinitializer, align 4 +@a = dso_local global [2 x i32] zeroinitializer, align 4 +@b = private global [2 x i32] zeroinitializer, align 4 +@c = internal global [2 x i32] zeroinitializer, align 4 +@d = unnamed_addr global [2 x i32] zeroinitializer, align 4 ; Check that we generate internal alias and odr indicator symbols for global to be protected. ; CHECK-NOINDICATOR-NOT: __odr_asan_gen_a ; CHECK-NOALIAS-NOT: private alias -; CHECK-INDICATOR: @__odr_asan_gen_a = internal global i8 0, align 1 +; CHECK-INDICATOR: @__odr_asan_gen_a = global i8 0, align 1 ; CHECK-ALIAS: @0 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @a +; CHECK-ALIAS: @1 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @b +; CHECK-ALIAS: @2 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @c +; CHECK-ALIAS: @3 = private alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @d + ; Function Attrs: nounwind sanitize_address uwtable define i32 @foo(i32 %M) #0 { entry: Index: llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll =================================================================== --- /dev/null +++ llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -asan -asan-module -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@a = global [2 x i32] zeroinitializer, align 4 +@b = private global [2 x i32] zeroinitializer, align 4 +@c = internal global [2 x i32] zeroinitializer, align 4 +@d = unnamed_addr global [2 x i32] zeroinitializer, align 4 + +; CHECK: @__asan_global_a = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @a to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.1 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 0 } + +; CHECK: @__asan_global_b = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @b to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.2 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 } + +; CHECK: @__asan_global_c = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @c to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.3 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 } + +; CHECK: @__asan_global_d = private global { i64, i64, i64, i64, i64, i64, i64, i64 } { i64 ptrtoint ({ [2 x i32], [56 x i8] }* @d to i64), i64 8, i64 64, i64 ptrtoint ([2 x i8]* @___asan_gen_.4 to i64), i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, i64 0, i64 -1 } Index: llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll +++ llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll @@ -15,7 +15,7 @@ ; CHECK-SAME: { i64 ptrtoint ({ [5 x i8], [59 x i8] }* @"??_C@_04JIHMPGLA@asdf?$AA@" to i64), ; CHECK-SAME: i64 5, i64 64, i64 ptrtoint ([17 x i8]* @___asan_gen_.1 to i64), ; CHECK-SAME: i64 ptrtoint ([8 x i8]* @___asan_gen_ to i64), i64 0, -; CHECK-SAME: i64 ptrtoint ({ [6 x i8]*, i32, i32 }* @___asan_gen_.3 to i64), i64 0 }, +; CHECK-SAME: i64 ptrtoint ({ [6 x i8]*, i32, i32 }* @___asan_gen_.3 to i64), i64 -1 }, ; CHECK-SAME: section ".ASAN$GL", comdat($"??_C@_04JIHMPGLA@asdf?$AA@"), align 64 ; ModuleID = 't.cpp'