@@ -47,8 +47,6 @@ struct DynInitGlobal {
4747 bool initialized = false ;
4848 DynInitGlobal *next = nullptr ;
4949};
50- typedef IntrusiveList<DynInitGlobal> DynInitGlobals;
51- static DynInitGlobals dynamic_init_globals SANITIZER_GUARDED_BY (mu_for_globals);
5250
5351// We want to remember where a certain range of globals was registered.
5452struct GlobalRegistrationSite {
@@ -72,6 +70,22 @@ static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator)
7270 return (*globals_by_indicator)[odr_indicator];
7371}
7472
73+ using DynInitGlobalsByModule =
74+ DenseMap<const char *, IntrusiveList<DynInitGlobal>>;
75+
76+ // TODO: Add a NoDestroy helper, this patter is very common in sanitizers.
77+ static DynInitGlobalsByModule &DynInitGlobals ()
78+ SANITIZER_REQUIRES(mu_for_globals) {
79+ static DynInitGlobalsByModule *globals_by_module = nullptr ;
80+ if (!globals_by_module) {
81+ alignas (alignof (DynInitGlobalsByModule)) static char
82+ placeholder[sizeof (DynInitGlobalsByModule)];
83+ globals_by_module = new (placeholder) DynInitGlobalsByModule ();
84+ }
85+
86+ return *globals_by_module;
87+ }
88+
7589ALWAYS_INLINE void PoisonShadowForGlobal (const Global *g, u8 value) {
7690 FastPoisonShadow (g->beg , g->size_with_redzone , value);
7791}
@@ -94,6 +108,31 @@ static void AddGlobalToList(ListOfGlobals &list, const Global *g) {
94108 list.push_front (new (GetGlobalLowLevelAllocator ()) GlobalListNode{g});
95109}
96110
111+ static void UnpoisonDynamicGlobals (IntrusiveList<DynInitGlobal> &dyn_globals,
112+ bool mark_initialized) {
113+ for (auto &dyn_g : dyn_globals) {
114+ const Global *g = &dyn_g.g ;
115+ if (dyn_g.initialized )
116+ continue ;
117+ // Unpoison the whole global.
118+ PoisonShadowForGlobal (g, 0 );
119+ // Poison redzones back.
120+ PoisonRedZones (*g);
121+ if (mark_initialized)
122+ dyn_g.initialized = true ;
123+ }
124+ }
125+
126+ static void PoisonDynamicGlobals (
127+ const IntrusiveList<DynInitGlobal> &dyn_globals) {
128+ for (auto &dyn_g : dyn_globals) {
129+ const Global *g = &dyn_g.g ;
130+ if (dyn_g.initialized )
131+ continue ;
132+ PoisonShadowForGlobal (g, kAsanInitializationOrderMagic );
133+ }
134+ }
135+
97136static bool IsAddressNearGlobal (uptr addr, const __asan_global &g) {
98137 if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal ) return false ;
99138 if (addr >= g.beg + g.size_with_redzone ) return false ;
@@ -257,8 +296,8 @@ static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) {
257296 AddGlobalToList (list_of_all_globals, g);
258297
259298 if (g->has_dynamic_init ) {
260- dynamic_init_globals .push_back (new ( GetGlobalLowLevelAllocator ())
261- DynInitGlobal{*g, false });
299+ DynInitGlobals ()[g-> module_name ] .push_back (
300+ new ( GetGlobalLowLevelAllocator ()) DynInitGlobal{*g, false });
262301 }
263302}
264303
@@ -289,13 +328,10 @@ void StopInitOrderChecking() {
289328 return ;
290329 Lock lock (&mu_for_globals);
291330 flags ()->check_initialization_order = false ;
292- for (const DynInitGlobal &dyn_g : dynamic_init_globals) {
293- const Global *g = &dyn_g.g ;
294- // Unpoison the whole global.
295- PoisonShadowForGlobal (g, 0 );
296- // Poison redzones back.
297- PoisonRedZones (*g);
298- }
331+ DynInitGlobals ().forEach ([&](auto &kv) {
332+ UnpoisonDynamicGlobals (kv.second , /* mark_initialized=*/ false );
333+ return true ;
334+ });
299335}
300336
301337static bool IsASCII (unsigned char c) { return /* 0x00 <= c &&*/ c <= 0x7F ; }
@@ -458,15 +494,16 @@ void __asan_before_dynamic_init(const char *module_name) {
458494 Lock lock (&mu_for_globals);
459495 if (flags ()->report_globals >= 3 )
460496 Printf (" DynInitPoison module: %s\n " , module_name);
461- for (DynInitGlobal &dyn_g : dynamic_init_globals) {
462- const Global *g = &dyn_g.g ;
463- if (dyn_g.initialized )
464- continue ;
465- if (g->module_name != module_name)
466- PoisonShadowForGlobal (g, kAsanInitializationOrderMagic );
467- else if (!strict_init_order)
468- dyn_g.initialized = true ;
469- }
497+
498+ DynInitGlobals ().forEach ([&](auto &kv) {
499+ if (kv.first != module_name) {
500+ PoisonDynamicGlobals (kv.second );
501+ } else {
502+ UnpoisonDynamicGlobals (kv.second ,
503+ /* mark_initialized=*/ !strict_init_order);
504+ }
505+ return true ;
506+ });
470507}
471508
472509// This method runs immediately after dynamic initialization in each TU, when
@@ -479,13 +516,9 @@ void __asan_after_dynamic_init() {
479516 Lock lock (&mu_for_globals);
480517 if (flags ()->report_globals >= 3 )
481518 Printf (" DynInitUnpoison\n " );
482- for (const DynInitGlobal &dyn_g : dynamic_init_globals) {
483- const Global *g = &dyn_g.g ;
484- if (!dyn_g.initialized ) {
485- // Unpoison the whole global.
486- PoisonShadowForGlobal (g, 0 );
487- // Poison redzones back.
488- PoisonRedZones (*g);
489- }
490- }
519+
520+ DynInitGlobals ().forEach ([&](auto &kv) {
521+ UnpoisonDynamicGlobals (kv.second , /* mark_initialized=*/ false );
522+ return true ;
523+ });
491524}
0 commit comments