blob: a202abe4c89dc1a41d6b27b6042b326b29d61f79 [file] [log] [blame]
Alexey Samsonove5f58952012-06-04 13:50:10 +00001//===-- asan_rtl.cc -------------------------------------------------------===//
Kostya Serebryany1e172b42011-11-30 01:07:02 +00002//
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//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interceptors.h"
Kostya Serebryany230e52f2013-09-18 10:35:12 +000016#include "asan_interface_internal.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000017#include "asan_internal.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000018#include "asan_mapping.h"
Alexey Samsonov7e843492013-03-28 15:42:43 +000019#include "asan_poisoning.h"
Alexey Samsonove218beb2012-08-09 09:06:52 +000020#include "asan_report.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000021#include "asan_stack.h"
22#include "asan_stats.h"
23#include "asan_thread.h"
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000024#include "sanitizer_common/sanitizer_atomic.h"
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000025#include "sanitizer_common/sanitizer_flags.h"
Alexey Samsonov9552db72012-06-05 07:25:47 +000026#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov9c6e5302012-08-23 07:32:06 +000027#include "sanitizer_common/sanitizer_symbolizer.h"
Sergey Matveev71f04112013-05-21 14:15:35 +000028#include "lsan/lsan_common.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000029
Kostya Serebryany230e52f2013-09-18 10:35:12 +000030int __asan_option_detect_stack_use_after_return; // Global interface symbol.
31
Alexey Samsonov591616d2012-09-11 09:44:48 +000032namespace __asan {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000033
Kostya Serebryanye31eca92013-02-15 12:00:24 +000034uptr AsanMappingProfile[kAsanMappingProfileSize];
35
Alexey Samsonov591616d2012-09-11 09:44:48 +000036static void AsanDie() {
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000037 static atomic_uint32_t num_calls;
38 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000039 // Don't die twice - run a busy loop.
40 while (1) { }
41 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000042 if (flags()->sleep_before_dying) {
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +000043 Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000044 SleepForSeconds(flags()->sleep_before_dying);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000045 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +000046 if (flags()->unmap_shadow_on_exit) {
47 if (kMidMemBeg) {
48 UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
49 UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
50 } else {
51 UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
52 }
53 }
Alexey Samsonov47657ce2012-06-06 07:02:44 +000054 if (death_callback)
55 death_callback();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000056 if (flags()->abort_on_error)
Alexey Samsonov47657ce2012-06-06 07:02:44 +000057 Abort();
Alexey Samsonovf8822472013-02-20 13:54:32 +000058 internal__exit(flags()->exitcode);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000059}
60
Alexey Samsonov591616d2012-09-11 09:44:48 +000061static void AsanCheckFailed(const char *file, int line, const char *cond,
62 u64 v1, u64 v2) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000063 Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
Alexey Samsonov15a77612012-06-06 15:22:20 +000064 file, line, cond, (uptr)v1, (uptr)v2);
Alexander Potapenko8e23d272012-09-07 15:50:19 +000065 // FIXME: check for infinite recursion without a thread-local counter here.
Alexey Samsonov15a77612012-06-06 15:22:20 +000066 PRINT_CURRENT_STACK();
Alexey Samsonov570c2a02012-12-13 11:09:26 +000067 Die();
Alexey Samsonov15a77612012-06-06 15:22:20 +000068}
69
Kostya Serebryany1e172b42011-11-30 01:07:02 +000070// -------------------------- Flags ------------------------- {{{1
Sergey Matveev3f5528b2013-04-16 14:58:45 +000071static const int kDefaultMallocContextSize = 30;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000072
Kostya Serebryany16cc10d2013-04-11 18:36:04 +000073Flags asan_flags_dont_use_directly; // use via flags().
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000074
Alexey Samsonov6a08d292012-12-07 22:01:28 +000075static const char *MaybeCallAsanDefaultOptions() {
76 return (&__asan_default_options) ? __asan_default_options() : "";
77}
78
Alexey Samsonov36ea94d2013-02-19 13:14:48 +000079static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
80#ifdef ASAN_DEFAULT_OPTIONS
81// Stringize the macro value.
82# define ASAN_STRINGIZE(x) #x
83# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options)
84 return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS);
85#else
86 return "";
87#endif
88}
89
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000090static void ParseFlagsFromString(Flags *f, const char *str) {
Sergey Matveeved20ebe2013-05-06 11:27:58 +000091 ParseCommonFlagsFromString(str);
92 CHECK((uptr)common_flags()->malloc_context_size <= kStackTraceMax);
93
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000094 ParseFlag(str, &f->quarantine_size, "quarantine_size");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000095 ParseFlag(str, &f->redzone, "redzone");
Kostya Serebryanya27bdf72013-04-05 14:40:25 +000096 CHECK_GE(f->redzone, 16);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000097 CHECK(IsPowerOfTwo(f->redzone));
98
99 ParseFlag(str, &f->debug, "debug");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000100 ParseFlag(str, &f->report_globals, "report_globals");
Alexey Samsonov6e7dca72013-03-28 09:11:20 +0000101 ParseFlag(str, &f->check_initialization_order, "check_initialization_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000102
103 ParseFlag(str, &f->replace_str, "replace_str");
104 ParseFlag(str, &f->replace_intrin, "replace_intrin");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000105 ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
Kostya Serebryany230e52f2013-09-18 10:35:12 +0000106 ParseFlag(str, &f->detect_stack_use_after_return,
107 "detect_stack_use_after_return");
Kostya Serebryanye1c68c32013-09-27 11:37:23 +0000108 ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000109 ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000110 ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000111 ParseFlag(str, &f->exitcode, "exitcode");
112 ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
113 ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
114 ParseFlag(str, &f->handle_segv, "handle_segv");
Alexey Samsonov332bf332013-04-25 10:52:15 +0000115 ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000116 ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000117 ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
118 ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
119 ParseFlag(str, &f->abort_on_error, "abort_on_error");
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000120 ParseFlag(str, &f->print_stats, "print_stats");
121 ParseFlag(str, &f->print_legend, "print_legend");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000122 ParseFlag(str, &f->atexit, "atexit");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000123 ParseFlag(str, &f->disable_core, "disable_core");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000124 ParseFlag(str, &f->allow_reexec, "allow_reexec");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000125 ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
Kostya Serebryany73bad812012-12-20 11:54:21 +0000126 ParseFlag(str, &f->poison_heap, "poison_heap");
Kostya Serebryanycca8e782013-10-16 13:49:01 +0000127 ParseFlag(str, &f->poison_partial, "poison_partial");
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +0000128 ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000129 ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000130 ParseFlag(str, &f->strict_init_order, "strict_init_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000131}
132
133void InitializeFlags(Flags *f, const char *env) {
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000134 CommonFlags *cf = common_flags();
135 cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
Kostya Serebryanyb76ea0c2013-05-16 13:04:29 +0000136 cf->symbolize = true;
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000137 cf->malloc_context_size = kDefaultMallocContextSize;
138 cf->fast_unwind_on_fatal = false;
139 cf->fast_unwind_on_malloc = true;
140 cf->strip_path_prefix = "";
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +0000141 cf->handle_ioctl = false;
Evgeniy Stepanovb6246062013-06-25 13:50:44 +0000142 cf->log_path = 0;
Sergey Matveev62519eb2013-07-22 12:38:17 +0000143 cf->detect_leaks = false;
Sergey Matveev41f15402013-08-01 14:57:07 +0000144 cf->leak_check_at_exit = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000145
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000146 internal_memset(f, 0, sizeof(*f));
Evgeniy Stepanov7315c262012-09-07 12:13:52 +0000147 f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
Kostya Serebryanyb1971ca2013-04-04 11:32:49 +0000148 f->redzone = 16;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000149 f->debug = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000150 f->report_globals = 1;
Alexey Samsonov6f5427b2013-10-31 00:40:15 +0000151 f->check_initialization_order = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000152 f->replace_str = true;
153 f->replace_intrin = true;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000154 f->mac_ignore_invalid_free = false;
Kostya Serebryanyb0796022013-09-23 08:58:14 +0000155 f->detect_stack_use_after_return = false; // Also needs the compiler flag.
Kostya Serebryanye1c68c32013-09-27 11:37:23 +0000156 f->uar_stack_size_log = 0;
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000157 f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K.
158 f->malloc_fill_byte = 0xbe;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000159 f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
160 f->allow_user_poisoning = true;
161 f->sleep_before_dying = 0;
162 f->handle_segv = ASAN_NEEDS_SEGV;
Alexey Samsonov332bf332013-04-25 10:52:15 +0000163 f->allow_user_segv_handler = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000164 f->use_sigaltstack = false;
165 f->check_malloc_usable_size = true;
166 f->unmap_shadow_on_exit = false;
167 f->abort_on_error = false;
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000168 f->print_stats = false;
169 f->print_legend = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000170 f->atexit = false;
Kostya Serebryany5af39e52012-11-21 12:38:58 +0000171 f->disable_core = (SANITIZER_WORDSIZE == 64);
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000172 f->allow_reexec = true;
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000173 f->print_full_thread_history = true;
Kostya Serebryany73bad812012-12-20 11:54:21 +0000174 f->poison_heap = true;
Kostya Serebryanycca8e782013-10-16 13:49:01 +0000175 f->poison_partial = true;
Timur Iskhodzhanova0e78c92013-08-16 11:04:59 +0000176 // Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
177 // TODO(glider,timurrrr): Fix known issues and enable this back.
178 f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0);
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000179 f->strict_memcmp = true;
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000180 f->strict_init_order = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000181
Alexey Samsonov36ea94d2013-02-19 13:14:48 +0000182 // Override from compile definition.
183 ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
184
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000185 // Override from user-specified string.
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000186 ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000187 if (common_flags()->verbosity) {
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000188 Report("Using the defaults from __asan_default_options: %s\n",
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000189 MaybeCallAsanDefaultOptions());
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000190 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000191
192 // Override from command line.
193 ParseFlagsFromString(f, env);
Sergey Matveev71f04112013-05-21 14:15:35 +0000194
195#if !CAN_SANITIZE_LEAKS
Sergey Matveev62519eb2013-07-22 12:38:17 +0000196 if (cf->detect_leaks) {
Sergey Matveev71f04112013-05-21 14:15:35 +0000197 Report("%s: detect_leaks is not supported on this platform.\n",
198 SanitizerToolName);
Sergey Matveev62519eb2013-07-22 12:38:17 +0000199 cf->detect_leaks = false;
Sergey Matveev71f04112013-05-21 14:15:35 +0000200 }
201#endif
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000202}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000203
204// -------------------------- Globals --------------------- {{{1
205int asan_inited;
206bool asan_init_is_running;
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000207void (*death_callback)(void);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000208
209#if !ASAN_FIXED_MAPPING
210uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
211#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000212
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000213// -------------------------- Misc ---------------- {{{1
214void ShowStatsAndAbort() {
215 __asan_print_accumulated_stats();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000216 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000217}
218
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000219// ---------------------- mmap -------------------- {{{1
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000220// Reserve memory range [beg, end].
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000221static void ReserveShadowMemoryRange(uptr beg, uptr end) {
Kostya Serebryanya27bdf72013-04-05 14:40:25 +0000222 CHECK_EQ((beg % GetPageSizeCached()), 0);
223 CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000224 uptr size = end - beg + 1;
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000225 void *res = MmapFixedNoReserve(beg, size);
Alexander Potapenko5aabcb52012-09-07 15:34:40 +0000226 if (res != (void*)beg) {
227 Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
228 "Perhaps you're using ulimit -v\n", size);
229 Abort();
230 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000231}
232
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000233// --------------- LowLevelAllocateCallbac ---------- {{{1
234static void OnLowLevelAllocate(uptr ptr, uptr size) {
235 PoisonShadow(ptr, size, kAsanInternalHeapMagic);
Kostya Serebryanyb89567c2011-12-02 21:02:20 +0000236}
237
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000238// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000239// exported functions
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000240#define ASAN_REPORT_ERROR(type, is_write, size) \
Alexey Samsonov0a4c9062012-06-05 13:50:57 +0000241extern "C" NOINLINE INTERFACE_ATTRIBUTE \
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000242void __asan_report_ ## type ## size(uptr addr); \
243void __asan_report_ ## type ## size(uptr addr) { \
Kostya Serebryany9f311bb2012-03-15 01:36:00 +0000244 GET_CALLER_PC_BP_SP; \
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000245 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000246}
247
248ASAN_REPORT_ERROR(load, false, 1)
249ASAN_REPORT_ERROR(load, false, 2)
250ASAN_REPORT_ERROR(load, false, 4)
251ASAN_REPORT_ERROR(load, false, 8)
252ASAN_REPORT_ERROR(load, false, 16)
253ASAN_REPORT_ERROR(store, true, 1)
254ASAN_REPORT_ERROR(store, true, 2)
255ASAN_REPORT_ERROR(store, true, 4)
256ASAN_REPORT_ERROR(store, true, 8)
257ASAN_REPORT_ERROR(store, true, 16)
258
Kostya Serebryany366984e2013-02-19 11:30:25 +0000259#define ASAN_REPORT_ERROR_N(type, is_write) \
260extern "C" NOINLINE INTERFACE_ATTRIBUTE \
261void __asan_report_ ## type ## _n(uptr addr, uptr size); \
262void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
263 GET_CALLER_PC_BP_SP; \
264 __asan_report_error(pc, bp, sp, addr, is_write, size); \
265}
266
267ASAN_REPORT_ERROR_N(load, false)
268ASAN_REPORT_ERROR_N(store, true)
269
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000270// Force the linker to keep the symbols for various ASan interface functions.
271// We want to keep those in the executable in order to let the instrumented
272// dynamic libraries access the symbol even if it is not used by the executable
273// itself. This should help if the build system is removing dead code at link
274// time.
Alexander Potapenko3fe91352012-02-27 14:06:48 +0000275static NOINLINE void force_interface_symbols() {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000276 volatile int fake_condition = 0; // prevent dead condition elimination.
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000277 // __asan_report_* functions are noreturn, so we need a switch to prevent
278 // the compiler from removing any of them.
279 switch (fake_condition) {
280 case 1: __asan_report_load1(0); break;
281 case 2: __asan_report_load2(0); break;
282 case 3: __asan_report_load4(0); break;
283 case 4: __asan_report_load8(0); break;
284 case 5: __asan_report_load16(0); break;
285 case 6: __asan_report_store1(0); break;
286 case 7: __asan_report_store2(0); break;
287 case 8: __asan_report_store4(0); break;
288 case 9: __asan_report_store8(0); break;
289 case 10: __asan_report_store16(0); break;
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000290 case 12: __asan_register_globals(0, 0); break;
291 case 13: __asan_unregister_globals(0, 0); break;
292 case 14: __asan_set_death_callback(0); break;
293 case 15: __asan_set_error_report_callback(0); break;
294 case 16: __asan_handle_no_return(); break;
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000295 case 17: __asan_address_is_poisoned(0); break;
296 case 18: __asan_get_allocated_size(0); break;
297 case 19: __asan_get_current_allocated_bytes(); break;
298 case 20: __asan_get_estimated_allocated_size(0); break;
299 case 21: __asan_get_free_bytes(); break;
300 case 22: __asan_get_heap_size(); break;
301 case 23: __asan_get_ownership(0); break;
302 case 24: __asan_get_unmapped_bytes(); break;
303 case 25: __asan_poison_memory_region(0, 0); break;
304 case 26: __asan_unpoison_memory_region(0, 0); break;
305 case 27: __asan_set_error_exit_code(0); break;
Alexey Samsonov05e16a02013-03-26 13:06:12 +0000306 case 30: __asan_before_dynamic_init(0); break;
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000307 case 31: __asan_after_dynamic_init(); break;
308 case 32: __asan_poison_stack_memory(0, 0); break;
309 case 33: __asan_unpoison_stack_memory(0, 0); break;
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000310 case 34: __asan_region_is_poisoned(0, 0); break;
Kostya Serebryany17a7c672012-12-29 10:18:31 +0000311 case 35: __asan_describe_address(0); break;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000312 }
313}
314
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000315static void asan_atexit() {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000316 Printf("AddressSanitizer exit stats:\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000317 __asan_print_accumulated_stats();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000318 // Print AsanMappingProfile.
319 for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
320 if (AsanMappingProfile[i] == 0) continue;
321 Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
322 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000323}
324
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000325static void InitializeHighMemEnd() {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000326#if !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000327 kHighMemEnd = GetMaxVirtualAddress();
328 // Increase kHighMemEnd to make sure it's properly
329 // aligned together with kHighMemBeg:
330 kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1;
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000331#endif // !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000332 CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000333}
334
335static void ProtectGap(uptr a, uptr size) {
336 CHECK_EQ(a, (uptr)Mprotect(a, size));
337}
338
339static void PrintAddressSpaceLayout() {
340 Printf("|| `[%p, %p]` || HighMem ||\n",
341 (void*)kHighMemBeg, (void*)kHighMemEnd);
342 Printf("|| `[%p, %p]` || HighShadow ||\n",
343 (void*)kHighShadowBeg, (void*)kHighShadowEnd);
344 if (kMidMemBeg) {
345 Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
346 (void*)kShadowGap3Beg, (void*)kShadowGap3End);
347 Printf("|| `[%p, %p]` || MidMem ||\n",
348 (void*)kMidMemBeg, (void*)kMidMemEnd);
349 Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
350 (void*)kShadowGap2Beg, (void*)kShadowGap2End);
351 Printf("|| `[%p, %p]` || MidShadow ||\n",
352 (void*)kMidShadowBeg, (void*)kMidShadowEnd);
353 }
354 Printf("|| `[%p, %p]` || ShadowGap ||\n",
355 (void*)kShadowGapBeg, (void*)kShadowGapEnd);
356 if (kLowShadowBeg) {
357 Printf("|| `[%p, %p]` || LowShadow ||\n",
358 (void*)kLowShadowBeg, (void*)kLowShadowEnd);
359 Printf("|| `[%p, %p]` || LowMem ||\n",
360 (void*)kLowMemBeg, (void*)kLowMemEnd);
361 }
362 Printf("MemToShadow(shadow): %p %p %p %p",
363 (void*)MEM_TO_SHADOW(kLowShadowBeg),
364 (void*)MEM_TO_SHADOW(kLowShadowEnd),
365 (void*)MEM_TO_SHADOW(kHighShadowBeg),
366 (void*)MEM_TO_SHADOW(kHighShadowEnd));
367 if (kMidMemBeg) {
368 Printf(" %p %p",
369 (void*)MEM_TO_SHADOW(kMidShadowBeg),
370 (void*)MEM_TO_SHADOW(kMidShadowEnd));
371 }
372 Printf("\n");
373 Printf("red_zone=%zu\n", (uptr)flags()->redzone);
Kostya Serebryany34e3ed12013-09-10 13:16:26 +0000374 Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000375 Printf("malloc_context_size=%zu\n",
376 (uptr)common_flags()->malloc_context_size);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000377
378 Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
379 Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
380 Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
381 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
382 if (kMidMemBeg)
383 CHECK(kMidShadowBeg > kLowShadowEnd &&
384 kMidMemBeg > kMidShadowEnd &&
385 kHighShadowBeg > kMidMemEnd);
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000386}
387
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000388} // namespace __asan
389
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000390// ---------------------- Interface ---------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000391using namespace __asan; // NOLINT
392
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000393#if !SANITIZER_SUPPORTS_WEAK_HOOKS
394extern "C" {
Timur Iskhodzhanov3c80c6c2013-08-13 11:42:45 +0000395SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000396const char* __asan_default_options() { return ""; }
397} // extern "C"
398#endif
399
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000400int NOINLINE __asan_set_error_exit_code(int exit_code) {
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000401 int old = flags()->exitcode;
402 flags()->exitcode = exit_code;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000403 return old;
404}
405
Alexander Potapenkodadc45d2012-03-06 11:45:59 +0000406void NOINLINE __asan_handle_no_return() {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000407 int local_stack;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000408 AsanThread *curr_thread = GetCurrentThread();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000409 CHECK(curr_thread);
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000410 uptr PageSize = GetPageSizeCached();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000411 uptr top = curr_thread->stack_top();
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000412 uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
Kostya Serebryany30e970f2013-05-22 08:54:30 +0000413 static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
414 if (top - bottom > kMaxExpectedCleanupSize) {
415 static bool reported_warning = false;
416 if (reported_warning)
417 return;
418 reported_warning = true;
419 Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
420 "stack top: %p; bottom %p; size: %p (%zd)\n"
421 "False positive error reports may follow\n"
422 "For details see "
423 "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
424 top, bottom, top - bottom, top - bottom);
425 return;
426 }
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000427 PoisonShadow(bottom, top - bottom, 0);
Kostya Serebryany89de4572013-09-12 13:25:29 +0000428 if (curr_thread->has_fake_stack())
429 curr_thread->fake_stack()->HandleNoReturn();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000430}
431
Alexander Potapenko2f3f9622012-03-01 14:39:21 +0000432void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
Kostya Serebryanye1fe0fd2012-02-13 21:24:29 +0000433 death_callback = callback;
434}
435
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000436void __asan_init() {
437 if (asan_inited) return;
Kostya Serebryany859778a2013-01-31 14:11:21 +0000438 SanitizerToolName = "AddressSanitizer";
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000439 CHECK(!asan_init_is_running && "ASan init calls itself!");
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000440 asan_init_is_running = true;
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000441 InitializeHighMemEnd();
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000442
443 // Make sure we are not statically linked.
444 AsanDoesNotSupportStaticLinkage();
445
Alexey Samsonov591616d2012-09-11 09:44:48 +0000446 // Install tool-specific callbacks in sanitizer_common.
447 SetDieCallback(AsanDie);
448 SetCheckFailedCallback(AsanCheckFailed);
Kostya Serebryany283c2962012-08-28 11:34:40 +0000449 SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
450
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000451 // Initialize flags. This must be done early, because most of the
452 // initialization steps look at flags().
Alexey Samsonov3dbeabb2012-06-14 14:07:21 +0000453 const char *options = GetEnv("ASAN_OPTIONS");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000454 InitializeFlags(flags(), options);
Evgeniy Stepanovb6246062013-06-25 13:50:44 +0000455 __sanitizer_set_report_path(common_flags()->log_path);
Kostya Serebryany230e52f2013-09-18 10:35:12 +0000456 __asan_option_detect_stack_use_after_return =
457 flags()->detect_stack_use_after_return;
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000458
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000459 if (common_flags()->verbosity && options) {
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000460 Report("Parsed ASAN_OPTIONS: %s\n", options);
461 }
462
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000463 // Re-exec ourselves if we need to set additional env or command line args.
464 MaybeReexec();
465
Alexey Samsonov947fbd12012-08-27 14:04:54 +0000466 // Setup internal allocator callback.
467 SetLowLevelAllocateCallback(OnLowLevelAllocate);
468
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000469 InitializeAsanInterceptors();
470
471 ReplaceSystemMalloc();
Alexey Samsonov4d5f98d2012-04-06 08:21:08 +0000472 ReplaceOperatorsNewAndDelete();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000473
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000474 uptr shadow_start = kLowShadowBeg;
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000475 if (kLowShadowBeg)
476 shadow_start -= GetMmapGranularity();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000477 bool full_shadow_is_available =
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000478 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000479
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +0000480#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000481 if (!full_shadow_is_available) {
482 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
Kostya Serebryany13577fe2013-02-28 12:28:37 +0000483 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000484 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000485#endif
486
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000487 if (common_flags()->verbosity)
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000488 PrintAddressSpaceLayout();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000489
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000490 if (flags()->disable_core) {
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000491 DisableCoreDumper();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000492 }
493
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000494 if (full_shadow_is_available) {
495 // mmap the low shadow plus at least one page at the left.
496 if (kLowShadowBeg)
497 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000498 // mmap the high shadow.
499 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000500 // protect the gap.
501 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
502 } else if (kMidMemBeg &&
503 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000504 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000505 CHECK(kLowShadowBeg != kLowShadowEnd);
506 // mmap the low shadow plus at least one page at the left.
507 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
508 // mmap the mid shadow.
509 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
510 // mmap the high shadow.
511 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
512 // protect the gaps.
513 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
514 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
515 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
Alexander Potapenkoc50e8352012-02-13 15:11:23 +0000516 } else {
517 Report("Shadow memory range interleaves with an existing memory mapping. "
518 "ASan cannot proceed correctly. ABORTING.\n");
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000519 DumpProcessMap();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000520 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000521 }
522
Kostya Serebryany13521a22013-10-17 13:18:21 +0000523 AsanTSDInit(PlatformTSDDtor);
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000524 InstallSignalHandlers();
Alexey Samsonovd64bcf42013-06-11 08:13:36 +0000525
Alexey Samsonovd64bcf42013-06-11 08:13:36 +0000526 // Allocator should be initialized before starting external symbolizer, as
527 // fork() on Mac locks the allocator.
528 InitializeAllocator();
529
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000530 // Start symbolizer process if necessary.
Peter Collingbournec1a1ed62013-10-25 23:03:29 +0000531 if (common_flags()->symbolize) {
532 Symbolizer::Init(common_flags()->external_symbolizer_path);
533 } else {
534 Symbolizer::Disable();
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000535 }
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000536
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000537 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
538 // should be set to 1 prior to initializing the threads.
539 asan_inited = 1;
540 asan_init_is_running = false;
541
Kostya Serebryanya2e70d92013-10-18 07:57:59 +0000542 if (flags()->atexit)
543 Atexit(asan_atexit);
544
545 // interceptors
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000546 InitTlsSize();
547
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000548 // Create main thread.
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000549 AsanThread *main_thread = AsanThread::Create(0, 0);
550 CreateThreadContextArgs create_main_args = { main_thread, 0 };
551 u32 main_tid = asanThreadRegistry().CreateThread(
552 0, true, 0, &create_main_args);
553 CHECK_EQ(0, main_tid);
554 SetCurrentThread(main_thread);
Peter Collingbourne0b694fc2013-05-17 16:56:53 +0000555 main_thread->ThreadStart(internal_getpid());
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000556 force_interface_symbols(); // no-op.
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000557
Alexey Samsonov975a3292013-05-22 13:20:37 +0000558#if CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000559 __lsan::InitCommonLsan();
Sergey Matveev41f15402013-08-01 14:57:07 +0000560 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
Sergey Matveev4cacb4f2013-05-21 17:56:45 +0000561 Atexit(__lsan::DoLeakCheck);
562 }
Alexey Samsonov975a3292013-05-22 13:20:37 +0000563#endif // CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000564
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000565 if (common_flags()->verbosity) {
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000566 Report("AddressSanitizer Init done\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000567 }
568}