Alexey Samsonov | e5f5895 | 2012-06-04 13:50:10 +0000 | [diff] [blame] | 1 | //===-- asan_globals.cc ---------------------------------------------------===// |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file is a part of AddressSanitizer, an address sanity checker. |
| 11 | // |
| 12 | // Handle globals. |
| 13 | //===----------------------------------------------------------------------===// |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 14 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 15 | #include "asan_interceptors.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 16 | #include "asan_internal.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 17 | #include "asan_mapping.h" |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 18 | #include "asan_poisoning.h" |
Alexey Samsonov | e4bfca2 | 2012-08-09 09:27:24 +0000 | [diff] [blame] | 19 | #include "asan_report.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 20 | #include "asan_stack.h" |
| 21 | #include "asan_stats.h" |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 22 | #include "asan_suppressions.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 23 | #include "asan_thread.h" |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 24 | #include "sanitizer_common/sanitizer_common.h" |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 25 | #include "sanitizer_common/sanitizer_mutex.h" |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 26 | #include "sanitizer_common/sanitizer_placement_new.h" |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 27 | #include "sanitizer_common/sanitizer_stackdepot.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 28 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 29 | namespace __asan { |
| 30 | |
| 31 | typedef __asan_global Global; |
| 32 | |
Kostya Serebryany | b89567c | 2011-12-02 21:02:20 +0000 | [diff] [blame] | 33 | struct ListOfGlobals { |
| 34 | const Global *g; |
| 35 | ListOfGlobals *next; |
| 36 | }; |
| 37 | |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 38 | static BlockingMutex mu_for_globals(LINKER_INITIALIZED); |
Alexey Samsonov | 947fbd1 | 2012-08-27 14:04:54 +0000 | [diff] [blame] | 39 | static LowLevelAllocator allocator_for_globals; |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 40 | static ListOfGlobals *list_of_all_globals; |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 41 | |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 42 | static const int kDynamicInitGlobalsInitialCapacity = 512; |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 43 | struct DynInitGlobal { |
| 44 | Global g; |
| 45 | bool initialized; |
| 46 | }; |
Alexey Samsonov | a64d435 | 2013-06-14 09:59:40 +0000 | [diff] [blame] | 47 | typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals; |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 48 | // Lazy-initialized and never deleted. |
| 49 | static VectorOfGlobals *dynamic_init_globals; |
| 50 | |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 51 | // We want to remember where a certain range of globals was registered. |
| 52 | struct GlobalRegistrationSite { |
| 53 | u32 stack_id; |
| 54 | Global *g_first, *g_last; |
| 55 | }; |
| 56 | typedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector; |
| 57 | static GlobalRegistrationSiteVector *global_registration_site_vector; |
| 58 | |
Timur Iskhodzhanov | abfdbdf | 2013-03-28 18:52:40 +0000 | [diff] [blame] | 59 | ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 60 | FastPoisonShadow(g->beg, g->size_with_redzone, value); |
| 61 | } |
| 62 | |
Timur Iskhodzhanov | abfdbdf | 2013-03-28 18:52:40 +0000 | [diff] [blame] | 63 | ALWAYS_INLINE void PoisonRedZones(const Global &g) { |
Kostya Serebryany | a3b0e5e | 2013-01-23 11:14:21 +0000 | [diff] [blame] | 64 | uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 65 | FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, |
| 66 | kAsanGlobalRedzoneMagic); |
Kostya Serebryany | a3b0e5e | 2013-01-23 11:14:21 +0000 | [diff] [blame] | 67 | if (g.size != aligned_size) { |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 68 | FastPoisonShadowPartialRightRedzone( |
Kostya Serebryany | a3b0e5e | 2013-01-23 11:14:21 +0000 | [diff] [blame] | 69 | g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), |
| 70 | g.size % SHADOW_GRANULARITY, |
| 71 | SHADOW_GRANULARITY, |
| 72 | kAsanGlobalRedzoneMagic); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 73 | } |
| 74 | } |
| 75 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 76 | const uptr kMinimalDistanceFromAnotherGlobal = 64; |
| 77 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 78 | static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) { |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 79 | if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; |
| 80 | if (addr >= g.beg + g.size_with_redzone) return false; |
| 81 | return true; |
Alexey Samsonov | 05e16a0 | 2013-03-26 13:06:12 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 84 | static void ReportGlobal(const Global &g, const char *prefix) { |
| 85 | Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n", |
| 86 | prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, |
| 87 | g.module_name, g.has_dynamic_init); |
| 88 | if (g.location) { |
| 89 | Report(" location (%p): name=%s[%p], %d %d\n", g.location, |
| 90 | g.location->filename, g.location->filename, g.location->line_no, |
| 91 | g.location->column_no); |
| 92 | } |
| 93 | } |
| 94 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 95 | static u32 FindRegistrationSite(const Global *g) { |
| 96 | mu_for_globals.CheckLocked(); |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 97 | CHECK(global_registration_site_vector); |
| 98 | for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { |
| 99 | GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; |
| 100 | if (g >= grs.g_first && g <= grs.g_last) |
| 101 | return grs.stack_id; |
| 102 | } |
| 103 | return 0; |
| 104 | } |
| 105 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 106 | int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, |
| 107 | int max_globals) { |
| 108 | if (!flags()->report_globals) return 0; |
| 109 | BlockingMutexLock lock(&mu_for_globals); |
| 110 | int res = 0; |
| 111 | for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { |
| 112 | const Global &g = *l->g; |
| 113 | if (flags()->report_globals >= 2) |
| 114 | ReportGlobal(g, "Search"); |
| 115 | if (IsAddressNearGlobal(addr, g)) { |
| 116 | globals[res] = g; |
| 117 | if (reg_sites) |
| 118 | reg_sites[res] = FindRegistrationSite(&g); |
| 119 | res++; |
| 120 | if (res == max_globals) break; |
| 121 | } |
| 122 | } |
| 123 | return res; |
| 124 | } |
| 125 | |
| 126 | bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) { |
| 127 | Global g = {}; |
| 128 | if (GetGlobalsForAddress(addr, &g, nullptr, 1)) { |
| 129 | internal_strncpy(descr->name, g.name, descr->name_size); |
| 130 | descr->region_address = g.beg; |
| 131 | descr->region_size = g.size; |
| 132 | descr->region_kind = "global"; |
| 133 | return true; |
| 134 | } |
| 135 | return false; |
| 136 | } |
| 137 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 138 | // Register a global variable. |
| 139 | // This function may be called more than once for every global |
| 140 | // so we store the globals in a map. |
| 141 | static void RegisterGlobal(const Global *g) { |
| 142 | CHECK(asan_inited); |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 143 | if (flags()->report_globals >= 2) |
Alexey Samsonov | 05e16a0 | 2013-03-26 13:06:12 +0000 | [diff] [blame] | 144 | ReportGlobal(*g, "Added"); |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 145 | CHECK(flags()->report_globals); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 146 | CHECK(AddrIsInMem(g->beg)); |
Kostya Serebryany | b89567c | 2011-12-02 21:02:20 +0000 | [diff] [blame] | 147 | CHECK(AddrIsAlignedByGranularity(g->beg)); |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 148 | CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 149 | if (flags()->detect_odr_violation) { |
| 150 | // Try detecting ODR (One Definition Rule) violation, i.e. the situation |
| 151 | // where two globals with the same name are defined in different modules. |
| 152 | if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { |
| 153 | // This check may not be enough: if the first global is much larger |
| 154 | // the entire redzone of the second global may be within the first global. |
| 155 | for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { |
| 156 | if (g->beg == l->g->beg && |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 157 | (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && |
| 158 | !IsODRViolationSuppressed(g->name)) |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 159 | ReportODRViolation(g, FindRegistrationSite(g), |
| 160 | l->g, FindRegistrationSite(l->g)); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 161 | } |
| 162 | } |
| 163 | } |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 164 | if (CanPoisonMemory()) |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 165 | PoisonRedZones(*g); |
Peter Collingbourne | 5317724 | 2013-10-24 06:23:39 +0000 | [diff] [blame] | 166 | ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; |
Kostya Serebryany | b89567c | 2011-12-02 21:02:20 +0000 | [diff] [blame] | 167 | l->g = g; |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 168 | l->next = list_of_all_globals; |
| 169 | list_of_all_globals = l; |
| 170 | if (g->has_dynamic_init) { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 171 | if (!dynamic_init_globals) { |
Peter Collingbourne | 5317724 | 2013-10-24 06:23:39 +0000 | [diff] [blame] | 172 | dynamic_init_globals = new(allocator_for_globals) |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 173 | VectorOfGlobals(kDynamicInitGlobalsInitialCapacity); |
| 174 | } |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 175 | DynInitGlobal dyn_global = { *g, false }; |
| 176 | dynamic_init_globals->push_back(dyn_global); |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 177 | } |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 178 | } |
| 179 | |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 180 | static void UnregisterGlobal(const Global *g) { |
| 181 | CHECK(asan_inited); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 182 | if (flags()->report_globals >= 2) |
| 183 | ReportGlobal(*g, "Removed"); |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 184 | CHECK(flags()->report_globals); |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 185 | CHECK(AddrIsInMem(g->beg)); |
| 186 | CHECK(AddrIsAlignedByGranularity(g->beg)); |
| 187 | CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 188 | if (CanPoisonMemory()) |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 189 | PoisonShadowForGlobal(g, 0); |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 190 | // We unpoison the shadow memory for the global but we do not remove it from |
| 191 | // the list because that would require O(n^2) time with the current list |
| 192 | // implementation. It might not be worth doing anyway. |
| 193 | } |
| 194 | |
Alexey Samsonov | 46efcb0 | 2013-05-24 11:46:56 +0000 | [diff] [blame] | 195 | void StopInitOrderChecking() { |
| 196 | BlockingMutexLock lock(&mu_for_globals); |
| 197 | if (!flags()->check_initialization_order || !dynamic_init_globals) |
| 198 | return; |
| 199 | flags()->check_initialization_order = false; |
| 200 | for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { |
| 201 | DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; |
| 202 | const Global *g = &dyn_g.g; |
| 203 | // Unpoison the whole global. |
| 204 | PoisonShadowForGlobal(g, 0); |
| 205 | // Poison redzones back. |
| 206 | PoisonRedZones(*g); |
| 207 | } |
| 208 | } |
| 209 | |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 210 | } // namespace __asan |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 211 | |
| 212 | // ---------------------- Interface ---------------- {{{1 |
| 213 | using namespace __asan; // NOLINT |
| 214 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 215 | // Register an array of globals. |
Kostya Serebryany | 9aead37 | 2012-05-31 14:11:07 +0000 | [diff] [blame] | 216 | void __asan_register_globals(__asan_global *globals, uptr n) { |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 217 | if (!flags()->report_globals) return; |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 218 | GET_STACK_TRACE_MALLOC; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 219 | u32 stack_id = StackDepotPut(stack); |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 220 | BlockingMutexLock lock(&mu_for_globals); |
Stephen Hines | 6a211c5 | 2014-07-21 00:49:56 -0700 | [diff] [blame] | 221 | if (!global_registration_site_vector) |
| 222 | global_registration_site_vector = |
| 223 | new(allocator_for_globals) GlobalRegistrationSiteVector(128); |
| 224 | GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]}; |
| 225 | global_registration_site_vector->push_back(site); |
| 226 | if (flags()->report_globals >= 2) { |
| 227 | PRINT_CURRENT_STACK(); |
| 228 | Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]); |
| 229 | } |
Kostya Serebryany | 9aead37 | 2012-05-31 14:11:07 +0000 | [diff] [blame] | 230 | for (uptr i = 0; i < n; i++) { |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 231 | RegisterGlobal(&globals[i]); |
| 232 | } |
| 233 | } |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 234 | |
| 235 | // Unregister an array of globals. |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 236 | // We must do this when a shared objects gets dlclosed. |
Kostya Serebryany | 9aead37 | 2012-05-31 14:11:07 +0000 | [diff] [blame] | 237 | void __asan_unregister_globals(__asan_global *globals, uptr n) { |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 238 | if (!flags()->report_globals) return; |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 239 | BlockingMutexLock lock(&mu_for_globals); |
Kostya Serebryany | 9aead37 | 2012-05-31 14:11:07 +0000 | [diff] [blame] | 240 | for (uptr i = 0; i < n; i++) { |
Kostya Serebryany | c491061 | 2011-12-15 21:55:34 +0000 | [diff] [blame] | 241 | UnregisterGlobal(&globals[i]); |
| 242 | } |
| 243 | } |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 244 | |
| 245 | // This method runs immediately prior to dynamic initialization in each TU, |
| 246 | // when all dynamically initialized globals are unpoisoned. This method |
| 247 | // poisons all global variables not defined in this TU, so that a dynamic |
| 248 | // initializer can only touch global variables in the same TU. |
Alexey Samsonov | 05e16a0 | 2013-03-26 13:06:12 +0000 | [diff] [blame] | 249 | void __asan_before_dynamic_init(const char *module_name) { |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 250 | if (!flags()->check_initialization_order || |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 251 | !CanPoisonMemory()) |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 252 | return; |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 253 | bool strict_init_order = flags()->strict_init_order; |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 254 | CHECK(dynamic_init_globals); |
Alexey Samsonov | 05e16a0 | 2013-03-26 13:06:12 +0000 | [diff] [blame] | 255 | CHECK(module_name); |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 256 | CHECK(asan_inited); |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 257 | BlockingMutexLock lock(&mu_for_globals); |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 258 | if (flags()->report_globals >= 3) |
| 259 | Printf("DynInitPoison module: %s\n", module_name); |
| 260 | for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 261 | DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; |
| 262 | const Global *g = &dyn_g.g; |
| 263 | if (dyn_g.initialized) |
| 264 | continue; |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 265 | if (g->module_name != module_name) |
| 266 | PoisonShadowForGlobal(g, kAsanInitializationOrderMagic); |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 267 | else if (!strict_init_order) |
| 268 | dyn_g.initialized = true; |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 269 | } |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | // This method runs immediately after dynamic initialization in each TU, when |
| 273 | // all dynamically initialized globals except for those defined in the current |
| 274 | // TU are poisoned. It simply unpoisons all dynamically initialized globals. |
| 275 | void __asan_after_dynamic_init() { |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 276 | if (!flags()->check_initialization_order || |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 277 | !CanPoisonMemory()) |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 278 | return; |
| 279 | CHECK(asan_inited); |
Dmitry Vyukov | f4f51f2 | 2013-01-14 07:51:39 +0000 | [diff] [blame] | 280 | BlockingMutexLock lock(&mu_for_globals); |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 281 | // FIXME: Optionally report that we're unpoisoning globals from a module. |
| 282 | for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { |
Alexey Samsonov | dfeef67 | 2013-04-19 08:35:16 +0000 | [diff] [blame] | 283 | DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; |
| 284 | const Global *g = &dyn_g.g; |
| 285 | if (!dyn_g.initialized) { |
| 286 | // Unpoison the whole global. |
| 287 | PoisonShadowForGlobal(g, 0); |
| 288 | // Poison redzones back. |
| 289 | PoisonRedZones(*g); |
| 290 | } |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 291 | } |
Kostya Serebryany | 3945c58 | 2012-08-21 14:10:25 +0000 | [diff] [blame] | 292 | } |