Skip to content

[NFC][asan] Use Thread Safety Analysis in asan_globals.cpp #101574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions compiler-rt/lib/asan/asan_globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include "sanitizer_common/sanitizer_thread_safety.h"

namespace __asan {

Expand All @@ -39,7 +40,7 @@ struct GlobalListNode {
typedef IntrusiveList<GlobalListNode> ListOfGlobals;

static Mutex mu_for_globals;
static ListOfGlobals list_of_all_globals;
static ListOfGlobals list_of_all_globals SANITIZER_GUARDED_BY(mu_for_globals);

static const int kDynamicInitGlobalsInitialCapacity = 512;
struct DynInitGlobal {
Expand All @@ -48,7 +49,8 @@ struct DynInitGlobal {
};
typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
// Lazy-initialized and never deleted.
static VectorOfGlobals *dynamic_init_globals;
static VectorOfGlobals *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 @@ -58,7 +60,8 @@ struct GlobalRegistrationSite {
typedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector;
static GlobalRegistrationSiteVector *global_registration_site_vector;

static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator) {
static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator)
SANITIZER_REQUIRES(mu_for_globals) {
using MapOfGlobals = DenseMap<uptr, ListOfGlobals>;

static MapOfGlobals *globals_by_indicator = nullptr;
Expand Down Expand Up @@ -158,7 +161,8 @@ enum GlobalSymbolState {
// Check ODR violation for given global G via special ODR indicator. We use
// this method in case compiler instruments global variables through their
// local aliases.
static void CheckODRViolationViaIndicator(const Global *g) {
static void CheckODRViolationViaIndicator(const Global *g)
SANITIZER_REQUIRES(mu_for_globals) {
// Instrumentation requests to skip ODR check.
if (g->odr_indicator == UINTPTR_MAX)
return;
Expand All @@ -185,7 +189,8 @@ static void CheckODRViolationViaIndicator(const Global *g) {
// Check ODR violation for given global G by checking if it's already poisoned.
// We use this method in case compiler doesn't use private aliases for global
// variables.
static void CheckODRViolationViaPoisoning(const Global *g) {
static void CheckODRViolationViaPoisoning(const Global *g)
SANITIZER_REQUIRES(mu_for_globals) {
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
// This check may not be enough: if the first global is much larger
// the entire redzone of the second global may be within the first global.
Expand Down Expand Up @@ -223,7 +228,7 @@ static inline bool UseODRIndicator(const Global *g) {
// Register a global variable.
// This function may be called more than once for every global
// so we store the globals in a map.
static void RegisterGlobal(const Global *g) {
static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) {
CHECK(AsanInited());
if (flags()->report_globals >= 2)
ReportGlobal(*g, "Added");
Expand Down Expand Up @@ -263,7 +268,8 @@ static void RegisterGlobal(const Global *g) {
}
}

static void UnregisterGlobal(const Global *g) {
static void UnregisterGlobal(const Global *g)
SANITIZER_REQUIRES(mu_for_globals) {
CHECK(AsanInited());
if (flags()->report_globals >= 2)
ReportGlobal(*g, "Removed");
Expand All @@ -285,8 +291,10 @@ static void UnregisterGlobal(const Global *g) {
}

void StopInitOrderChecking() {
if (!flags()->check_initialization_order)
return;
Lock lock(&mu_for_globals);
if (!flags()->check_initialization_order || !dynamic_init_globals)
if (!dynamic_init_globals)
return;
flags()->check_initialization_order = false;
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
Expand Down Expand Up @@ -451,14 +459,14 @@ void __asan_unregister_globals(__asan_global *globals, uptr n) {
// poisons all global variables not defined in this TU, so that a dynamic
// initializer can only touch global variables in the same TU.
void __asan_before_dynamic_init(const char *module_name) {
if (!flags()->check_initialization_order ||
!CanPoisonMemory() ||
!dynamic_init_globals)
if (!flags()->check_initialization_order || !CanPoisonMemory())
return;
bool strict_init_order = flags()->strict_init_order;
CHECK(module_name);
CHECK(AsanInited());
Lock lock(&mu_for_globals);
if (!dynamic_init_globals)
return;
if (flags()->report_globals >= 3)
Printf("DynInitPoison module: %s\n", module_name);
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
Expand All @@ -477,12 +485,12 @@ void __asan_before_dynamic_init(const char *module_name) {
// all dynamically initialized globals except for those defined in the current
// TU are poisoned. It simply unpoisons all dynamically initialized globals.
void __asan_after_dynamic_init() {
if (!flags()->check_initialization_order ||
!CanPoisonMemory() ||
!dynamic_init_globals)
if (!flags()->check_initialization_order || !CanPoisonMemory())
return;
CHECK(AsanInited());
Lock lock(&mu_for_globals);
if (!dynamic_init_globals)
return;
// FIXME: Optionally report that we're unpoisoning globals from a module.
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
Expand Down
Loading