@@ -47,8 +47,6 @@ struct DynInitGlobal {
47
47
bool initialized = false ;
48
48
DynInitGlobal *next = nullptr ;
49
49
};
50
- typedef IntrusiveList<DynInitGlobal> DynInitGlobals;
51
- static DynInitGlobals dynamic_init_globals SANITIZER_GUARDED_BY (mu_for_globals);
52
50
53
51
// We want to remember where a certain range of globals was registered.
54
52
struct GlobalRegistrationSite {
@@ -72,6 +70,22 @@ static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator)
72
70
return (*globals_by_indicator)[odr_indicator];
73
71
}
74
72
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
+
75
89
ALWAYS_INLINE void PoisonShadowForGlobal (const Global *g, u8 value) {
76
90
FastPoisonShadow (g->beg , g->size_with_redzone , value);
77
91
}
@@ -94,6 +108,31 @@ static void AddGlobalToList(ListOfGlobals &list, const Global *g) {
94
108
list.push_front (new (GetGlobalLowLevelAllocator ()) GlobalListNode{g});
95
109
}
96
110
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
+
97
136
static bool IsAddressNearGlobal (uptr addr, const __asan_global &g) {
98
137
if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal ) return false ;
99
138
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) {
257
296
AddGlobalToList (list_of_all_globals, g);
258
297
259
298
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 });
262
301
}
263
302
}
264
303
@@ -289,13 +328,10 @@ void StopInitOrderChecking() {
289
328
return ;
290
329
Lock lock (&mu_for_globals);
291
330
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
+ });
299
335
}
300
336
301
337
static bool IsASCII (unsigned char c) { return /* 0x00 <= c &&*/ c <= 0x7F ; }
@@ -458,15 +494,16 @@ void __asan_before_dynamic_init(const char *module_name) {
458
494
Lock lock (&mu_for_globals);
459
495
if (flags ()->report_globals >= 3 )
460
496
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
+ });
470
507
}
471
508
472
509
// This method runs immediately after dynamic initialization in each TU, when
@@ -479,13 +516,9 @@ void __asan_after_dynamic_init() {
479
516
Lock lock (&mu_for_globals);
480
517
if (flags ()->report_globals >= 3 )
481
518
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
+ });
491
524
}
0 commit comments