1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_globals.cc ---------------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Handle globals.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h"
151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
177e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_poisoning.h"
18e4bfca2b154a6ab4eda921aff454035f33f3551aAlexey Samsonov#include "asan_report.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h"
227e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "sanitizer_common/sanitizer_common.h"
23f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov#include "sanitizer_common/sanitizer_mutex.h"
247e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h"
255d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h"
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanytypedef __asan_global Global;
301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
31b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryanystruct ListOfGlobals {
32b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany  const Global *g;
33b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany  ListOfGlobals *next;
34b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany};
35b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany
36f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovstatic BlockingMutex mu_for_globals(LINKER_INITIALIZED);
37947fbd1a073fcd38988c1ec131452e99bb0313f8Alexey Samsonovstatic LowLevelAllocator allocator_for_globals;
383945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryanystatic ListOfGlobals *list_of_all_globals;
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
407e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonovstatic const int kDynamicInitGlobalsInitialCapacity = 512;
41dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonovstruct DynInitGlobal {
42dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov  Global g;
43dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov  bool initialized;
44dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov};
45a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovtypedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
467e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov// Lazy-initialized and never deleted.
477e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonovstatic VectorOfGlobals *dynamic_init_globals;
487e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov
495d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// We want to remember where a certain range of globals was registered.
505d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesstruct GlobalRegistrationSite {
515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  u32 stack_id;
525d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  Global *g_first, *g_last;
535d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines};
545d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinestypedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector;
555d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesstatic GlobalRegistrationSiteVector *global_registration_site_vector;
565d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
57abfdbdf5bc7e9d202652fe061acd20c14a4d22f4Timur IskhodzhanovALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {
587e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  FastPoisonShadow(g->beg, g->size_with_redzone, value);
597e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov}
607e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov
61abfdbdf5bc7e9d202652fe061acd20c14a4d22f4Timur IskhodzhanovALWAYS_INLINE void PoisonRedZones(const Global &g) {
62a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY);
637e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
647e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov                   kAsanGlobalRedzoneMagic);
65a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany  if (g.size != aligned_size) {
667e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    FastPoisonShadowPartialRightRedzone(
67a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany        g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY),
68a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany        g.size % SHADOW_GRANULARITY,
69a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany        SHADOW_GRANULARITY,
70a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany        kAsanGlobalRedzoneMagic);
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
7405e16a028d26503153a8fe512a500676cad66031Alexey Samsonovstatic void ReportGlobal(const Global &g, const char *prefix) {
755d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
765d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines         prefix, &g, (void*)g.beg, g.size, g.size_with_redzone, g.name,
7705e16a028d26503153a8fe512a500676cad66031Alexey Samsonov         g.module_name, g.has_dynamic_init);
7805e16a028d26503153a8fe512a500676cad66031Alexey Samsonov}
7905e16a028d26503153a8fe512a500676cad66031Alexey Samsonov
80589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanovbool DescribeAddressIfGlobal(uptr addr, uptr size) {
81cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->report_globals) return false;
82f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  BlockingMutexLock lock(&mu_for_globals);
831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  bool res = false;
843945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
85b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany    const Global &g = *l->g;
86cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov    if (flags()->report_globals >= 2)
8705e16a028d26503153a8fe512a500676cad66031Alexey Samsonov      ReportGlobal(g, "Search");
88589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov    res |= DescribeAddressRelativeToGlobal(addr, size, g);
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return res;
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
935d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesu32 FindRegistrationSite(const Global *g) {
945d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  CHECK(global_registration_site_vector);
955d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
965d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
975d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    if (g >= grs.g_first && g <= grs.g_last)
985d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines      return grs.stack_id;
995d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  }
1005d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  return 0;
1015d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines}
1025d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Register a global variable.
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This function may be called more than once for every global
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// so we store the globals in a map.
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic void RegisterGlobal(const Global *g) {
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  CHECK(asan_inited);
1083945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  if (flags()->report_globals >= 2)
10905e16a028d26503153a8fe512a500676cad66031Alexey Samsonov    ReportGlobal(*g, "Added");
110cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  CHECK(flags()->report_globals);
1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  CHECK(AddrIsInMem(g->beg));
112b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany  CHECK(AddrIsAlignedByGranularity(g->beg));
113c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (flags()->detect_odr_violation) {
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // Try detecting ODR (One Definition Rule) violation, i.e. the situation
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // where two globals with the same name are defined in different modules.
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // This check may not be enough: if the first global is much larger
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      // the entire redzone of the second global may be within the first global.
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        if (g->beg == l->g->beg &&
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            (flags()->detect_odr_violation >= 2 || g->size != l->g->size))
1235d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines          ReportODRViolation(g, FindRegistrationSite(g),
1245d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines                             l->g, FindRegistrationSite(l->g));
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      }
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1287e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  if (flags()->poison_heap)
1297e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    PoisonRedZones(*g);
13053177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne  ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals;
131b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany  l->g = g;
1323945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  l->next = list_of_all_globals;
1333945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  list_of_all_globals = l;
1343945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  if (g->has_dynamic_init) {
1357e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    if (dynamic_init_globals == 0) {
13653177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne      dynamic_init_globals = new(allocator_for_globals)
1377e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov          VectorOfGlobals(kDynamicInitGlobalsInitialCapacity);
1387e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    }
139dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    DynInitGlobal dyn_global = { *g, false };
140dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    dynamic_init_globals->push_back(dyn_global);
1413945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  }
1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
144c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryanystatic void UnregisterGlobal(const Global *g) {
145c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  CHECK(asan_inited);
146cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  CHECK(flags()->report_globals);
147c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  CHECK(AddrIsInMem(g->beg));
148c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  CHECK(AddrIsAlignedByGranularity(g->beg));
149c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
1507e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  if (flags()->poison_heap)
1517e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    PoisonShadowForGlobal(g, 0);
152c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  // We unpoison the shadow memory for the global but we do not remove it from
153c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  // the list because that would require O(n^2) time with the current list
154c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  // implementation. It might not be worth doing anyway.
155c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany}
156c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany
15746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovvoid StopInitOrderChecking() {
15846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  BlockingMutexLock lock(&mu_for_globals);
15946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  if (!flags()->check_initialization_order || !dynamic_init_globals)
16046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    return;
16146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  flags()->check_initialization_order = false;
16246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
16346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
16446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    const Global *g = &dyn_g.g;
16546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    // Unpoison the whole global.
16646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    PoisonShadowForGlobal(g, 0);
16746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    // Poison redzones back.
16846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov    PoisonRedZones(*g);
16946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov  }
17046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov}
17146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov
1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Interface ---------------- {{{1
1751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Register an array of globals.
1789aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyvoid __asan_register_globals(__asan_global *globals, uptr n) {
179cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->report_globals) return;
1805d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  GET_STACK_TRACE_FATAL_HERE;
1815d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  u32 stack_id = StackDepotPut(stack.trace, stack.size);
182f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  BlockingMutexLock lock(&mu_for_globals);
1835d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (!global_registration_site_vector)
1845d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    global_registration_site_vector =
1855d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines        new(allocator_for_globals) GlobalRegistrationSiteVector(128);
1865d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};
1875d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  global_registration_site_vector->push_back(site);
1885d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (flags()->report_globals >= 2) {
1895d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    PRINT_CURRENT_STACK();
1905d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]);
1915d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  }
1929aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany  for (uptr i = 0; i < n; i++) {
1931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    RegisterGlobal(&globals[i]);
1941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
196c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany
197c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany// Unregister an array of globals.
1983945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// We must do this when a shared objects gets dlclosed.
1999aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyvoid __asan_unregister_globals(__asan_global *globals, uptr n) {
200cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (!flags()->report_globals) return;
201f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  BlockingMutexLock lock(&mu_for_globals);
2029aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany  for (uptr i = 0; i < n; i++) {
203c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany    UnregisterGlobal(&globals[i]);
204c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany  }
205c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany}
2063945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany
2073945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// This method runs immediately prior to dynamic initialization in each TU,
2083945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// when all dynamically initialized globals are unpoisoned.  This method
2093945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// poisons all global variables not defined in this TU, so that a dynamic
2103945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// initializer can only touch global variables in the same TU.
21105e16a028d26503153a8fe512a500676cad66031Alexey Samsonovvoid __asan_before_dynamic_init(const char *module_name) {
2127e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  if (!flags()->check_initialization_order ||
2137e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov      !flags()->poison_heap)
2147e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    return;
215dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov  bool strict_init_order = flags()->strict_init_order;
2167e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  CHECK(dynamic_init_globals);
21705e16a028d26503153a8fe512a500676cad66031Alexey Samsonov  CHECK(module_name);
2187e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  CHECK(asan_inited);
219f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  BlockingMutexLock lock(&mu_for_globals);
2207e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  if (flags()->report_globals >= 3)
2217e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    Printf("DynInitPoison module: %s\n", module_name);
2227e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
223dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
224dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    const Global *g = &dyn_g.g;
225dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    if (dyn_g.initialized)
226dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      continue;
2277e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    if (g->module_name != module_name)
2287e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov      PoisonShadowForGlobal(g, kAsanInitializationOrderMagic);
229dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    else if (!strict_init_order)
230dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      dyn_g.initialized = true;
2313945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany  }
2323945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany}
2333945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany
2343945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// This method runs immediately after dynamic initialization in each TU, when
2353945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// all dynamically initialized globals except for those defined in the current
2363945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// TU are poisoned.  It simply unpoisons all dynamically initialized globals.
2373945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryanyvoid __asan_after_dynamic_init() {
2387e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  if (!flags()->check_initialization_order ||
2397e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov      !flags()->poison_heap)
2407e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov    return;
2417e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  CHECK(asan_inited);
242f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  BlockingMutexLock lock(&mu_for_globals);
2437e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  // FIXME: Optionally report that we're unpoisoning globals from a module.
2447e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
245dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
246dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    const Global *g = &dyn_g.g;
247dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    if (!dyn_g.initialized) {
248dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      // Unpoison the whole global.
249dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      PoisonShadowForGlobal(g, 0);
250dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      // Poison redzones back.
251dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov      PoisonRedZones(*g);
252dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov    }
2537e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov  }
2543945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany}
255