1 1.1 kamil //===-- asan_globals.cc ---------------------------------------------------===// 2 1.1 kamil // 3 1.1 kamil // The LLVM Compiler Infrastructure 4 1.1 kamil // 5 1.1 kamil // This file is distributed under the University of Illinois Open Source 6 1.1 kamil // License. See LICENSE.TXT for details. 7 1.1 kamil // 8 1.1 kamil //===----------------------------------------------------------------------===// 9 1.1 kamil // 10 1.1 kamil // This file is a part of AddressSanitizer, an address sanity checker. 11 1.1 kamil // 12 1.1 kamil // Handle globals. 13 1.1 kamil //===----------------------------------------------------------------------===// 14 1.1 kamil 15 1.1 kamil #include "asan_interceptors.h" 16 1.1 kamil #include "asan_internal.h" 17 1.1 kamil #include "asan_mapping.h" 18 1.1 kamil #include "asan_poisoning.h" 19 1.1 kamil #include "asan_report.h" 20 1.1 kamil #include "asan_stack.h" 21 1.1 kamil #include "asan_stats.h" 22 1.1 kamil #include "asan_suppressions.h" 23 1.1 kamil #include "asan_thread.h" 24 1.1 kamil #include "sanitizer_common/sanitizer_common.h" 25 1.1 kamil #include "sanitizer_common/sanitizer_mutex.h" 26 1.1 kamil #include "sanitizer_common/sanitizer_placement_new.h" 27 1.1 kamil #include "sanitizer_common/sanitizer_stackdepot.h" 28 1.1 kamil #include "sanitizer_common/sanitizer_symbolizer.h" 29 1.1 kamil 30 1.1 kamil namespace __asan { 31 1.1 kamil 32 1.1 kamil typedef __asan_global Global; 33 1.1 kamil 34 1.1 kamil struct ListOfGlobals { 35 1.1 kamil const Global *g; 36 1.1 kamil ListOfGlobals *next; 37 1.1 kamil }; 38 1.1 kamil 39 1.1 kamil static BlockingMutex mu_for_globals(LINKER_INITIALIZED); 40 1.1 kamil static LowLevelAllocator allocator_for_globals; 41 1.1 kamil static ListOfGlobals *list_of_all_globals; 42 1.1 kamil 43 1.1 kamil static const int kDynamicInitGlobalsInitialCapacity = 512; 44 1.1 kamil struct DynInitGlobal { 45 1.1 kamil Global g; 46 1.1 kamil bool initialized; 47 1.1 kamil }; 48 1.1 kamil typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals; 49 1.1 kamil // Lazy-initialized and never deleted. 50 1.1 kamil static VectorOfGlobals *dynamic_init_globals; 51 1.1 kamil 52 1.1 kamil // We want to remember where a certain range of globals was registered. 53 1.1 kamil struct GlobalRegistrationSite { 54 1.1 kamil u32 stack_id; 55 1.1 kamil Global *g_first, *g_last; 56 1.1 kamil }; 57 1.1 kamil typedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector; 58 1.1 kamil static GlobalRegistrationSiteVector *global_registration_site_vector; 59 1.1 kamil 60 1.1 kamil ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { 61 1.1 kamil FastPoisonShadow(g->beg, g->size_with_redzone, value); 62 1.1 kamil } 63 1.1 kamil 64 1.1 kamil ALWAYS_INLINE void PoisonRedZones(const Global &g) { 65 1.1 kamil uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); 66 1.1 kamil FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, 67 1.1 kamil kAsanGlobalRedzoneMagic); 68 1.1 kamil if (g.size != aligned_size) { 69 1.1 kamil FastPoisonShadowPartialRightRedzone( 70 1.1 kamil g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), 71 1.1 kamil g.size % SHADOW_GRANULARITY, 72 1.1 kamil SHADOW_GRANULARITY, 73 1.1 kamil kAsanGlobalRedzoneMagic); 74 1.1 kamil } 75 1.1 kamil } 76 1.1 kamil 77 1.1 kamil const uptr kMinimalDistanceFromAnotherGlobal = 64; 78 1.1 kamil 79 1.1 kamil static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) { 80 1.1 kamil if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; 81 1.1 kamil if (addr >= g.beg + g.size_with_redzone) return false; 82 1.1 kamil return true; 83 1.1 kamil } 84 1.1 kamil 85 1.1 kamil static void ReportGlobal(const Global &g, const char *prefix) { 86 1.1 kamil Report( 87 1.1 kamil "%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu " 88 1.1 kamil "odr_indicator=%p\n", 89 1.1 kamil prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, 90 1.1 kamil g.module_name, g.has_dynamic_init, (void *)g.odr_indicator); 91 1.1 kamil if (g.location) { 92 1.1 kamil Report(" location (%p): name=%s[%p], %d %d\n", g.location, 93 1.1 kamil g.location->filename, g.location->filename, g.location->line_no, 94 1.1 kamil g.location->column_no); 95 1.1 kamil } 96 1.1 kamil } 97 1.1 kamil 98 1.1 kamil static u32 FindRegistrationSite(const Global *g) { 99 1.1 kamil mu_for_globals.CheckLocked(); 100 1.1 kamil CHECK(global_registration_site_vector); 101 1.1 kamil for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { 102 1.1 kamil GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; 103 1.1 kamil if (g >= grs.g_first && g <= grs.g_last) 104 1.1 kamil return grs.stack_id; 105 1.1 kamil } 106 1.1 kamil return 0; 107 1.1 kamil } 108 1.1 kamil 109 1.1 kamil int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, 110 1.1 kamil int max_globals) { 111 1.1 kamil if (!flags()->report_globals) return 0; 112 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 113 1.1 kamil int res = 0; 114 1.1 kamil for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { 115 1.1 kamil const Global &g = *l->g; 116 1.1 kamil if (flags()->report_globals >= 2) 117 1.1 kamil ReportGlobal(g, "Search"); 118 1.1 kamil if (IsAddressNearGlobal(addr, g)) { 119 1.1 kamil globals[res] = g; 120 1.1 kamil if (reg_sites) 121 1.1 kamil reg_sites[res] = FindRegistrationSite(&g); 122 1.1 kamil res++; 123 1.1 kamil if (res == max_globals) break; 124 1.1 kamil } 125 1.1 kamil } 126 1.1 kamil return res; 127 1.1 kamil } 128 1.1 kamil 129 1.1 kamil enum GlobalSymbolState { 130 1.1 kamil UNREGISTERED = 0, 131 1.1 kamil REGISTERED = 1 132 1.1 kamil }; 133 1.1 kamil 134 1.1 kamil // Check ODR violation for given global G via special ODR indicator. We use 135 1.1 kamil // this method in case compiler instruments global variables through their 136 1.1 kamil // local aliases. 137 1.1 kamil static void CheckODRViolationViaIndicator(const Global *g) { 138 1.1 kamil // Instrumentation requests to skip ODR check. 139 1.1 kamil if (g->odr_indicator == UINTPTR_MAX) 140 1.1 kamil return; 141 1.1 kamil u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator); 142 1.1 kamil if (*odr_indicator == UNREGISTERED) { 143 1.1 kamil *odr_indicator = REGISTERED; 144 1.1 kamil return; 145 1.1 kamil } 146 1.1 kamil // If *odr_indicator is DEFINED, some module have already registered 147 1.1 kamil // externally visible symbol with the same name. This is an ODR violation. 148 1.1 kamil for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { 149 1.1 kamil if (g->odr_indicator == l->g->odr_indicator && 150 1.1 kamil (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && 151 1.1 kamil !IsODRViolationSuppressed(g->name)) 152 1.1 kamil ReportODRViolation(g, FindRegistrationSite(g), 153 1.1 kamil l->g, FindRegistrationSite(l->g)); 154 1.1 kamil } 155 1.1 kamil } 156 1.1 kamil 157 1.1 kamil // Check ODR violation for given global G by checking if it's already poisoned. 158 1.1 kamil // We use this method in case compiler doesn't use private aliases for global 159 1.1 kamil // variables. 160 1.1 kamil static void CheckODRViolationViaPoisoning(const Global *g) { 161 1.1 kamil if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { 162 1.1 kamil // This check may not be enough: if the first global is much larger 163 1.1 kamil // the entire redzone of the second global may be within the first global. 164 1.1 kamil for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { 165 1.1 kamil if (g->beg == l->g->beg && 166 1.1 kamil (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && 167 1.1 kamil !IsODRViolationSuppressed(g->name)) 168 1.1 kamil ReportODRViolation(g, FindRegistrationSite(g), 169 1.1 kamil l->g, FindRegistrationSite(l->g)); 170 1.1 kamil } 171 1.1 kamil } 172 1.1 kamil } 173 1.1 kamil 174 1.1 kamil // Clang provides two different ways for global variables protection: 175 1.1 kamil // it can poison the global itself or its private alias. In former 176 1.1 kamil // case we may poison same symbol multiple times, that can help us to 177 1.1 kamil // cheaply detect ODR violation: if we try to poison an already poisoned 178 1.1 kamil // global, we have ODR violation error. 179 1.1 kamil // In latter case, we poison each symbol exactly once, so we use special 180 1.1 kamil // indicator symbol to perform similar check. 181 1.1 kamil // In either case, compiler provides a special odr_indicator field to Global 182 1.1 kamil // structure, that can contain two kinds of values: 183 1.1 kamil // 1) Non-zero value. In this case, odr_indicator is an address of 184 1.1 kamil // corresponding indicator variable for given global. 185 1.1 kamil // 2) Zero. This means that we don't use private aliases for global variables 186 1.1 kamil // and can freely check ODR violation with the first method. 187 1.1 kamil // 188 1.1 kamil // This routine chooses between two different methods of ODR violation 189 1.1 kamil // detection. 190 1.1 kamil static inline bool UseODRIndicator(const Global *g) { 191 1.1 kamil return g->odr_indicator > 0; 192 1.1 kamil } 193 1.1 kamil 194 1.1 kamil // Register a global variable. 195 1.1 kamil // This function may be called more than once for every global 196 1.1 kamil // so we store the globals in a map. 197 1.1 kamil static void RegisterGlobal(const Global *g) { 198 1.1 kamil CHECK(asan_inited); 199 1.1 kamil if (flags()->report_globals >= 2) 200 1.1 kamil ReportGlobal(*g, "Added"); 201 1.1 kamil CHECK(flags()->report_globals); 202 1.1 kamil CHECK(AddrIsInMem(g->beg)); 203 1.1 kamil if (!AddrIsAlignedByGranularity(g->beg)) { 204 1.1 kamil Report("The following global variable is not properly aligned.\n"); 205 1.1 kamil Report("This may happen if another global with the same name\n"); 206 1.1 kamil Report("resides in another non-instrumented module.\n"); 207 1.1 kamil Report("Or the global comes from a C file built w/o -fno-common.\n"); 208 1.1 kamil Report("In either case this is likely an ODR violation bug,\n"); 209 1.1 kamil Report("but AddressSanitizer can not provide more details.\n"); 210 1.1 kamil ReportODRViolation(g, FindRegistrationSite(g), g, FindRegistrationSite(g)); 211 1.1 kamil CHECK(AddrIsAlignedByGranularity(g->beg)); 212 1.1 kamil } 213 1.1 kamil CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 214 1.1 kamil if (flags()->detect_odr_violation) { 215 1.1 kamil // Try detecting ODR (One Definition Rule) violation, i.e. the situation 216 1.1 kamil // where two globals with the same name are defined in different modules. 217 1.1 kamil if (UseODRIndicator(g)) 218 1.1 kamil CheckODRViolationViaIndicator(g); 219 1.1 kamil else 220 1.1 kamil CheckODRViolationViaPoisoning(g); 221 1.1 kamil } 222 1.1 kamil if (CanPoisonMemory()) 223 1.1 kamil PoisonRedZones(*g); 224 1.1 kamil ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; 225 1.1 kamil l->g = g; 226 1.1 kamil l->next = list_of_all_globals; 227 1.1 kamil list_of_all_globals = l; 228 1.1 kamil if (g->has_dynamic_init) { 229 1.1 kamil if (!dynamic_init_globals) { 230 1.1 kamil dynamic_init_globals = 231 1.1 kamil new (allocator_for_globals) VectorOfGlobals; // NOLINT 232 1.1 kamil dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity); 233 1.1 kamil } 234 1.1 kamil DynInitGlobal dyn_global = { *g, false }; 235 1.1 kamil dynamic_init_globals->push_back(dyn_global); 236 1.1 kamil } 237 1.1 kamil } 238 1.1 kamil 239 1.1 kamil static void UnregisterGlobal(const Global *g) { 240 1.1 kamil CHECK(asan_inited); 241 1.1 kamil if (flags()->report_globals >= 2) 242 1.1 kamil ReportGlobal(*g, "Removed"); 243 1.1 kamil CHECK(flags()->report_globals); 244 1.1 kamil CHECK(AddrIsInMem(g->beg)); 245 1.1 kamil CHECK(AddrIsAlignedByGranularity(g->beg)); 246 1.1 kamil CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 247 1.1 kamil if (CanPoisonMemory()) 248 1.1 kamil PoisonShadowForGlobal(g, 0); 249 1.1 kamil // We unpoison the shadow memory for the global but we do not remove it from 250 1.1 kamil // the list because that would require O(n^2) time with the current list 251 1.1 kamil // implementation. It might not be worth doing anyway. 252 1.1 kamil 253 1.1 kamil // Release ODR indicator. 254 1.1 kamil if (UseODRIndicator(g) && g->odr_indicator != UINTPTR_MAX) { 255 1.1 kamil u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator); 256 1.1 kamil *odr_indicator = UNREGISTERED; 257 1.1 kamil } 258 1.1 kamil } 259 1.1 kamil 260 1.1 kamil void StopInitOrderChecking() { 261 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 262 1.1 kamil if (!flags()->check_initialization_order || !dynamic_init_globals) 263 1.1 kamil return; 264 1.1 kamil flags()->check_initialization_order = false; 265 1.1 kamil for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 266 1.1 kamil DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 267 1.1 kamil const Global *g = &dyn_g.g; 268 1.1 kamil // Unpoison the whole global. 269 1.1 kamil PoisonShadowForGlobal(g, 0); 270 1.1 kamil // Poison redzones back. 271 1.1 kamil PoisonRedZones(*g); 272 1.1 kamil } 273 1.1 kamil } 274 1.1 kamil 275 1.1 kamil static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; } 276 1.1 kamil 277 1.1 kamil const char *MaybeDemangleGlobalName(const char *name) { 278 1.1 kamil // We can spoil names of globals with C linkage, so use an heuristic 279 1.1 kamil // approach to check if the name should be demangled. 280 1.1 kamil bool should_demangle = false; 281 1.1 kamil if (name[0] == '_' && name[1] == 'Z') 282 1.1 kamil should_demangle = true; 283 1.1 kamil else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?') 284 1.1 kamil should_demangle = true; 285 1.1 kamil 286 1.1 kamil return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name; 287 1.1 kamil } 288 1.1 kamil 289 1.1 kamil // Check if the global is a zero-terminated ASCII string. If so, print it. 290 1.1 kamil void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) { 291 1.1 kamil for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { 292 1.1 kamil unsigned char c = *(unsigned char *)p; 293 1.1 kamil if (c == '\0' || !IsASCII(c)) return; 294 1.1 kamil } 295 1.1 kamil if (*(char *)(g.beg + g.size - 1) != '\0') return; 296 1.1 kamil str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name), 297 1.1 kamil (char *)g.beg); 298 1.1 kamil } 299 1.1 kamil 300 1.1 kamil static const char *GlobalFilename(const __asan_global &g) { 301 1.1 kamil const char *res = g.module_name; 302 1.1 kamil // Prefer the filename from source location, if is available. 303 1.1 kamil if (g.location) res = g.location->filename; 304 1.1 kamil CHECK(res); 305 1.1 kamil return res; 306 1.1 kamil } 307 1.1 kamil 308 1.1 kamil void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) { 309 1.1 kamil str->append("%s", GlobalFilename(g)); 310 1.1 kamil if (!g.location) return; 311 1.1 kamil if (g.location->line_no) str->append(":%d", g.location->line_no); 312 1.1 kamil if (g.location->column_no) str->append(":%d", g.location->column_no); 313 1.1 kamil } 314 1.1 kamil 315 1.1 kamil } // namespace __asan 316 1.1 kamil 317 1.1 kamil // ---------------------- Interface ---------------- {{{1 318 1.1 kamil using namespace __asan; // NOLINT 319 1.1 kamil 320 1.1 kamil 321 1.1 kamil // Apply __asan_register_globals to all globals found in the same loaded 322 1.1 kamil // executable or shared library as `flag'. The flag tracks whether globals have 323 1.1 kamil // already been registered or not for this image. 324 1.1 kamil void __asan_register_image_globals(uptr *flag) { 325 1.1 kamil if (*flag) 326 1.1 kamil return; 327 1.1 kamil AsanApplyToGlobals(__asan_register_globals, flag); 328 1.1 kamil *flag = 1; 329 1.1 kamil } 330 1.1 kamil 331 1.1 kamil // This mirrors __asan_register_image_globals. 332 1.1 kamil void __asan_unregister_image_globals(uptr *flag) { 333 1.1 kamil if (!*flag) 334 1.1 kamil return; 335 1.1 kamil AsanApplyToGlobals(__asan_unregister_globals, flag); 336 1.1 kamil *flag = 0; 337 1.1 kamil } 338 1.1 kamil 339 1.1 kamil void __asan_register_elf_globals(uptr *flag, void *start, void *stop) { 340 1.1 kamil if (*flag) return; 341 1.1 kamil if (!start) return; 342 1.1 kamil CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global)); 343 1.1 kamil __asan_global *globals_start = (__asan_global*)start; 344 1.1 kamil __asan_global *globals_stop = (__asan_global*)stop; 345 1.1 kamil __asan_register_globals(globals_start, globals_stop - globals_start); 346 1.1 kamil *flag = 1; 347 1.1 kamil } 348 1.1 kamil 349 1.1 kamil void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop) { 350 1.1 kamil if (!*flag) return; 351 1.1 kamil if (!start) return; 352 1.1 kamil CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global)); 353 1.1 kamil __asan_global *globals_start = (__asan_global*)start; 354 1.1 kamil __asan_global *globals_stop = (__asan_global*)stop; 355 1.1 kamil __asan_unregister_globals(globals_start, globals_stop - globals_start); 356 1.1 kamil *flag = 0; 357 1.1 kamil } 358 1.1 kamil 359 1.1 kamil // Register an array of globals. 360 1.1 kamil void __asan_register_globals(__asan_global *globals, uptr n) { 361 1.1 kamil if (!flags()->report_globals) return; 362 1.1 kamil GET_STACK_TRACE_MALLOC; 363 1.1 kamil u32 stack_id = StackDepotPut(stack); 364 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 365 1.1 kamil if (!global_registration_site_vector) { 366 1.1 kamil global_registration_site_vector = 367 1.1 kamil new (allocator_for_globals) GlobalRegistrationSiteVector; // NOLINT 368 1.1 kamil global_registration_site_vector->reserve(128); 369 1.1 kamil } 370 1.1 kamil GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]}; 371 1.1 kamil global_registration_site_vector->push_back(site); 372 1.1 kamil if (flags()->report_globals >= 2) { 373 1.1 kamil PRINT_CURRENT_STACK(); 374 1.1 kamil Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]); 375 1.1 kamil } 376 1.1 kamil for (uptr i = 0; i < n; i++) { 377 1.1 kamil if (SANITIZER_WINDOWS && globals[i].beg == 0) { 378 1.1 kamil // The MSVC incremental linker may pad globals out to 256 bytes. As long 379 1.1 kamil // as __asan_global is less than 256 bytes large and its size is a power 380 1.1 kamil // of two, we can skip over the padding. 381 1.1 kamil static_assert( 382 1.1 kamil sizeof(__asan_global) < 256 && 383 1.1 kamil (sizeof(__asan_global) & (sizeof(__asan_global) - 1)) == 0, 384 1.1 kamil "sizeof(__asan_global) incompatible with incremental linker padding"); 385 1.1 kamil // If these are padding bytes, the rest of the global should be zero. 386 1.1 kamil CHECK(globals[i].size == 0 && globals[i].size_with_redzone == 0 && 387 1.1 kamil globals[i].name == nullptr && globals[i].module_name == nullptr && 388 1.1 kamil globals[i].odr_indicator == 0); 389 1.1 kamil continue; 390 1.1 kamil } 391 1.1 kamil RegisterGlobal(&globals[i]); 392 1.1 kamil } 393 1.1 kamil 394 1.1 kamil // Poison the metadata. It should not be accessible to user code. 395 1.1 kamil PoisonShadow(reinterpret_cast<uptr>(globals), n * sizeof(__asan_global), 396 1.1 kamil kAsanGlobalRedzoneMagic); 397 1.1 kamil } 398 1.1 kamil 399 1.1 kamil // Unregister an array of globals. 400 1.1 kamil // We must do this when a shared objects gets dlclosed. 401 1.1 kamil void __asan_unregister_globals(__asan_global *globals, uptr n) { 402 1.1 kamil if (!flags()->report_globals) return; 403 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 404 1.1 kamil for (uptr i = 0; i < n; i++) { 405 1.1 kamil if (SANITIZER_WINDOWS && globals[i].beg == 0) { 406 1.1 kamil // Skip globals that look like padding from the MSVC incremental linker. 407 1.1 kamil // See comment in __asan_register_globals. 408 1.1 kamil continue; 409 1.1 kamil } 410 1.1 kamil UnregisterGlobal(&globals[i]); 411 1.1 kamil } 412 1.1 kamil 413 1.1 kamil // Unpoison the metadata. 414 1.1 kamil PoisonShadow(reinterpret_cast<uptr>(globals), n * sizeof(__asan_global), 0); 415 1.1 kamil } 416 1.1 kamil 417 1.1 kamil // This method runs immediately prior to dynamic initialization in each TU, 418 1.1 kamil // when all dynamically initialized globals are unpoisoned. This method 419 1.1 kamil // poisons all global variables not defined in this TU, so that a dynamic 420 1.1 kamil // initializer can only touch global variables in the same TU. 421 1.1 kamil void __asan_before_dynamic_init(const char *module_name) { 422 1.1 kamil if (!flags()->check_initialization_order || 423 1.1 kamil !CanPoisonMemory() || 424 1.1 kamil !dynamic_init_globals) 425 1.1 kamil return; 426 1.1 kamil bool strict_init_order = flags()->strict_init_order; 427 1.1 kamil CHECK(module_name); 428 1.1 kamil CHECK(asan_inited); 429 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 430 1.1 kamil if (flags()->report_globals >= 3) 431 1.1 kamil Printf("DynInitPoison module: %s\n", module_name); 432 1.1 kamil for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 433 1.1 kamil DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 434 1.1 kamil const Global *g = &dyn_g.g; 435 1.1 kamil if (dyn_g.initialized) 436 1.1 kamil continue; 437 1.1 kamil if (g->module_name != module_name) 438 1.1 kamil PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); 439 1.1 kamil else if (!strict_init_order) 440 1.1 kamil dyn_g.initialized = true; 441 1.1 kamil } 442 1.1 kamil } 443 1.1 kamil 444 1.1 kamil // This method runs immediately after dynamic initialization in each TU, when 445 1.1 kamil // all dynamically initialized globals except for those defined in the current 446 1.1 kamil // TU are poisoned. It simply unpoisons all dynamically initialized globals. 447 1.1 kamil void __asan_after_dynamic_init() { 448 1.1 kamil if (!flags()->check_initialization_order || 449 1.1 kamil !CanPoisonMemory() || 450 1.1 kamil !dynamic_init_globals) 451 1.1 kamil return; 452 1.1 kamil CHECK(asan_inited); 453 1.1 kamil BlockingMutexLock lock(&mu_for_globals); 454 1.1 kamil // FIXME: Optionally report that we're unpoisoning globals from a module. 455 1.1 kamil for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { 456 1.1 kamil DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; 457 1.1 kamil const Global *g = &dyn_g.g; 458 1.1 kamil if (!dyn_g.initialized) { 459 1.1 kamil // Unpoison the whole global. 460 1.1 kamil PoisonShadowForGlobal(g, 0); 461 1.1 kamil // Poison redzones back. 462 1.1 kamil PoisonRedZones(*g); 463 1.1 kamil } 464 1.1 kamil } 465 1.1 kamil } 466