llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-compiler-rt-sanitizer Author: Vitaly Buka (vitalybuka) <details> <summary>Changes</summary> Prepare for incremental poisoning, poisoning all globals for every TU is expensive. --- Full diff: https://github.com/llvm/llvm-project/pull/101596.diff 1 Files Affected: - (modified) compiler-rt/lib/asan/asan_globals.cpp (+61-28) ``````````diff diff --git a/compiler-rt/lib/asan/asan_globals.cpp b/compiler-rt/lib/asan/asan_globals.cpp index cc5308a24fe89..c7dcc47460e83 100644 --- a/compiler-rt/lib/asan/asan_globals.cpp +++ b/compiler-rt/lib/asan/asan_globals.cpp @@ -47,8 +47,6 @@ struct DynInitGlobal { bool initialized = false; DynInitGlobal *next = nullptr; }; -typedef IntrusiveList<DynInitGlobal> 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 { @@ -72,6 +70,22 @@ static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator) return (*globals_by_indicator)[odr_indicator]; } +using DynInitGLobalsByModule = + DenseMap<const char *, IntrusiveList<DynInitGlobal>>; + +// TODO: Add a NoDestroy helper, this patter is very common in sanitizers. +static DynInitGLobalsByModule &DynInitGlobals() + SANITIZER_REQUIRES(mu_for_globals) { + static DynInitGLobalsByModule *globals_by_module = nullptr; + if (!globals_by_module) { + alignas(alignof(DynInitGLobalsByModule)) static char + placeholder[sizeof(DynInitGLobalsByModule)]; + globals_by_module = new (placeholder) DynInitGLobalsByModule(); + } + + return *globals_by_module; +} + ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { FastPoisonShadow(g->beg, g->size_with_redzone, value); } @@ -257,8 +271,8 @@ static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) { AddGlobalToList(list_of_all_globals, g); if (g->has_dynamic_init) { - dynamic_init_globals.push_back(new (GetGlobalLowLevelAllocator()) - DynInitGlobal{*g, false}); + DynInitGlobals()[g->module_name].push_back( + new (GetGlobalLowLevelAllocator()) DynInitGlobal{*g, false}); } } @@ -284,20 +298,42 @@ static void UnregisterGlobal(const Global *g) } } -void StopInitOrderChecking() { - if (!flags()->check_initialization_order) - return; - Lock lock(&mu_for_globals); - flags()->check_initialization_order = false; - for (const DynInitGlobal &dyn_g : dynamic_init_globals) { +static void UnpoisonDynamicGlobals(IntrusiveList<DynInitGlobal> &dyn_globals, + bool mark_initialized) { + for (auto &dyn_g : dyn_globals) { const Global *g = &dyn_g.g; + if (dyn_g.initialized) + continue; // Unpoison the whole global. PoisonShadowForGlobal(g, 0); // Poison redzones back. PoisonRedZones(*g); + if (mark_initialized) + dyn_g.initialized = true; + } +} + +static void PoisonDynamicGlobals( + const IntrusiveList<DynInitGlobal> &dyn_globals) { + for (auto &dyn_g : dyn_globals) { + const Global *g = &dyn_g.g; + if (dyn_g.initialized) + continue; + PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); } } +void StopInitOrderChecking() { + if (!flags()->check_initialization_order) + return; + Lock lock(&mu_for_globals); + flags()->check_initialization_order = false; + DynInitGlobals().forEach([&](auto &kv) { + UnpoisonDynamicGlobals(kv.second, /*mark_initialized=*/false); + return true; + }); +} + static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; } const char *MaybeDemangleGlobalName(const char *name) { @@ -458,15 +494,16 @@ 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 (DynInitGlobal &dyn_g : dynamic_init_globals) { - const Global *g = &dyn_g.g; - if (dyn_g.initialized) - continue; - if (g->module_name != module_name) - PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); - else if (!strict_init_order) - dyn_g.initialized = true; - } + + DynInitGlobals().forEach([&](auto &kv) { + if (kv.first != module_name) { + PoisonDynamicGlobals(kv.second); + } else { + UnpoisonDynamicGlobals(kv.second, + /*mark_initialized=*/!strict_init_order); + } + return true; + }); } // This method runs immediately after dynamic initialization in each TU, when @@ -479,13 +516,9 @@ void __asan_after_dynamic_init() { Lock lock(&mu_for_globals); 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. - PoisonShadowForGlobal(g, 0); - // Poison redzones back. - PoisonRedZones(*g); - } - } + + DynInitGlobals().forEach([&](auto &kv) { + UnpoisonDynamicGlobals(kv.second, /*mark_initialized=*/false); + return true; + }); } `````````` </details> https://github.com/llvm/llvm-project/pull/101596 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits