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" 2186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_suppressions.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 237e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "sanitizer_common/sanitizer_common.h" 24f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov#include "sanitizer_common/sanitizer_mutex.h" 257e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 266a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h" 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanytypedef __asan_global Global; 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 32b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryanystruct ListOfGlobals { 33b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany const Global *g; 34b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany ListOfGlobals *next; 35b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany}; 36b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany 37f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovstatic BlockingMutex mu_for_globals(LINKER_INITIALIZED); 38947fbd1a073fcd38988c1ec131452e99bb0313f8Alexey Samsonovstatic LowLevelAllocator allocator_for_globals; 393945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryanystatic ListOfGlobals *list_of_all_globals; 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 417e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonovstatic const int kDynamicInitGlobalsInitialCapacity = 512; 42dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonovstruct DynInitGlobal { 43dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov Global g; 44dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov bool initialized; 45dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov}; 46a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovtypedef InternalMmapVector<DynInitGlobal> VectorOfGlobals; 477e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov// Lazy-initialized and never deleted. 487e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonovstatic VectorOfGlobals *dynamic_init_globals; 497e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov 506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// We want to remember where a certain range of globals was registered. 516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesstruct GlobalRegistrationSite { 526a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines u32 stack_id; 536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines Global *g_first, *g_last; 546a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}; 556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinestypedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector; 566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesstatic GlobalRegistrationSiteVector *global_registration_site_vector; 576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines 58abfdbdf5bc7e9d202652fe061acd20c14a4d22f4Timur IskhodzhanovALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { 597e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov FastPoisonShadow(g->beg, g->size_with_redzone, value); 607e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov} 617e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov 62abfdbdf5bc7e9d202652fe061acd20c14a4d22f4Timur IskhodzhanovALWAYS_INLINE void PoisonRedZones(const Global &g) { 63a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); 647e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, 657e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov kAsanGlobalRedzoneMagic); 66a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany if (g.size != aligned_size) { 677e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov FastPoisonShadowPartialRightRedzone( 68a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), 69a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany g.size % SHADOW_GRANULARITY, 70a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany SHADOW_GRANULARITY, 71a3b0e5e4f9f48b2ed0baee10c0236eda7c21c660Kostya Serebryany kAsanGlobalRedzoneMagic); 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 756d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesconst uptr kMinimalDistanceFromAnotherGlobal = 64; 766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 776d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool IsAddressNearGlobal(uptr addr, const __asan_global &g) { 786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; 796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (addr >= g.beg + g.size_with_redzone) return false; 806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return true; 816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 826d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 8305e16a028d26503153a8fe512a500676cad66031Alexey Samsonovstatic void ReportGlobal(const Global &g, const char *prefix) { 846a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n", 856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, 8605e16a028d26503153a8fe512a500676cad66031Alexey Samsonov g.module_name, g.has_dynamic_init); 876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (g.location) { 886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Report(" location (%p): name=%s[%p], %d %d\n", g.location, 896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines g.location->filename, g.location->filename, g.location->line_no, 906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines g.location->column_no); 916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 9205e16a028d26503153a8fe512a500676cad66031Alexey Samsonov} 9305e16a028d26503153a8fe512a500676cad66031Alexey Samsonov 946d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic bool DescribeOrGetInfoIfGlobal(uptr addr, uptr size, bool print, 956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Global *output_global) { 96cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->report_globals) return false; 97f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov BlockingMutexLock lock(&mu_for_globals); 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool res = false; 993945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { 100b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany const Global &g = *l->g; 1016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (print) { 1026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (flags()->report_globals >= 2) 1036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ReportGlobal(g, "Search"); 1046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines res |= DescribeAddressRelativeToGlobal(addr, size, g); 1056d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } else { 1066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (IsAddressNearGlobal(addr, g)) { 1076d1862363c88c183b0ed7740fca876342cf0474bStephen Hines CHECK(output_global); 1086d1862363c88c183b0ed7740fca876342cf0474bStephen Hines *output_global = g; 1096d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return true; 1106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1116d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1166d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool DescribeAddressIfGlobal(uptr addr, uptr size) { 1176d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return DescribeOrGetInfoIfGlobal(addr, size, /* print */ true, 1186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines /* output_global */ nullptr); 1196d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 1206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1216d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesbool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) { 1226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Global g = {}; 1236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (DescribeOrGetInfoIfGlobal(addr, /* size */ 1, /* print */ false, &g)) { 1246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines internal_strncpy(descr->name, g.name, descr->name_size); 1256d1862363c88c183b0ed7740fca876342cf0474bStephen Hines descr->region_address = g.beg; 1266d1862363c88c183b0ed7740fca876342cf0474bStephen Hines descr->region_size = g.size; 1276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines descr->region_kind = "global"; 1286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return true; 1296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return false; 1316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 1326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesu32 FindRegistrationSite(const Global *g) { 1346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines CHECK(global_registration_site_vector); 1356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { 1366a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; 1376a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (g >= grs.g_first && g <= grs.g_last) 1386a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return grs.stack_id; 1396a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 1406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return 0; 1416a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines} 1426a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Register a global variable. 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This function may be called more than once for every global 1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// so we store the globals in a map. 1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic void RegisterGlobal(const Global *g) { 1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(asan_inited); 1483945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany if (flags()->report_globals >= 2) 14905e16a028d26503153a8fe512a500676cad66031Alexey Samsonov ReportGlobal(*g, "Added"); 150cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov CHECK(flags()->report_globals); 1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInMem(g->beg)); 152b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany CHECK(AddrIsAlignedByGranularity(g->beg)); 153c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (flags()->detect_odr_violation) { 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Try detecting ODR (One Definition Rule) violation, i.e. the situation 1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // where two globals with the same name are defined in different modules. 1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { 1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // This check may not be enough: if the first global is much larger 1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // the entire redzone of the second global may be within the first global. 1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { 1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (g->beg == l->g->beg && 16286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && 16386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines !IsODRViolationSuppressed(g->name)) 1646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines ReportODRViolation(g, FindRegistrationSite(g), 1656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines l->g, FindRegistrationSite(l->g)); 1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 16986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (CanPoisonMemory()) 1707e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov PoisonRedZones(*g); 17153177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; 172b89567ce41bef82cf92a9c741c78b632c07b2781Kostya Serebryany l->g = g; 1733945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany l->next = list_of_all_globals; 1743945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany list_of_all_globals = l; 1753945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany if (g->has_dynamic_init) { 1767e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov if (dynamic_init_globals == 0) { 17753177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne dynamic_init_globals = new(allocator_for_globals) 1787e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov VectorOfGlobals(kDynamicInitGlobalsInitialCapacity); 1797e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov } 180dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov DynInitGlobal dyn_global = { *g, false }; 181dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov dynamic_init_globals->push_back(dyn_global); 1823945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany } 1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 185c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryanystatic void UnregisterGlobal(const Global *g) { 186c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany CHECK(asan_inited); 18786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (flags()->report_globals >= 2) 18886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportGlobal(*g, "Removed"); 189cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov CHECK(flags()->report_globals); 190c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany CHECK(AddrIsInMem(g->beg)); 191c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany CHECK(AddrIsAlignedByGranularity(g->beg)); 192c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (CanPoisonMemory()) 1947e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov PoisonShadowForGlobal(g, 0); 195c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany // We unpoison the shadow memory for the global but we do not remove it from 196c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany // the list because that would require O(n^2) time with the current list 197c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany // implementation. It might not be worth doing anyway. 198c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany} 199c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany 20046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovvoid StopInitOrderChecking() { 20146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov BlockingMutexLock lock(&mu_for_globals); 20246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov if (!flags()->check_initialization_order || !dynamic_init_globals) 20346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov return; 20446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov flags()->check_initialization_order = false; 20546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 20646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 20746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov const Global *g = &dyn_g.g; 20846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov // Unpoison the whole global. 20946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov PoisonShadowForGlobal(g, 0); 21046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov // Poison redzones back. 21146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov PoisonRedZones(*g); 21246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov } 21346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov} 21446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov 2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Interface ---------------- {{{1 2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Register an array of globals. 2219aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyvoid __asan_register_globals(__asan_global *globals, uptr n) { 222cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->report_globals) return; 22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines GET_STACK_TRACE_MALLOC; 2246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines u32 stack_id = StackDepotPut(stack); 225f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov BlockingMutexLock lock(&mu_for_globals); 2266a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (!global_registration_site_vector) 2276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines global_registration_site_vector = 2286a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines new(allocator_for_globals) GlobalRegistrationSiteVector(128); 2296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]}; 2306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines global_registration_site_vector->push_back(site); 2316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (flags()->report_globals >= 2) { 2326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines PRINT_CURRENT_STACK(); 2336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]); 2346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 2359aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany for (uptr i = 0; i < n; i++) { 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany RegisterGlobal(&globals[i]); 2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 239c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany 240c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany// Unregister an array of globals. 2413945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// We must do this when a shared objects gets dlclosed. 2429aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyvoid __asan_unregister_globals(__asan_global *globals, uptr n) { 243cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->report_globals) return; 244f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov BlockingMutexLock lock(&mu_for_globals); 2459aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany for (uptr i = 0; i < n; i++) { 246c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany UnregisterGlobal(&globals[i]); 247c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany } 248c491061eddb0bb7047470b2746cbcbfe7730b2a9Kostya Serebryany} 2493945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany 2503945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// This method runs immediately prior to dynamic initialization in each TU, 2513945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// when all dynamically initialized globals are unpoisoned. This method 2523945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// poisons all global variables not defined in this TU, so that a dynamic 2533945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// initializer can only touch global variables in the same TU. 25405e16a028d26503153a8fe512a500676cad66031Alexey Samsonovvoid __asan_before_dynamic_init(const char *module_name) { 2557e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov if (!flags()->check_initialization_order || 25686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines !CanPoisonMemory()) 2577e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov return; 258dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov bool strict_init_order = flags()->strict_init_order; 2597e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov CHECK(dynamic_init_globals); 26005e16a028d26503153a8fe512a500676cad66031Alexey Samsonov CHECK(module_name); 2617e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov CHECK(asan_inited); 262f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov BlockingMutexLock lock(&mu_for_globals); 2637e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov if (flags()->report_globals >= 3) 2647e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov Printf("DynInitPoison module: %s\n", module_name); 2657e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 266dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 267dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov const Global *g = &dyn_g.g; 268dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov if (dyn_g.initialized) 269dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov continue; 2707e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov if (g->module_name != module_name) 2717e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); 272dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov else if (!strict_init_order) 273dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov dyn_g.initialized = true; 2743945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany } 2753945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany} 2763945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany 2773945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// This method runs immediately after dynamic initialization in each TU, when 2783945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// all dynamically initialized globals except for those defined in the current 2793945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany// TU are poisoned. It simply unpoisons all dynamically initialized globals. 2803945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryanyvoid __asan_after_dynamic_init() { 2817e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov if (!flags()->check_initialization_order || 28286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines !CanPoisonMemory()) 2837e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov return; 2847e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov CHECK(asan_inited); 285f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov BlockingMutexLock lock(&mu_for_globals); 2867e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov // FIXME: Optionally report that we're unpoisoning globals from a module. 2877e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 288dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 289dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov const Global *g = &dyn_g.g; 290dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov if (!dyn_g.initialized) { 291dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov // Unpoison the whole global. 292dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov PoisonShadowForGlobal(g, 0); 293dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov // Poison redzones back. 294dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov PoisonRedZones(*g); 295dfeef67b23ba92bbee598293164ee20078f633a1Alexey Samsonov } 2967e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov } 2973945c58f9db42671b1a3b865fde5008f09a3a40eKostya Serebryany} 298