From 3d62680d61001ba730cabb98be55a624a9e13cc0 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 1 Aug 2024 18:17:29 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20change?= =?UTF-8?q?s=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 [skip ci] --- compiler-rt/lib/asan/asan_globals.cpp | 60 +++++++++---------- .../Helpers/initialization-nobug-extra.cpp | 6 +- .../asan/TestCases/initialization-nobug.cpp | 19 +++--- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/compiler-rt/lib/asan/asan_globals.cpp b/compiler-rt/lib/asan/asan_globals.cpp index e2ff0a51acf775..cc5308a24fe890 100644 --- a/compiler-rt/lib/asan/asan_globals.cpp +++ b/compiler-rt/lib/asan/asan_globals.cpp @@ -27,6 +27,7 @@ #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_symbolizer.h" +#include "sanitizer_common/sanitizer_thread_safety.h" namespace __asan { @@ -39,16 +40,15 @@ struct GlobalListNode { typedef IntrusiveList ListOfGlobals; static Mutex mu_for_globals; -static ListOfGlobals list_of_all_globals; +static ListOfGlobals list_of_all_globals SANITIZER_GUARDED_BY(mu_for_globals); -static const int kDynamicInitGlobalsInitialCapacity = 512; struct DynInitGlobal { - Global g; - bool initialized; + Global g = {}; + bool initialized = false; + DynInitGlobal *next = nullptr; }; -typedef InternalMmapVector VectorOfGlobals; -// Lazy-initialized and never deleted. -static VectorOfGlobals *dynamic_init_globals; +typedef IntrusiveList DynInitGlobals; +static DynInitGlobals dynamic_init_globals SANITIZER_GUARDED_BY(mu_for_globals); // We want to remember where a certain range of globals was registered. struct GlobalRegistrationSite { @@ -58,7 +58,8 @@ struct GlobalRegistrationSite { typedef InternalMmapVector GlobalRegistrationSiteVector; static GlobalRegistrationSiteVector *global_registration_site_vector; -static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator) { +static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator) + SANITIZER_REQUIRES(mu_for_globals) { using MapOfGlobals = DenseMap; static MapOfGlobals *globals_by_indicator = nullptr; @@ -158,7 +159,8 @@ enum GlobalSymbolState { // Check ODR violation for given global G via special ODR indicator. We use // this method in case compiler instruments global variables through their // local aliases. -static void CheckODRViolationViaIndicator(const Global *g) { +static void CheckODRViolationViaIndicator(const Global *g) + SANITIZER_REQUIRES(mu_for_globals) { // Instrumentation requests to skip ODR check. if (g->odr_indicator == UINTPTR_MAX) return; @@ -185,7 +187,8 @@ static void CheckODRViolationViaIndicator(const Global *g) { // Check ODR violation for given global G by checking if it's already poisoned. // We use this method in case compiler doesn't use private aliases for global // variables. -static void CheckODRViolationViaPoisoning(const Global *g) { +static void CheckODRViolationViaPoisoning(const Global *g) + SANITIZER_REQUIRES(mu_for_globals) { if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { // This check may not be enough: if the first global is much larger // the entire redzone of the second global may be within the first global. @@ -223,7 +226,7 @@ static inline bool UseODRIndicator(const Global *g) { // Register a global variable. // This function may be called more than once for every global // so we store the globals in a map. -static void RegisterGlobal(const Global *g) { +static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) { CHECK(AsanInited()); if (flags()->report_globals >= 2) ReportGlobal(*g, "Added"); @@ -254,16 +257,13 @@ static void RegisterGlobal(const Global *g) { AddGlobalToList(list_of_all_globals, g); if (g->has_dynamic_init) { - if (!dynamic_init_globals) { - dynamic_init_globals = new (GetGlobalLowLevelAllocator()) VectorOfGlobals; - dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity); - } - DynInitGlobal dyn_global = { *g, false }; - dynamic_init_globals->push_back(dyn_global); + dynamic_init_globals.push_back(new (GetGlobalLowLevelAllocator()) + DynInitGlobal{*g, false}); } } -static void UnregisterGlobal(const Global *g) { +static void UnregisterGlobal(const Global *g) + SANITIZER_REQUIRES(mu_for_globals) { CHECK(AsanInited()); if (flags()->report_globals >= 2) ReportGlobal(*g, "Removed"); @@ -285,12 +285,11 @@ static void UnregisterGlobal(const Global *g) { } void StopInitOrderChecking() { - Lock lock(&mu_for_globals); - if (!flags()->check_initialization_order || !dynamic_init_globals) + if (!flags()->check_initialization_order) return; + Lock lock(&mu_for_globals); flags()->check_initialization_order = false; - for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { - DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; + for (const DynInitGlobal &dyn_g : dynamic_init_globals) { const Global *g = &dyn_g.g; // Unpoison the whole global. PoisonShadowForGlobal(g, 0); @@ -451,9 +450,7 @@ void __asan_unregister_globals(__asan_global *globals, uptr n) { // poisons all global variables not defined in this TU, so that a dynamic // initializer can only touch global variables in the same TU. void __asan_before_dynamic_init(const char *module_name) { - if (!flags()->check_initialization_order || - !CanPoisonMemory() || - !dynamic_init_globals) + if (!flags()->check_initialization_order || !CanPoisonMemory()) return; bool strict_init_order = flags()->strict_init_order; CHECK(module_name); @@ -461,8 +458,7 @@ void __asan_before_dynamic_init(const char *module_name) { Lock lock(&mu_for_globals); if (flags()->report_globals >= 3) Printf("DynInitPoison module: %s\n", module_name); - for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { - DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; + for (DynInitGlobal &dyn_g : dynamic_init_globals) { const Global *g = &dyn_g.g; if (dyn_g.initialized) continue; @@ -477,15 +473,13 @@ void __asan_before_dynamic_init(const char *module_name) { // all dynamically initialized globals except for those defined in the current // TU are poisoned. It simply unpoisons all dynamically initialized globals. void __asan_after_dynamic_init() { - if (!flags()->check_initialization_order || - !CanPoisonMemory() || - !dynamic_init_globals) + if (!flags()->check_initialization_order || !CanPoisonMemory()) return; CHECK(AsanInited()); Lock lock(&mu_for_globals); - // FIXME: Optionally report that we're unpoisoning globals from a module. - for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { - DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; + if (flags()->report_globals >= 3) + Printf("DynInitUnpoison\n"); + for (const DynInitGlobal &dyn_g : dynamic_init_globals) { const Global *g = &dyn_g.g; if (!dyn_g.initialized) { // Unpoison the whole global. diff --git a/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cpp b/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cpp index 886165affd7603..0ce5359b405d07 100644 --- a/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cpp +++ b/compiler-rt/test/asan/TestCases/Helpers/initialization-nobug-extra.cpp @@ -1,9 +1,9 @@ // Linker initialized: int getAB(); -static int ab = getAB(); +int ab = getAB(); // Function local statics: int countCalls(); -static int one = countCalls(); +int one = countCalls(); // Trivial constructor, non-trivial destructor: int getStructWithDtorValue(); -static int val = getStructWithDtorValue(); +int val = getStructWithDtorValue(); diff --git a/compiler-rt/test/asan/TestCases/initialization-nobug.cpp b/compiler-rt/test/asan/TestCases/initialization-nobug.cpp index d4dc855148ad36..6cfef022ae57e9 100644 --- a/compiler-rt/test/asan/TestCases/initialization-nobug.cpp +++ b/compiler-rt/test/asan/TestCases/initialization-nobug.cpp @@ -1,19 +1,16 @@ // A collection of various initializers which shouldn't trip up initialization // order checking. If successful, this will just return 0. -// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-nobug-extra.cpp -o %t -// RUN: %env_asan_opts=check_initialization_order=true %run %t 2>&1 -// RUN: %clangxx_asan -O1 %s %p/Helpers/initialization-nobug-extra.cpp -o %t -// RUN: %env_asan_opts=check_initialization_order=true %run %t 2>&1 -// RUN: %clangxx_asan -O2 %s %p/Helpers/initialization-nobug-extra.cpp -o %t -// RUN: %env_asan_opts=check_initialization_order=true %run %t 2>&1 -// RUN: %clangxx_asan -O3 %s %p/Helpers/initialization-nobug-extra.cpp -o %t -// RUN: %env_asan_opts=check_initialization_order=true %run %t 2>&1 +// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-nobug-extra.cpp -o %t && %env_asan_opts=check_initialization_order=true:report_globals=3 %run %t 2>&1 | FileCheck %s --implicit-check-not "DynInit" +// RUN: %clangxx_asan -O1 %s %p/Helpers/initialization-nobug-extra.cpp -o %t && %env_asan_opts=check_initialization_order=true:report_globals=3 %run %t 2>&1 | FileCheck %s --implicit-check-not "DynInit" +// RUN: %clangxx_asan -O2 %s %p/Helpers/initialization-nobug-extra.cpp -o %t && %env_asan_opts=check_initialization_order=true:report_globals=3 %run %t 2>&1 | FileCheck %s --implicit-check-not "DynInit" +// RUN: %clangxx_asan -O3 %s %p/Helpers/initialization-nobug-extra.cpp -o %t && %env_asan_opts=check_initialization_order=true:report_globals=3 %run %t 2>&1 | FileCheck %s --implicit-check-not "DynInit" // Simple access: // Make sure that accessing a global in the same TU is safe bool condition = true; +__attribute__((noinline, weak)) int initializeSameTU() { return condition ? 0x2a : 052; } @@ -46,3 +43,9 @@ StructWithDtor struct_with_dtor; int getStructWithDtorValue() { return struct_with_dtor.value; } int main() { return 0; } + + +// CHECK: DynInitPoison module: {{.*}}initialization-nobug.cpp +// CHECK: DynInitUnpoison +// CHECK: DynInitPoison module: {{.*}}initialization-nobug-extra.cpp +// CHECK: DynInitUnpoison