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