blob: 11f05954d31ea0ac7633ef130a110b127104974e [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");
Bob Wilsondbd69cc2013-11-15 07:18:15 +0000123 ParseFlag(str, &f->coverage, "coverage");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000124 ParseFlag(str, &f->disable_core, "disable_core");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000125 ParseFlag(str, &f->allow_reexec, "allow_reexec");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000126 ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
Kostya Serebryany73bad812012-12-20 11:54:21 +0000127 ParseFlag(str, &f->poison_heap, "poison_heap");
Kostya Serebryanycca8e782013-10-16 13:49:01 +0000128 ParseFlag(str, &f->poison_partial, "poison_partial");
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +0000129 ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000130 ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000131 ParseFlag(str, &f->strict_init_order, "strict_init_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000132}
133
134void InitializeFlags(Flags *f, const char *env) {
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000135 CommonFlags *cf = common_flags();
Alexey Samsonov55c79472013-11-12 13:59:08 +0000136 SetCommonFlagDefaults();
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000137 cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000138 cf->malloc_context_size = kDefaultMallocContextSize;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000139
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000140 internal_memset(f, 0, sizeof(*f));
Evgeniy Stepanov7315c262012-09-07 12:13:52 +0000141 f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
Kostya Serebryanyb1971ca2013-04-04 11:32:49 +0000142 f->redzone = 16;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000143 f->debug = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000144 f->report_globals = 1;
Alexey Samsonove9e2b7f2013-11-06 04:27:09 +0000145 f->check_initialization_order = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000146 f->replace_str = true;
147 f->replace_intrin = true;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000148 f->mac_ignore_invalid_free = false;
Kostya Serebryanyb0796022013-09-23 08:58:14 +0000149 f->detect_stack_use_after_return = false; // Also needs the compiler flag.
Kostya Serebryanye1c68c32013-09-27 11:37:23 +0000150 f->uar_stack_size_log = 0;
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000151 f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K.
152 f->malloc_fill_byte = 0xbe;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000153 f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
154 f->allow_user_poisoning = true;
155 f->sleep_before_dying = 0;
156 f->handle_segv = ASAN_NEEDS_SEGV;
Alexey Samsonov332bf332013-04-25 10:52:15 +0000157 f->allow_user_segv_handler = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000158 f->use_sigaltstack = false;
159 f->check_malloc_usable_size = true;
160 f->unmap_shadow_on_exit = false;
161 f->abort_on_error = false;
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000162 f->print_stats = false;
163 f->print_legend = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000164 f->atexit = false;
Bob Wilsondbd69cc2013-11-15 07:18:15 +0000165 f->coverage = false;
Kostya Serebryany5af39e52012-11-21 12:38:58 +0000166 f->disable_core = (SANITIZER_WORDSIZE == 64);
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000167 f->allow_reexec = true;
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000168 f->print_full_thread_history = true;
Kostya Serebryany73bad812012-12-20 11:54:21 +0000169 f->poison_heap = true;
Kostya Serebryanycca8e782013-10-16 13:49:01 +0000170 f->poison_partial = true;
Timur Iskhodzhanova0e78c92013-08-16 11:04:59 +0000171 // Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
172 // TODO(glider,timurrrr): Fix known issues and enable this back.
173 f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0);
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000174 f->strict_memcmp = true;
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000175 f->strict_init_order = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000176
Alexey Samsonov36ea94d2013-02-19 13:14:48 +0000177 // Override from compile definition.
178 ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
179
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000180 // Override from user-specified string.
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000181 ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000182 if (common_flags()->verbosity) {
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000183 Report("Using the defaults from __asan_default_options: %s\n",
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000184 MaybeCallAsanDefaultOptions());
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000185 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000186
187 // Override from command line.
188 ParseFlagsFromString(f, env);
Sergey Matveev71f04112013-05-21 14:15:35 +0000189
190#if !CAN_SANITIZE_LEAKS
Sergey Matveev62519eb2013-07-22 12:38:17 +0000191 if (cf->detect_leaks) {
Sergey Matveev71f04112013-05-21 14:15:35 +0000192 Report("%s: detect_leaks is not supported on this platform.\n",
193 SanitizerToolName);
Sergey Matveev62519eb2013-07-22 12:38:17 +0000194 cf->detect_leaks = false;
Sergey Matveev71f04112013-05-21 14:15:35 +0000195 }
196#endif
Alexey Samsonove9e2b7f2013-11-06 04:27:09 +0000197
198 // Make "strict_init_order" imply "check_initialization_order".
199 // TODO(samsonov): Use a single runtime flag for an init-order checker.
200 if (f->strict_init_order) {
201 f->check_initialization_order = true;
202 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000203}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000204
205// -------------------------- Globals --------------------- {{{1
206int asan_inited;
207bool asan_init_is_running;
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000208void (*death_callback)(void);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000209
210#if !ASAN_FIXED_MAPPING
211uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
212#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000213
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000214// -------------------------- Misc ---------------- {{{1
215void ShowStatsAndAbort() {
216 __asan_print_accumulated_stats();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000217 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000218}
219
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000220// ---------------------- mmap -------------------- {{{1
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000221// Reserve memory range [beg, end].
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000222static void ReserveShadowMemoryRange(uptr beg, uptr end) {
Kostya Serebryanya27bdf72013-04-05 14:40:25 +0000223 CHECK_EQ((beg % GetPageSizeCached()), 0);
224 CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000225 uptr size = end - beg + 1;
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000226 void *res = MmapFixedNoReserve(beg, size);
Alexander Potapenko5aabcb52012-09-07 15:34:40 +0000227 if (res != (void*)beg) {
228 Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
229 "Perhaps you're using ulimit -v\n", size);
230 Abort();
231 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000232}
233
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000234// --------------- LowLevelAllocateCallbac ---------- {{{1
235static void OnLowLevelAllocate(uptr ptr, uptr size) {
236 PoisonShadow(ptr, size, kAsanInternalHeapMagic);
Kostya Serebryanyb89567c2011-12-02 21:02:20 +0000237}
238
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000239// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000240// exported functions
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000241#define ASAN_REPORT_ERROR(type, is_write, size) \
Alexey Samsonov0a4c9062012-06-05 13:50:57 +0000242extern "C" NOINLINE INTERFACE_ATTRIBUTE \
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000243void __asan_report_ ## type ## size(uptr addr); \
244void __asan_report_ ## type ## size(uptr addr) { \
Kostya Serebryany9f311bb2012-03-15 01:36:00 +0000245 GET_CALLER_PC_BP_SP; \
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000246 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000247}
248
249ASAN_REPORT_ERROR(load, false, 1)
250ASAN_REPORT_ERROR(load, false, 2)
251ASAN_REPORT_ERROR(load, false, 4)
252ASAN_REPORT_ERROR(load, false, 8)
253ASAN_REPORT_ERROR(load, false, 16)
254ASAN_REPORT_ERROR(store, true, 1)
255ASAN_REPORT_ERROR(store, true, 2)
256ASAN_REPORT_ERROR(store, true, 4)
257ASAN_REPORT_ERROR(store, true, 8)
258ASAN_REPORT_ERROR(store, true, 16)
259
Kostya Serebryany366984e2013-02-19 11:30:25 +0000260#define ASAN_REPORT_ERROR_N(type, is_write) \
261extern "C" NOINLINE INTERFACE_ATTRIBUTE \
262void __asan_report_ ## type ## _n(uptr addr, uptr size); \
263void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
264 GET_CALLER_PC_BP_SP; \
265 __asan_report_error(pc, bp, sp, addr, is_write, size); \
266}
267
268ASAN_REPORT_ERROR_N(load, false)
269ASAN_REPORT_ERROR_N(store, true)
270
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000271// Force the linker to keep the symbols for various ASan interface functions.
272// We want to keep those in the executable in order to let the instrumented
273// dynamic libraries access the symbol even if it is not used by the executable
274// itself. This should help if the build system is removing dead code at link
275// time.
Alexander Potapenko3fe91352012-02-27 14:06:48 +0000276static NOINLINE void force_interface_symbols() {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000277 volatile int fake_condition = 0; // prevent dead condition elimination.
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000278 // __asan_report_* functions are noreturn, so we need a switch to prevent
279 // the compiler from removing any of them.
280 switch (fake_condition) {
281 case 1: __asan_report_load1(0); break;
282 case 2: __asan_report_load2(0); break;
283 case 3: __asan_report_load4(0); break;
284 case 4: __asan_report_load8(0); break;
285 case 5: __asan_report_load16(0); break;
286 case 6: __asan_report_store1(0); break;
287 case 7: __asan_report_store2(0); break;
288 case 8: __asan_report_store4(0); break;
289 case 9: __asan_report_store8(0); break;
290 case 10: __asan_report_store16(0); break;
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000291 case 12: __asan_register_globals(0, 0); break;
292 case 13: __asan_unregister_globals(0, 0); break;
293 case 14: __asan_set_death_callback(0); break;
294 case 15: __asan_set_error_report_callback(0); break;
295 case 16: __asan_handle_no_return(); break;
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000296 case 17: __asan_address_is_poisoned(0); break;
297 case 18: __asan_get_allocated_size(0); break;
298 case 19: __asan_get_current_allocated_bytes(); break;
299 case 20: __asan_get_estimated_allocated_size(0); break;
300 case 21: __asan_get_free_bytes(); break;
301 case 22: __asan_get_heap_size(); break;
302 case 23: __asan_get_ownership(0); break;
303 case 24: __asan_get_unmapped_bytes(); break;
304 case 25: __asan_poison_memory_region(0, 0); break;
305 case 26: __asan_unpoison_memory_region(0, 0); break;
306 case 27: __asan_set_error_exit_code(0); break;
Alexey Samsonov05e16a02013-03-26 13:06:12 +0000307 case 30: __asan_before_dynamic_init(0); break;
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000308 case 31: __asan_after_dynamic_init(); break;
309 case 32: __asan_poison_stack_memory(0, 0); break;
310 case 33: __asan_unpoison_stack_memory(0, 0); break;
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000311 case 34: __asan_region_is_poisoned(0, 0); break;
Kostya Serebryany17a7c672012-12-29 10:18:31 +0000312 case 35: __asan_describe_address(0); break;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000313 }
314}
315
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000316static void asan_atexit() {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000317 Printf("AddressSanitizer exit stats:\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000318 __asan_print_accumulated_stats();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000319 // Print AsanMappingProfile.
320 for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
321 if (AsanMappingProfile[i] == 0) continue;
322 Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
323 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000324}
325
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000326static void InitializeHighMemEnd() {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000327#if !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000328 kHighMemEnd = GetMaxVirtualAddress();
329 // Increase kHighMemEnd to make sure it's properly
330 // aligned together with kHighMemBeg:
331 kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1;
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000332#endif // !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000333 CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000334}
335
336static void ProtectGap(uptr a, uptr size) {
337 CHECK_EQ(a, (uptr)Mprotect(a, size));
338}
339
340static void PrintAddressSpaceLayout() {
341 Printf("|| `[%p, %p]` || HighMem ||\n",
342 (void*)kHighMemBeg, (void*)kHighMemEnd);
343 Printf("|| `[%p, %p]` || HighShadow ||\n",
344 (void*)kHighShadowBeg, (void*)kHighShadowEnd);
345 if (kMidMemBeg) {
346 Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
347 (void*)kShadowGap3Beg, (void*)kShadowGap3End);
348 Printf("|| `[%p, %p]` || MidMem ||\n",
349 (void*)kMidMemBeg, (void*)kMidMemEnd);
350 Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
351 (void*)kShadowGap2Beg, (void*)kShadowGap2End);
352 Printf("|| `[%p, %p]` || MidShadow ||\n",
353 (void*)kMidShadowBeg, (void*)kMidShadowEnd);
354 }
355 Printf("|| `[%p, %p]` || ShadowGap ||\n",
356 (void*)kShadowGapBeg, (void*)kShadowGapEnd);
357 if (kLowShadowBeg) {
358 Printf("|| `[%p, %p]` || LowShadow ||\n",
359 (void*)kLowShadowBeg, (void*)kLowShadowEnd);
360 Printf("|| `[%p, %p]` || LowMem ||\n",
361 (void*)kLowMemBeg, (void*)kLowMemEnd);
362 }
363 Printf("MemToShadow(shadow): %p %p %p %p",
364 (void*)MEM_TO_SHADOW(kLowShadowBeg),
365 (void*)MEM_TO_SHADOW(kLowShadowEnd),
366 (void*)MEM_TO_SHADOW(kHighShadowBeg),
367 (void*)MEM_TO_SHADOW(kHighShadowEnd));
368 if (kMidMemBeg) {
369 Printf(" %p %p",
370 (void*)MEM_TO_SHADOW(kMidShadowBeg),
371 (void*)MEM_TO_SHADOW(kMidShadowEnd));
372 }
373 Printf("\n");
374 Printf("red_zone=%zu\n", (uptr)flags()->redzone);
Kostya Serebryany34e3ed12013-09-10 13:16:26 +0000375 Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000376 Printf("malloc_context_size=%zu\n",
377 (uptr)common_flags()->malloc_context_size);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000378
379 Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
380 Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
381 Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
382 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
383 if (kMidMemBeg)
384 CHECK(kMidShadowBeg > kLowShadowEnd &&
385 kMidMemBeg > kMidShadowEnd &&
386 kHighShadowBeg > kMidMemEnd);
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000387}
388
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000389} // namespace __asan
390
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000391// ---------------------- Interface ---------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000392using namespace __asan; // NOLINT
393
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000394#if !SANITIZER_SUPPORTS_WEAK_HOOKS
395extern "C" {
Timur Iskhodzhanov3c80c6c2013-08-13 11:42:45 +0000396SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000397const char* __asan_default_options() { return ""; }
398} // extern "C"
399#endif
400
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000401int NOINLINE __asan_set_error_exit_code(int exit_code) {
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000402 int old = flags()->exitcode;
403 flags()->exitcode = exit_code;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000404 return old;
405}
406
Alexander Potapenkodadc45d2012-03-06 11:45:59 +0000407void NOINLINE __asan_handle_no_return() {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000408 int local_stack;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000409 AsanThread *curr_thread = GetCurrentThread();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000410 CHECK(curr_thread);
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000411 uptr PageSize = GetPageSizeCached();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000412 uptr top = curr_thread->stack_top();
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000413 uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
Kostya Serebryany30e970f2013-05-22 08:54:30 +0000414 static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
415 if (top - bottom > kMaxExpectedCleanupSize) {
416 static bool reported_warning = false;
417 if (reported_warning)
418 return;
419 reported_warning = true;
420 Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
421 "stack top: %p; bottom %p; size: %p (%zd)\n"
422 "False positive error reports may follow\n"
423 "For details see "
424 "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
425 top, bottom, top - bottom, top - bottom);
426 return;
427 }
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000428 PoisonShadow(bottom, top - bottom, 0);
Kostya Serebryany89de4572013-09-12 13:25:29 +0000429 if (curr_thread->has_fake_stack())
430 curr_thread->fake_stack()->HandleNoReturn();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000431}
432
Alexander Potapenko2f3f9622012-03-01 14:39:21 +0000433void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
Kostya Serebryanye1fe0fd2012-02-13 21:24:29 +0000434 death_callback = callback;
435}
436
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000437void __asan_init() {
438 if (asan_inited) return;
Kostya Serebryany859778a2013-01-31 14:11:21 +0000439 SanitizerToolName = "AddressSanitizer";
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000440 CHECK(!asan_init_is_running && "ASan init calls itself!");
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000441 asan_init_is_running = true;
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000442 InitializeHighMemEnd();
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000443
444 // Make sure we are not statically linked.
445 AsanDoesNotSupportStaticLinkage();
446
Alexey Samsonov591616d2012-09-11 09:44:48 +0000447 // Install tool-specific callbacks in sanitizer_common.
448 SetDieCallback(AsanDie);
449 SetCheckFailedCallback(AsanCheckFailed);
Kostya Serebryany283c2962012-08-28 11:34:40 +0000450 SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
451
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000452 // Initialize flags. This must be done early, because most of the
453 // initialization steps look at flags().
Alexey Samsonov3dbeabb2012-06-14 14:07:21 +0000454 const char *options = GetEnv("ASAN_OPTIONS");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000455 InitializeFlags(flags(), options);
Evgeniy Stepanovb6246062013-06-25 13:50:44 +0000456 __sanitizer_set_report_path(common_flags()->log_path);
Kostya Serebryany230e52f2013-09-18 10:35:12 +0000457 __asan_option_detect_stack_use_after_return =
458 flags()->detect_stack_use_after_return;
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000459
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000460 if (common_flags()->verbosity && options) {
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000461 Report("Parsed ASAN_OPTIONS: %s\n", options);
462 }
463
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000464 // Re-exec ourselves if we need to set additional env or command line args.
465 MaybeReexec();
466
Alexey Samsonov947fbd12012-08-27 14:04:54 +0000467 // Setup internal allocator callback.
468 SetLowLevelAllocateCallback(OnLowLevelAllocate);
469
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000470 InitializeAsanInterceptors();
471
472 ReplaceSystemMalloc();
Alexey Samsonov4d5f98d2012-04-06 08:21:08 +0000473 ReplaceOperatorsNewAndDelete();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000474
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000475 uptr shadow_start = kLowShadowBeg;
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000476 if (kLowShadowBeg)
477 shadow_start -= GetMmapGranularity();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000478 bool full_shadow_is_available =
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000479 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000480
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +0000481#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000482 if (!full_shadow_is_available) {
483 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
Kostya Serebryany13577fe2013-02-28 12:28:37 +0000484 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000485 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000486#endif
487
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000488 if (common_flags()->verbosity)
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000489 PrintAddressSpaceLayout();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000490
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000491 if (flags()->disable_core) {
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000492 DisableCoreDumper();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000493 }
494
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000495 if (full_shadow_is_available) {
496 // mmap the low shadow plus at least one page at the left.
497 if (kLowShadowBeg)
498 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000499 // mmap the high shadow.
500 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000501 // protect the gap.
502 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
503 } else if (kMidMemBeg &&
504 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000505 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000506 CHECK(kLowShadowBeg != kLowShadowEnd);
507 // mmap the low shadow plus at least one page at the left.
508 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
509 // mmap the mid shadow.
510 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
511 // mmap the high shadow.
512 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
513 // protect the gaps.
514 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
515 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
516 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
Alexander Potapenkoc50e8352012-02-13 15:11:23 +0000517 } else {
518 Report("Shadow memory range interleaves with an existing memory mapping. "
519 "ASan cannot proceed correctly. ABORTING.\n");
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000520 DumpProcessMap();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000521 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000522 }
523
Kostya Serebryany13521a22013-10-17 13:18:21 +0000524 AsanTSDInit(PlatformTSDDtor);
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000525 InstallSignalHandlers();
Alexey Samsonovd64bcf42013-06-11 08:13:36 +0000526
Alexey Samsonovd64bcf42013-06-11 08:13:36 +0000527 // Allocator should be initialized before starting external symbolizer, as
528 // fork() on Mac locks the allocator.
529 InitializeAllocator();
530
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000531 // Start symbolizer process if necessary.
Peter Collingbournec1a1ed62013-10-25 23:03:29 +0000532 if (common_flags()->symbolize) {
533 Symbolizer::Init(common_flags()->external_symbolizer_path);
534 } else {
535 Symbolizer::Disable();
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000536 }
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000537
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000538 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
539 // should be set to 1 prior to initializing the threads.
540 asan_inited = 1;
541 asan_init_is_running = false;
542
Kostya Serebryanya2e70d92013-10-18 07:57:59 +0000543 if (flags()->atexit)
544 Atexit(asan_atexit);
545
Bob Wilsondbd69cc2013-11-15 07:18:15 +0000546 if (flags()->coverage)
547 Atexit(__sanitizer_cov_dump);
548
Kostya Serebryanya2e70d92013-10-18 07:57:59 +0000549 // interceptors
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000550 InitTlsSize();
551
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000552 // Create main thread.
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000553 AsanThread *main_thread = AsanThread::Create(0, 0);
554 CreateThreadContextArgs create_main_args = { main_thread, 0 };
555 u32 main_tid = asanThreadRegistry().CreateThread(
556 0, true, 0, &create_main_args);
557 CHECK_EQ(0, main_tid);
558 SetCurrentThread(main_thread);
Peter Collingbourne0b694fc2013-05-17 16:56:53 +0000559 main_thread->ThreadStart(internal_getpid());
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000560 force_interface_symbols(); // no-op.
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000561
Alexey Samsonov975a3292013-05-22 13:20:37 +0000562#if CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000563 __lsan::InitCommonLsan();
Sergey Matveev41f15402013-08-01 14:57:07 +0000564 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
Sergey Matveev4cacb4f2013-05-21 17:56:45 +0000565 Atexit(__lsan::DoLeakCheck);
566 }
Alexey Samsonov975a3292013-05-22 13:20:37 +0000567#endif // CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000568
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000569 if (common_flags()->verbosity) {
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000570 Report("AddressSanitizer Init done\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000571 }
572}