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