Alexey Samsonov | e5f5895 | 2012-06-04 13:50:10 +0000 | [diff] [blame] | 1 | //===-- asan_rtl.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 | // Main file of the ASan run-time library. |
| 13 | //===----------------------------------------------------------------------===// |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 14 | #include "asan_activation.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 15 | #include "asan_allocator.h" |
| 16 | #include "asan_interceptors.h" |
Kostya Serebryany | 230e52f | 2013-09-18 10:35:12 +0000 | [diff] [blame] | 17 | #include "asan_interface_internal.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 18 | #include "asan_internal.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 19 | #include "asan_mapping.h" |
Alexey Samsonov | 7e84349 | 2013-03-28 15:42:43 +0000 | [diff] [blame] | 20 | #include "asan_poisoning.h" |
Alexey Samsonov | e218beb | 2012-08-09 09:06:52 +0000 | [diff] [blame] | 21 | #include "asan_report.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 22 | #include "asan_stack.h" |
| 23 | #include "asan_stats.h" |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 24 | #include "asan_suppressions.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 25 | #include "asan_thread.h" |
Dmitry Vyukov | fce5bd4 | 2012-06-29 16:58:33 +0000 | [diff] [blame] | 26 | #include "sanitizer_common/sanitizer_atomic.h" |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 27 | #include "sanitizer_common/sanitizer_flags.h" |
Alexey Samsonov | 9552db7 | 2012-06-05 07:25:47 +0000 | [diff] [blame] | 28 | #include "sanitizer_common/sanitizer_libc.h" |
Alexey Samsonov | 9c6e530 | 2012-08-23 07:32:06 +0000 | [diff] [blame] | 29 | #include "sanitizer_common/sanitizer_symbolizer.h" |
Sergey Matveev | 71f0411 | 2013-05-21 14:15:35 +0000 | [diff] [blame] | 30 | #include "lsan/lsan_common.h" |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 31 | #include "ubsan/ubsan_init.h" |
| 32 | #include "ubsan/ubsan_platform.h" |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 33 | |
Kostya Serebryany | 230e52f | 2013-09-18 10:35:12 +0000 | [diff] [blame] | 34 | int __asan_option_detect_stack_use_after_return; // Global interface symbol. |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 35 | uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. |
Kostya Serebryany | 230e52f | 2013-09-18 10:35:12 +0000 | [diff] [blame] | 36 | |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 37 | namespace __asan { |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 38 | |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 39 | uptr AsanMappingProfile[kAsanMappingProfileSize]; |
| 40 | |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 41 | static void AsanDie() { |
Dmitry Vyukov | fce5bd4 | 2012-06-29 16:58:33 +0000 | [diff] [blame] | 42 | static atomic_uint32_t num_calls; |
| 43 | if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 44 | // Don't die twice - run a busy loop. |
| 45 | while (1) { } |
| 46 | } |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 47 | if (flags()->sleep_before_dying) { |
Alexey Samsonov | 4e21c6b | 2012-08-06 13:00:21 +0000 | [diff] [blame] | 48 | Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 49 | SleepForSeconds(flags()->sleep_before_dying); |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 50 | } |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 51 | if (flags()->unmap_shadow_on_exit) { |
| 52 | if (kMidMemBeg) { |
| 53 | UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); |
| 54 | UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); |
| 55 | } else { |
| 56 | UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); |
| 57 | } |
| 58 | } |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 59 | if (common_flags()->coverage) |
| 60 | __sanitizer_cov_dump(); |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 61 | if (flags()->abort_on_error) |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 62 | Abort(); |
Alexey Samsonov | f882247 | 2013-02-20 13:54:32 +0000 | [diff] [blame] | 63 | internal__exit(flags()->exitcode); |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 64 | } |
| 65 | |
Alexey Samsonov | 591616d | 2012-09-11 09:44:48 +0000 | [diff] [blame] | 66 | static void AsanCheckFailed(const char *file, int line, const char *cond, |
| 67 | u64 v1, u64 v2) { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 68 | Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file, |
| 69 | line, cond, (uptr)v1, (uptr)v2); |
Alexander Potapenko | 8e23d27 | 2012-09-07 15:50:19 +0000 | [diff] [blame] | 70 | // FIXME: check for infinite recursion without a thread-local counter here. |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 71 | PRINT_CURRENT_STACK_CHECK(); |
Alexey Samsonov | 570c2a0 | 2012-12-13 11:09:26 +0000 | [diff] [blame] | 72 | Die(); |
Alexey Samsonov | 15a7761 | 2012-06-06 15:22:20 +0000 | [diff] [blame] | 73 | } |
| 74 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 75 | // -------------------------- Globals --------------------- {{{1 |
| 76 | int asan_inited; |
| 77 | bool asan_init_is_running; |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 78 | |
| 79 | #if !ASAN_FIXED_MAPPING |
| 80 | uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; |
| 81 | #endif |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 82 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 83 | // -------------------------- Misc ---------------- {{{1 |
| 84 | void ShowStatsAndAbort() { |
| 85 | __asan_print_accumulated_stats(); |
Alexey Samsonov | 47657ce | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 86 | Die(); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 89 | // ---------------------- mmap -------------------- {{{1 |
Kostya Serebryany | a874fe5 | 2011-12-28 23:28:54 +0000 | [diff] [blame] | 90 | // Reserve memory range [beg, end]. |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 91 | // We need to use inclusive range because end+1 may not be representable. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 92 | void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) { |
Kostya Serebryany | a27bdf7 | 2013-04-05 14:40:25 +0000 | [diff] [blame] | 93 | CHECK_EQ((beg % GetPageSizeCached()), 0); |
| 94 | CHECK_EQ(((end + 1) % GetPageSizeCached()), 0); |
Kostya Serebryany | 3f4c387 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 95 | uptr size = end - beg + 1; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 96 | DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 97 | void *res = MmapFixedNoReserve(beg, size, name); |
Alexander Potapenko | 5aabcb5 | 2012-09-07 15:34:40 +0000 | [diff] [blame] | 98 | if (res != (void*)beg) { |
| 99 | Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. " |
| 100 | "Perhaps you're using ulimit -v\n", size); |
| 101 | Abort(); |
| 102 | } |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 103 | if (common_flags()->no_huge_pages_for_shadow) |
| 104 | NoHugePagesInRegion(beg, size); |
| 105 | if (common_flags()->use_madv_dontdump) |
| 106 | DontDumpShadowMemory(beg, size); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Alexey Samsonov | 70e177e | 2012-08-27 09:30:58 +0000 | [diff] [blame] | 109 | // --------------- LowLevelAllocateCallbac ---------- {{{1 |
| 110 | static void OnLowLevelAllocate(uptr ptr, uptr size) { |
| 111 | PoisonShadow(ptr, size, kAsanInternalHeapMagic); |
Kostya Serebryany | b89567c | 2011-12-02 21:02:20 +0000 | [diff] [blame] | 112 | } |
| 113 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 114 | // -------------------------- Run-time entry ------------------- {{{1 |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 115 | // exported functions |
Kostya Serebryany | 51e75c4 | 2011-12-28 00:59:39 +0000 | [diff] [blame] | 116 | #define ASAN_REPORT_ERROR(type, is_write, size) \ |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 117 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
| 118 | void __asan_report_ ## type ## size(uptr addr) { \ |
Kostya Serebryany | 9f311bb | 2012-03-15 01:36:00 +0000 | [diff] [blame] | 119 | GET_CALLER_PC_BP_SP; \ |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 120 | __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \ |
| 121 | } \ |
| 122 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
| 123 | void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ |
| 124 | GET_CALLER_PC_BP_SP; \ |
| 125 | __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \ |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | ASAN_REPORT_ERROR(load, false, 1) |
| 129 | ASAN_REPORT_ERROR(load, false, 2) |
| 130 | ASAN_REPORT_ERROR(load, false, 4) |
| 131 | ASAN_REPORT_ERROR(load, false, 8) |
| 132 | ASAN_REPORT_ERROR(load, false, 16) |
| 133 | ASAN_REPORT_ERROR(store, true, 1) |
| 134 | ASAN_REPORT_ERROR(store, true, 2) |
| 135 | ASAN_REPORT_ERROR(store, true, 4) |
| 136 | ASAN_REPORT_ERROR(store, true, 8) |
| 137 | ASAN_REPORT_ERROR(store, true, 16) |
| 138 | |
Kostya Serebryany | 366984e | 2013-02-19 11:30:25 +0000 | [diff] [blame] | 139 | #define ASAN_REPORT_ERROR_N(type, is_write) \ |
| 140 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
Kostya Serebryany | 366984e | 2013-02-19 11:30:25 +0000 | [diff] [blame] | 141 | void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ |
| 142 | GET_CALLER_PC_BP_SP; \ |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 143 | __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \ |
| 144 | } \ |
| 145 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
| 146 | void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ |
| 147 | GET_CALLER_PC_BP_SP; \ |
| 148 | __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \ |
Kostya Serebryany | 366984e | 2013-02-19 11:30:25 +0000 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | ASAN_REPORT_ERROR_N(load, false) |
| 152 | ASAN_REPORT_ERROR_N(store, true) |
| 153 | |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 154 | #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \ |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 155 | uptr sp = MEM_TO_SHADOW(addr); \ |
| 156 | uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ |
| 157 | : *reinterpret_cast<u16 *>(sp); \ |
| 158 | if (UNLIKELY(s)) { \ |
| 159 | if (UNLIKELY(size >= SHADOW_GRANULARITY || \ |
| 160 | ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \ |
| 161 | (s8)s)) { \ |
| 162 | if (__asan_test_only_reported_buggy_pointer) { \ |
| 163 | *__asan_test_only_reported_buggy_pointer = addr; \ |
| 164 | } else { \ |
| 165 | GET_CALLER_PC_BP_SP; \ |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 166 | __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg); \ |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 167 | } \ |
| 168 | } \ |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ |
| 172 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
| 173 | void __asan_##type##size(uptr addr) { \ |
| 174 | ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0) \ |
| 175 | } \ |
| 176 | extern "C" NOINLINE INTERFACE_ATTRIBUTE \ |
| 177 | void __asan_exp_##type##size(uptr addr, u32 exp) { \ |
| 178 | ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp) \ |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) |
| 182 | ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) |
| 183 | ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) |
| 184 | ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) |
| 185 | ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) |
| 186 | ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) |
| 187 | ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) |
| 188 | ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) |
| 189 | ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) |
| 190 | ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) |
| 191 | |
| 192 | extern "C" |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 193 | NOINLINE INTERFACE_ATTRIBUTE |
| 194 | void __asan_loadN(uptr addr, uptr size) { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 195 | if (__asan_region_is_poisoned(addr, size)) { |
| 196 | GET_CALLER_PC_BP_SP; |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 197 | __asan_report_error(pc, bp, sp, addr, false, size, 0); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 198 | } |
| 199 | } |
| 200 | |
| 201 | extern "C" |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 202 | NOINLINE INTERFACE_ATTRIBUTE |
| 203 | void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 204 | if (__asan_region_is_poisoned(addr, size)) { |
| 205 | GET_CALLER_PC_BP_SP; |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 206 | __asan_report_error(pc, bp, sp, addr, false, size, exp); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | extern "C" |
| 211 | NOINLINE INTERFACE_ATTRIBUTE |
| 212 | void __asan_storeN(uptr addr, uptr size) { |
| 213 | if (__asan_region_is_poisoned(addr, size)) { |
| 214 | GET_CALLER_PC_BP_SP; |
| 215 | __asan_report_error(pc, bp, sp, addr, true, size, 0); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | extern "C" |
| 220 | NOINLINE INTERFACE_ATTRIBUTE |
| 221 | void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { |
| 222 | if (__asan_region_is_poisoned(addr, size)) { |
| 223 | GET_CALLER_PC_BP_SP; |
| 224 | __asan_report_error(pc, bp, sp, addr, true, size, exp); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 225 | } |
| 226 | } |
| 227 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 228 | // Force the linker to keep the symbols for various ASan interface functions. |
| 229 | // We want to keep those in the executable in order to let the instrumented |
| 230 | // dynamic libraries access the symbol even if it is not used by the executable |
| 231 | // itself. This should help if the build system is removing dead code at link |
| 232 | // time. |
Alexander Potapenko | 3fe9135 | 2012-02-27 14:06:48 +0000 | [diff] [blame] | 233 | static NOINLINE void force_interface_symbols() { |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 234 | volatile int fake_condition = 0; // prevent dead condition elimination. |
Alexander Potapenko | 448fe9a | 2012-08-09 09:46:12 +0000 | [diff] [blame] | 235 | // __asan_report_* functions are noreturn, so we need a switch to prevent |
| 236 | // the compiler from removing any of them. |
| 237 | switch (fake_condition) { |
| 238 | case 1: __asan_report_load1(0); break; |
| 239 | case 2: __asan_report_load2(0); break; |
| 240 | case 3: __asan_report_load4(0); break; |
| 241 | case 4: __asan_report_load8(0); break; |
| 242 | case 5: __asan_report_load16(0); break; |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 243 | case 6: __asan_report_load_n(0, 0); break; |
| 244 | case 7: __asan_report_store1(0); break; |
| 245 | case 8: __asan_report_store2(0); break; |
| 246 | case 9: __asan_report_store4(0); break; |
| 247 | case 10: __asan_report_store8(0); break; |
| 248 | case 11: __asan_report_store16(0); break; |
| 249 | case 12: __asan_report_store_n(0, 0); break; |
| 250 | case 13: __asan_report_exp_load1(0, 0); break; |
| 251 | case 14: __asan_report_exp_load2(0, 0); break; |
| 252 | case 15: __asan_report_exp_load4(0, 0); break; |
| 253 | case 16: __asan_report_exp_load8(0, 0); break; |
| 254 | case 17: __asan_report_exp_load16(0, 0); break; |
| 255 | case 18: __asan_report_exp_load_n(0, 0, 0); break; |
| 256 | case 19: __asan_report_exp_store1(0, 0); break; |
| 257 | case 20: __asan_report_exp_store2(0, 0); break; |
| 258 | case 21: __asan_report_exp_store4(0, 0); break; |
| 259 | case 22: __asan_report_exp_store8(0, 0); break; |
| 260 | case 23: __asan_report_exp_store16(0, 0); break; |
| 261 | case 24: __asan_report_exp_store_n(0, 0, 0); break; |
| 262 | case 25: __asan_register_globals(0, 0); break; |
| 263 | case 26: __asan_unregister_globals(0, 0); break; |
| 264 | case 27: __asan_set_death_callback(0); break; |
| 265 | case 28: __asan_set_error_report_callback(0); break; |
| 266 | case 29: __asan_handle_no_return(); break; |
| 267 | case 30: __asan_address_is_poisoned(0); break; |
| 268 | case 31: __asan_poison_memory_region(0, 0); break; |
| 269 | case 32: __asan_unpoison_memory_region(0, 0); break; |
| 270 | case 33: __asan_set_error_exit_code(0); break; |
| 271 | case 34: __asan_before_dynamic_init(0); break; |
| 272 | case 35: __asan_after_dynamic_init(); break; |
| 273 | case 36: __asan_poison_stack_memory(0, 0); break; |
| 274 | case 37: __asan_unpoison_stack_memory(0, 0); break; |
| 275 | case 38: __asan_region_is_poisoned(0, 0); break; |
| 276 | case 39: __asan_describe_address(0); break; |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 277 | } |
| 278 | } |
| 279 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 280 | static void asan_atexit() { |
Kostya Serebryany | 283c296 | 2012-08-28 11:34:40 +0000 | [diff] [blame] | 281 | Printf("AddressSanitizer exit stats:\n"); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 282 | __asan_print_accumulated_stats(); |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 283 | // Print AsanMappingProfile. |
| 284 | for (uptr i = 0; i < kAsanMappingProfileSize; i++) { |
| 285 | if (AsanMappingProfile[i] == 0) continue; |
| 286 | Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); |
| 287 | } |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 288 | } |
| 289 | |
Kostya Serebryany | e5ab968 | 2013-01-23 13:27:43 +0000 | [diff] [blame] | 290 | static void InitializeHighMemEnd() { |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 291 | #if !ASAN_FIXED_MAPPING |
Timur Iskhodzhanov | bb7f2d8 | 2013-07-16 09:47:39 +0000 | [diff] [blame] | 292 | kHighMemEnd = GetMaxVirtualAddress(); |
| 293 | // Increase kHighMemEnd to make sure it's properly |
| 294 | // aligned together with kHighMemBeg: |
| 295 | kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1; |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 296 | #endif // !ASAN_FIXED_MAPPING |
Timur Iskhodzhanov | bb7f2d8 | 2013-07-16 09:47:39 +0000 | [diff] [blame] | 297 | CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0); |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 298 | } |
| 299 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 300 | static void ProtectGap(uptr addr, uptr size) { |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 301 | void *res = MmapNoAccess(addr, size, "shadow gap"); |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 302 | if (addr == (uptr)res) |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 303 | return; |
| 304 | Report("ERROR: Failed to protect the shadow gap. " |
| 305 | "ASan cannot proceed correctly. ABORTING.\n"); |
| 306 | DumpProcessMap(); |
| 307 | Die(); |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | static void PrintAddressSpaceLayout() { |
| 311 | Printf("|| `[%p, %p]` || HighMem ||\n", |
| 312 | (void*)kHighMemBeg, (void*)kHighMemEnd); |
| 313 | Printf("|| `[%p, %p]` || HighShadow ||\n", |
| 314 | (void*)kHighShadowBeg, (void*)kHighShadowEnd); |
| 315 | if (kMidMemBeg) { |
| 316 | Printf("|| `[%p, %p]` || ShadowGap3 ||\n", |
| 317 | (void*)kShadowGap3Beg, (void*)kShadowGap3End); |
| 318 | Printf("|| `[%p, %p]` || MidMem ||\n", |
| 319 | (void*)kMidMemBeg, (void*)kMidMemEnd); |
| 320 | Printf("|| `[%p, %p]` || ShadowGap2 ||\n", |
| 321 | (void*)kShadowGap2Beg, (void*)kShadowGap2End); |
| 322 | Printf("|| `[%p, %p]` || MidShadow ||\n", |
| 323 | (void*)kMidShadowBeg, (void*)kMidShadowEnd); |
| 324 | } |
| 325 | Printf("|| `[%p, %p]` || ShadowGap ||\n", |
| 326 | (void*)kShadowGapBeg, (void*)kShadowGapEnd); |
| 327 | if (kLowShadowBeg) { |
| 328 | Printf("|| `[%p, %p]` || LowShadow ||\n", |
| 329 | (void*)kLowShadowBeg, (void*)kLowShadowEnd); |
| 330 | Printf("|| `[%p, %p]` || LowMem ||\n", |
| 331 | (void*)kLowMemBeg, (void*)kLowMemEnd); |
| 332 | } |
| 333 | Printf("MemToShadow(shadow): %p %p %p %p", |
| 334 | (void*)MEM_TO_SHADOW(kLowShadowBeg), |
| 335 | (void*)MEM_TO_SHADOW(kLowShadowEnd), |
| 336 | (void*)MEM_TO_SHADOW(kHighShadowBeg), |
| 337 | (void*)MEM_TO_SHADOW(kHighShadowEnd)); |
| 338 | if (kMidMemBeg) { |
| 339 | Printf(" %p %p", |
| 340 | (void*)MEM_TO_SHADOW(kMidShadowBeg), |
| 341 | (void*)MEM_TO_SHADOW(kMidShadowEnd)); |
| 342 | } |
| 343 | Printf("\n"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 344 | Printf("redzone=%zu\n", (uptr)flags()->redzone); |
| 345 | Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 346 | Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); |
Sergey Matveev | ed20ebe | 2013-05-06 11:27:58 +0000 | [diff] [blame] | 347 | Printf("malloc_context_size=%zu\n", |
| 348 | (uptr)common_flags()->malloc_context_size); |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 349 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 350 | Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); |
| 351 | Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); |
| 352 | Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET); |
Kostya Serebryany | e31eca9 | 2013-02-15 12:00:24 +0000 | [diff] [blame] | 353 | CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); |
| 354 | if (kMidMemBeg) |
| 355 | CHECK(kMidShadowBeg > kLowShadowEnd && |
| 356 | kMidMemBeg > kMidShadowEnd && |
| 357 | kHighShadowBeg > kMidMemEnd); |
Kostya Serebryany | e5ab968 | 2013-01-23 13:27:43 +0000 | [diff] [blame] | 358 | } |
| 359 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 360 | static void AsanInitInternal() { |
| 361 | if (LIKELY(asan_inited)) return; |
| 362 | SanitizerToolName = "AddressSanitizer"; |
| 363 | CHECK(!asan_init_is_running && "ASan init calls itself!"); |
| 364 | asan_init_is_running = true; |
| 365 | |
| 366 | // Initialize flags. This must be done early, because most of the |
| 367 | // initialization steps look at flags(). |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 368 | InitializeFlags(); |
| 369 | |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 370 | CacheBinaryName(); |
| 371 | |
| 372 | AsanCheckIncompatibleRT(); |
| 373 | AsanCheckDynamicRTPrereqs(); |
| 374 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 375 | SetCanPoisonMemory(flags()->poison_heap); |
| 376 | SetMallocContextSize(common_flags()->malloc_context_size); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 377 | |
| 378 | InitializeHighMemEnd(); |
| 379 | |
| 380 | // Make sure we are not statically linked. |
| 381 | AsanDoesNotSupportStaticLinkage(); |
| 382 | |
| 383 | // Install tool-specific callbacks in sanitizer_common. |
| 384 | SetDieCallback(AsanDie); |
| 385 | SetCheckFailedCallback(AsanCheckFailed); |
| 386 | SetPrintfAndReportCallback(AppendToErrorMessageBuffer); |
| 387 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 388 | __sanitizer_set_report_path(common_flags()->log_path); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 389 | |
| 390 | // Enable UAR detection, if required. |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 391 | __asan_option_detect_stack_use_after_return = |
| 392 | flags()->detect_stack_use_after_return; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 393 | |
| 394 | // Re-exec ourselves if we need to set additional env or command line args. |
| 395 | MaybeReexec(); |
| 396 | |
| 397 | // Setup internal allocator callback. |
| 398 | SetLowLevelAllocateCallback(OnLowLevelAllocate); |
| 399 | |
| 400 | InitializeAsanInterceptors(); |
| 401 | |
Evgeniy Stepanov | aafc5c8 | 2014-09-15 11:37:40 +0000 | [diff] [blame] | 402 | // Enable system log ("adb logcat") on Android. |
| 403 | // Doing this before interceptors are initialized crashes in: |
| 404 | // AsanInitInternal -> android_log_write -> __interceptor_strcmp |
| 405 | AndroidLogInit(); |
| 406 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 407 | ReplaceSystemMalloc(); |
| 408 | |
| 409 | uptr shadow_start = kLowShadowBeg; |
| 410 | if (kLowShadowBeg) |
| 411 | shadow_start -= GetMmapGranularity(); |
| 412 | bool full_shadow_is_available = |
| 413 | MemoryRangeIsAvailable(shadow_start, kHighShadowEnd); |
| 414 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 415 | #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \ |
| 416 | !ASAN_FIXED_MAPPING |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 417 | if (!full_shadow_is_available) { |
| 418 | kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; |
| 419 | kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0; |
| 420 | } |
| 421 | #endif |
| 422 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 423 | if (Verbosity()) PrintAddressSpaceLayout(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 424 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 425 | DisableCoreDumperIfNecessary(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 426 | |
| 427 | if (full_shadow_is_available) { |
| 428 | // mmap the low shadow plus at least one page at the left. |
| 429 | if (kLowShadowBeg) |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 430 | ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 431 | // mmap the high shadow. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 432 | ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 433 | // protect the gap. |
| 434 | ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); |
| 435 | CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); |
| 436 | } else if (kMidMemBeg && |
| 437 | MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && |
| 438 | MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { |
| 439 | CHECK(kLowShadowBeg != kLowShadowEnd); |
| 440 | // mmap the low shadow plus at least one page at the left. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 441 | ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 442 | // mmap the mid shadow. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 443 | ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 444 | // mmap the high shadow. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 445 | ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 446 | // protect the gaps. |
| 447 | ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); |
| 448 | ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); |
| 449 | ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); |
| 450 | } else { |
| 451 | Report("Shadow memory range interleaves with an existing memory mapping. " |
| 452 | "ASan cannot proceed correctly. ABORTING.\n"); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 453 | Report("ASan shadow was supposed to be located in the [%p-%p] range.\n", |
| 454 | shadow_start, kHighShadowEnd); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 455 | DumpProcessMap(); |
| 456 | Die(); |
| 457 | } |
| 458 | |
| 459 | AsanTSDInit(PlatformTSDDtor); |
| 460 | InstallDeadlySignalHandlers(AsanOnSIGSEGV); |
| 461 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 462 | AllocatorOptions allocator_options; |
| 463 | allocator_options.SetFrom(flags(), common_flags()); |
| 464 | InitializeAllocator(allocator_options); |
| 465 | |
| 466 | MaybeStartBackgroudThread(); |
| 467 | SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 468 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 469 | // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited |
| 470 | // should be set to 1 prior to initializing the threads. |
| 471 | asan_inited = 1; |
| 472 | asan_init_is_running = false; |
| 473 | |
| 474 | if (flags()->atexit) |
| 475 | Atexit(asan_atexit); |
| 476 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 477 | InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); |
| 478 | |
| 479 | // Now that ASan runtime is (mostly) initialized, deactivate it if |
| 480 | // necessary, so that it can be re-activated when requested. |
| 481 | if (flags()->start_deactivated) |
| 482 | AsanDeactivate(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 483 | |
| 484 | // interceptors |
| 485 | InitTlsSize(); |
| 486 | |
| 487 | // Create main thread. |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 488 | AsanThread *main_thread = AsanThread::Create( |
| 489 | /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ 0, |
| 490 | /* stack */ nullptr, /* detached */ true); |
| 491 | CHECK_EQ(0, main_thread->tid()); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 492 | SetCurrentThread(main_thread); |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 493 | main_thread->ThreadStart(internal_getpid(), |
| 494 | /* signal_thread_is_registered */ nullptr); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 495 | force_interface_symbols(); // no-op. |
| 496 | SanitizerInitializeUnwinder(); |
| 497 | |
| 498 | #if CAN_SANITIZE_LEAKS |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 499 | __lsan::InitCommonLsan(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 500 | if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { |
| 501 | Atexit(__lsan::DoLeakCheck); |
| 502 | } |
| 503 | #endif // CAN_SANITIZE_LEAKS |
| 504 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 505 | #if CAN_SANITIZE_UB |
| 506 | __ubsan::InitAsPlugin(); |
| 507 | #endif |
| 508 | |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 509 | InitializeSuppressions(); |
| 510 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 511 | VReport(1, "AddressSanitizer Init done\n"); |
| 512 | } |
| 513 | |
| 514 | // Initialize as requested from some part of ASan runtime library (interceptors, |
| 515 | // allocator, etc). |
| 516 | void AsanInitFromRtl() { |
| 517 | AsanInitInternal(); |
| 518 | } |
| 519 | |
| 520 | #if ASAN_DYNAMIC |
| 521 | // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 522 | // (and thus normal initializers from .preinit_array or modules haven't run). |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 523 | |
| 524 | class AsanInitializer { |
| 525 | public: // NOLINT |
| 526 | AsanInitializer() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 527 | AsanInitFromRtl(); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 528 | } |
| 529 | }; |
| 530 | |
| 531 | static AsanInitializer asan_initializer; |
| 532 | #endif // ASAN_DYNAMIC |
| 533 | |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 534 | } // namespace __asan |
| 535 | |
Kostya Serebryany | 4803ab9 | 2012-01-09 18:53:15 +0000 | [diff] [blame] | 536 | // ---------------------- Interface ---------------- {{{1 |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 537 | using namespace __asan; // NOLINT |
| 538 | |
Alexander Potapenko | 5a9938d | 2012-08-09 16:05:17 +0000 | [diff] [blame] | 539 | int NOINLINE __asan_set_error_exit_code(int exit_code) { |
Alexey Samsonov | cb8c4dc | 2012-07-09 14:36:04 +0000 | [diff] [blame] | 540 | int old = flags()->exitcode; |
| 541 | flags()->exitcode = exit_code; |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 542 | return old; |
| 543 | } |
| 544 | |
Alexander Potapenko | dadc45d | 2012-03-06 11:45:59 +0000 | [diff] [blame] | 545 | void NOINLINE __asan_handle_no_return() { |
Kostya Serebryany | f54b1f9 | 2012-02-08 21:33:27 +0000 | [diff] [blame] | 546 | int local_stack; |
Alexey Samsonov | 89c1384 | 2013-03-20 09:23:28 +0000 | [diff] [blame] | 547 | AsanThread *curr_thread = GetCurrentThread(); |
Kostya Serebryany | f54b1f9 | 2012-02-08 21:33:27 +0000 | [diff] [blame] | 548 | CHECK(curr_thread); |
Kostya Serebryany | f67ec2b | 2012-11-23 15:38:49 +0000 | [diff] [blame] | 549 | uptr PageSize = GetPageSizeCached(); |
Kostya Serebryany | 3f4c387 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 550 | uptr top = curr_thread->stack_top(); |
Kostya Serebryany | f67ec2b | 2012-11-23 15:38:49 +0000 | [diff] [blame] | 551 | uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1); |
Kostya Serebryany | 30e970f | 2013-05-22 08:54:30 +0000 | [diff] [blame] | 552 | static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M |
| 553 | if (top - bottom > kMaxExpectedCleanupSize) { |
| 554 | static bool reported_warning = false; |
| 555 | if (reported_warning) |
| 556 | return; |
| 557 | reported_warning = true; |
| 558 | Report("WARNING: ASan is ignoring requested __asan_handle_no_return: " |
| 559 | "stack top: %p; bottom %p; size: %p (%zd)\n" |
| 560 | "False positive error reports may follow\n" |
| 561 | "For details see " |
| 562 | "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n", |
| 563 | top, bottom, top - bottom, top - bottom); |
| 564 | return; |
| 565 | } |
Kostya Serebryany | f54b1f9 | 2012-02-08 21:33:27 +0000 | [diff] [blame] | 566 | PoisonShadow(bottom, top - bottom, 0); |
Kostya Serebryany | 89de457 | 2013-09-12 13:25:29 +0000 | [diff] [blame] | 567 | if (curr_thread->has_fake_stack()) |
| 568 | curr_thread->fake_stack()->HandleNoReturn(); |
Kostya Serebryany | f54b1f9 | 2012-02-08 21:33:27 +0000 | [diff] [blame] | 569 | } |
| 570 | |
Alexander Potapenko | 2f3f962 | 2012-03-01 14:39:21 +0000 | [diff] [blame] | 571 | void NOINLINE __asan_set_death_callback(void (*callback)(void)) { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 572 | SetUserDieCallback(callback); |
Kostya Serebryany | e1fe0fd | 2012-02-13 21:24:29 +0000 | [diff] [blame] | 573 | } |
| 574 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 575 | // Initialize as requested from instrumented application code. |
| 576 | // We use this call as a trigger to wake up ASan from deactivated state. |
Alexander Potapenko | fca72fd | 2012-05-25 15:37:16 +0000 | [diff] [blame] | 577 | void __asan_init() { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 578 | AsanActivate(); |
| 579 | AsanInitInternal(); |
Kostya Serebryany | 1e172b4 | 2011-11-30 01:07:02 +0000 | [diff] [blame] | 580 | } |