Skip to content

Commit 242e8b9

Browse files
authored
[NFC][asan] Switch from list to DynInitGlobalsByModule (#101596)
The patch just switches container from plain list of globals, to a map grouped by module. Prepare for incremental poisoning in #101837
1 parent 59476c9 commit 242e8b9

File tree

1 file changed

+62
-29
lines changed

1 file changed

+62
-29
lines changed

compiler-rt/lib/asan/asan_globals.cpp

+62-29
Original file line numberDiff line numberDiff line change
@@ -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.
5452
struct 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+
7589
ALWAYS_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+
97136
static 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

301337
static 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

Comments
 (0)