Skip to content

Commit

Permalink
[NFC][asan] Switch from list to DynInitGlobalsByModule (llvm#101596)
Browse files Browse the repository at this point in the history
The patch just switches container from plain
list of globals, to a map grouped by module.

Prepare for incremental poisoning in llvm#101837
  • Loading branch information
vitalybuka authored and kstoimenov committed Aug 15, 2024
1 parent 4d0722d commit d96df5f
Showing 1 changed file with 62 additions and 29 deletions.
91 changes: 62 additions & 29 deletions compiler-rt/lib/asan/asan_globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
}
Expand All @@ -94,6 +108,31 @@ static void AddGlobalToList(ListOfGlobals &list, const Global *g) {
list.push_front(new (GetGlobalLowLevelAllocator()) GlobalListNode{g});
}

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);
}
}

static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
if (addr >= g.beg + g.size_with_redzone) return false;
Expand Down Expand Up @@ -257,8 +296,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});
}
}

Expand Down Expand Up @@ -289,13 +328,10 @@ void StopInitOrderChecking() {
return;
Lock lock(&mu_for_globals);
flags()->check_initialization_order = false;
for (const DynInitGlobal &dyn_g : dynamic_init_globals) {
const Global *g = &dyn_g.g;
// Unpoison the whole global.
PoisonShadowForGlobal(g, 0);
// Poison redzones back.
PoisonRedZones(*g);
}
DynInitGlobals().forEach([&](auto &kv) {
UnpoisonDynamicGlobals(kv.second, /*mark_initialized=*/false);
return true;
});
}

static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; }
Expand Down Expand Up @@ -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
Expand All @@ -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;
});
}

0 comments on commit d96df5f

Please sign in to comment.