27
27
#include " sanitizer_common/sanitizer_placement_new.h"
28
28
#include " sanitizer_common/sanitizer_stackdepot.h"
29
29
#include " sanitizer_common/sanitizer_symbolizer.h"
30
+ #include " sanitizer_common/sanitizer_thread_safety.h"
30
31
31
32
namespace __asan {
32
33
@@ -40,17 +41,17 @@ typedef IntrusiveList<GlobalListNode> ListOfGlobals;
40
41
typedef DenseMap<uptr, ListOfGlobals> MapOfGlobals;
41
42
42
43
static Mutex mu_for_globals;
43
- static ListOfGlobals list_of_all_globals;
44
- static MapOfGlobals map_of_globals_by_indicator;
44
+ static ListOfGlobals list_of_all_globals SANITIZER_GUARDED_BY (mu_for_globals);
45
+ static MapOfGlobals map_of_globals_by_indicator
46
+ SANITIZER_GUARDED_BY (mu_for_globals);
45
47
46
- static const int kDynamicInitGlobalsInitialCapacity = 512 ;
47
48
struct DynInitGlobal {
48
- Global g;
49
- bool initialized;
49
+ Global g = {};
50
+ bool initialized = false ;
51
+ DynInitGlobal *next = nullptr ;
50
52
};
51
- typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
52
- // Lazy-initialized and never deleted.
53
- static VectorOfGlobals *dynamic_init_globals;
53
+ typedef IntrusiveList<DynInitGlobal> DynInitGlobals;
54
+ static DynInitGlobals dynamic_init_globals SANITIZER_GUARDED_BY (mu_for_globals);
54
55
55
56
// We want to remember where a certain range of globals was registered.
56
57
struct GlobalRegistrationSite {
@@ -147,7 +148,8 @@ enum GlobalSymbolState {
147
148
// Check ODR violation for given global G via special ODR indicator. We use
148
149
// this method in case compiler instruments global variables through their
149
150
// local aliases.
150
- static void CheckODRViolationViaIndicator (const Global *g) {
151
+ static void CheckODRViolationViaIndicator (const Global *g)
152
+ SANITIZER_REQUIRES(mu_for_globals) {
151
153
// Instrumentation requests to skip ODR check.
152
154
if (g->odr_indicator == UINTPTR_MAX)
153
155
return ;
@@ -175,7 +177,8 @@ static void CheckODRViolationViaIndicator(const Global *g) {
175
177
// Check ODR violation for given global G by checking if it's already poisoned.
176
178
// We use this method in case compiler doesn't use private aliases for global
177
179
// variables.
178
- static void CheckODRViolationViaPoisoning (const Global *g) {
180
+ static void CheckODRViolationViaPoisoning (const Global *g)
181
+ SANITIZER_REQUIRES(mu_for_globals) {
179
182
if (__asan_region_is_poisoned (g->beg , g->size_with_redzone )) {
180
183
// This check may not be enough: if the first global is much larger
181
184
// the entire redzone of the second global may be within the first global.
@@ -213,7 +216,7 @@ static inline bool UseODRIndicator(const Global *g) {
213
216
// Register a global variable.
214
217
// This function may be called more than once for every global
215
218
// so we store the globals in a map.
216
- static void RegisterGlobal (const Global *g) {
219
+ static void RegisterGlobal (const Global *g) SANITIZER_REQUIRES(mu_for_globals) {
217
220
CHECK (AsanInited ());
218
221
if (flags ()->report_globals >= 2 )
219
222
ReportGlobal (*g, " Added" );
@@ -244,16 +247,13 @@ static void RegisterGlobal(const Global *g) {
244
247
AddGlobalToList (list_of_all_globals, g);
245
248
246
249
if (g->has_dynamic_init ) {
247
- if (!dynamic_init_globals) {
248
- dynamic_init_globals = new (GetGlobalLowLevelAllocator ()) VectorOfGlobals;
249
- dynamic_init_globals->reserve (kDynamicInitGlobalsInitialCapacity );
250
- }
251
- DynInitGlobal dyn_global = { *g, false };
252
- dynamic_init_globals->push_back (dyn_global);
250
+ dynamic_init_globals.push_back (new (GetGlobalLowLevelAllocator ())
251
+ DynInitGlobal{*g, false });
253
252
}
254
253
}
255
254
256
- static void UnregisterGlobal (const Global *g) {
255
+ static void UnregisterGlobal (const Global *g)
256
+ SANITIZER_REQUIRES(mu_for_globals) {
257
257
CHECK (AsanInited ());
258
258
if (flags ()->report_globals >= 2 )
259
259
ReportGlobal (*g, " Removed" );
@@ -275,12 +275,11 @@ static void UnregisterGlobal(const Global *g) {
275
275
}
276
276
277
277
void StopInitOrderChecking () {
278
- Lock lock (&mu_for_globals);
279
- if (!flags ()->check_initialization_order || !dynamic_init_globals)
278
+ if (!flags ()->check_initialization_order )
280
279
return ;
280
+ Lock lock (&mu_for_globals);
281
281
flags ()->check_initialization_order = false ;
282
- for (uptr i = 0 , n = dynamic_init_globals->size (); i < n; ++i) {
283
- DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
282
+ for (const DynInitGlobal &dyn_g : dynamic_init_globals) {
284
283
const Global *g = &dyn_g.g ;
285
284
// Unpoison the whole global.
286
285
PoisonShadowForGlobal (g, 0 );
@@ -441,18 +440,15 @@ void __asan_unregister_globals(__asan_global *globals, uptr n) {
441
440
// poisons all global variables not defined in this TU, so that a dynamic
442
441
// initializer can only touch global variables in the same TU.
443
442
void __asan_before_dynamic_init (const char *module_name) {
444
- if (!flags ()->check_initialization_order ||
445
- !CanPoisonMemory () ||
446
- !dynamic_init_globals)
443
+ if (!flags ()->check_initialization_order || !CanPoisonMemory ())
447
444
return ;
448
445
bool strict_init_order = flags ()->strict_init_order ;
449
446
CHECK (module_name);
450
447
CHECK (AsanInited ());
451
448
Lock lock (&mu_for_globals);
452
449
if (flags ()->report_globals >= 3 )
453
450
Printf (" DynInitPoison module: %s\n " , module_name);
454
- for (uptr i = 0 , n = dynamic_init_globals->size (); i < n; ++i) {
455
- DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
451
+ for (DynInitGlobal &dyn_g : dynamic_init_globals) {
456
452
const Global *g = &dyn_g.g ;
457
453
if (dyn_g.initialized )
458
454
continue ;
@@ -467,15 +463,12 @@ void __asan_before_dynamic_init(const char *module_name) {
467
463
// all dynamically initialized globals except for those defined in the current
468
464
// TU are poisoned. It simply unpoisons all dynamically initialized globals.
469
465
void __asan_after_dynamic_init () {
470
- if (!flags ()->check_initialization_order ||
471
- !CanPoisonMemory () ||
472
- !dynamic_init_globals)
466
+ if (!flags ()->check_initialization_order || !CanPoisonMemory ())
473
467
return ;
474
468
CHECK (AsanInited ());
475
469
Lock lock (&mu_for_globals);
476
470
// FIXME: Optionally report that we're unpoisoning globals from a module.
477
- for (uptr i = 0 , n = dynamic_init_globals->size (); i < n; ++i) {
478
- DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
471
+ for (const DynInitGlobal &dyn_g : dynamic_init_globals) {
479
472
const Global *g = &dyn_g.g ;
480
473
if (!dyn_g.initialized ) {
481
474
// Unpoison the whole global.
0 commit comments