blob: 80bd5918013d696e03a9733f53863ff586837fa4 [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 Serebryany1e172b42011-11-30 01:07:02 +000016#include "asan_internal.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000017#include "asan_mapping.h"
Alexey Samsonov7e843492013-03-28 15:42:43 +000018#include "asan_poisoning.h"
Alexey Samsonove218beb2012-08-09 09:06:52 +000019#include "asan_report.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000020#include "asan_stack.h"
21#include "asan_stats.h"
22#include "asan_thread.h"
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000023#include "sanitizer_common/sanitizer_atomic.h"
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000024#include "sanitizer_common/sanitizer_flags.h"
Alexey Samsonov9552db72012-06-05 07:25:47 +000025#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov9c6e5302012-08-23 07:32:06 +000026#include "sanitizer_common/sanitizer_symbolizer.h"
Sergey Matveev71f04112013-05-21 14:15:35 +000027#include "lsan/lsan_common.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000028
Alexey Samsonov591616d2012-09-11 09:44:48 +000029namespace __asan {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000030
Kostya Serebryanye31eca92013-02-15 12:00:24 +000031uptr AsanMappingProfile[kAsanMappingProfileSize];
32
Alexey Samsonov591616d2012-09-11 09:44:48 +000033static void AsanDie() {
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000034 static atomic_uint32_t num_calls;
35 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000036 // Don't die twice - run a busy loop.
37 while (1) { }
38 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000039 if (flags()->sleep_before_dying) {
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +000040 Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000041 SleepForSeconds(flags()->sleep_before_dying);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000042 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +000043 if (flags()->unmap_shadow_on_exit) {
44 if (kMidMemBeg) {
45 UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
46 UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
47 } else {
48 UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
49 }
50 }
Alexey Samsonov47657ce2012-06-06 07:02:44 +000051 if (death_callback)
52 death_callback();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000053 if (flags()->abort_on_error)
Alexey Samsonov47657ce2012-06-06 07:02:44 +000054 Abort();
Alexey Samsonovf8822472013-02-20 13:54:32 +000055 internal__exit(flags()->exitcode);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000056}
57
Alexey Samsonov591616d2012-09-11 09:44:48 +000058static void AsanCheckFailed(const char *file, int line, const char *cond,
59 u64 v1, u64 v2) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000060 Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
Alexey Samsonov15a77612012-06-06 15:22:20 +000061 file, line, cond, (uptr)v1, (uptr)v2);
Alexander Potapenko8e23d272012-09-07 15:50:19 +000062 // FIXME: check for infinite recursion without a thread-local counter here.
Alexey Samsonov15a77612012-06-06 15:22:20 +000063 PRINT_CURRENT_STACK();
Alexey Samsonov570c2a02012-12-13 11:09:26 +000064 Die();
Alexey Samsonov15a77612012-06-06 15:22:20 +000065}
66
Kostya Serebryany1e172b42011-11-30 01:07:02 +000067// -------------------------- Flags ------------------------- {{{1
Sergey Matveev3f5528b2013-04-16 14:58:45 +000068static const int kDefaultMallocContextSize = 30;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000069
Kostya Serebryany16cc10d2013-04-11 18:36:04 +000070Flags asan_flags_dont_use_directly; // use via flags().
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000071
Alexey Samsonov6a08d292012-12-07 22:01:28 +000072static const char *MaybeCallAsanDefaultOptions() {
73 return (&__asan_default_options) ? __asan_default_options() : "";
74}
75
Alexey Samsonov36ea94d2013-02-19 13:14:48 +000076static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
77#ifdef ASAN_DEFAULT_OPTIONS
78// Stringize the macro value.
79# define ASAN_STRINGIZE(x) #x
80# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options)
81 return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS);
82#else
83 return "";
84#endif
85}
86
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000087static void ParseFlagsFromString(Flags *f, const char *str) {
Sergey Matveeved20ebe2013-05-06 11:27:58 +000088 ParseCommonFlagsFromString(str);
89 CHECK((uptr)common_flags()->malloc_context_size <= kStackTraceMax);
90
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000091 ParseFlag(str, &f->quarantine_size, "quarantine_size");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000092 ParseFlag(str, &f->verbosity, "verbosity");
93 ParseFlag(str, &f->redzone, "redzone");
Kostya Serebryanya27bdf72013-04-05 14:40:25 +000094 CHECK_GE(f->redzone, 16);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000095 CHECK(IsPowerOfTwo(f->redzone));
96
97 ParseFlag(str, &f->debug, "debug");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000098 ParseFlag(str, &f->report_globals, "report_globals");
Alexey Samsonov6e7dca72013-03-28 09:11:20 +000099 ParseFlag(str, &f->check_initialization_order, "check_initialization_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000100
101 ParseFlag(str, &f->replace_str, "replace_str");
102 ParseFlag(str, &f->replace_intrin, "replace_intrin");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000103 ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
104 ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
105 ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000106 ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000107 ParseFlag(str, &f->exitcode, "exitcode");
108 ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
109 ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
110 ParseFlag(str, &f->handle_segv, "handle_segv");
Alexey Samsonov332bf332013-04-25 10:52:15 +0000111 ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000112 ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000113 ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
114 ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
115 ParseFlag(str, &f->abort_on_error, "abort_on_error");
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000116 ParseFlag(str, &f->print_stats, "print_stats");
117 ParseFlag(str, &f->print_legend, "print_legend");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000118 ParseFlag(str, &f->atexit, "atexit");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000119 ParseFlag(str, &f->disable_core, "disable_core");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000120 ParseFlag(str, &f->allow_reexec, "allow_reexec");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000121 ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
Kostya Serebryany73bad812012-12-20 11:54:21 +0000122 ParseFlag(str, &f->poison_heap, "poison_heap");
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +0000123 ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
Kostya Serebryany9e3bd382012-12-26 06:30:02 +0000124 ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000125 ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000126 ParseFlag(str, &f->strict_init_order, "strict_init_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000127}
128
129void InitializeFlags(Flags *f, const char *env) {
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000130 CommonFlags *cf = common_flags();
131 cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
Kostya Serebryanyb76ea0c2013-05-16 13:04:29 +0000132 cf->symbolize = true;
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000133 cf->malloc_context_size = kDefaultMallocContextSize;
134 cf->fast_unwind_on_fatal = false;
135 cf->fast_unwind_on_malloc = true;
136 cf->strip_path_prefix = "";
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +0000137 cf->handle_ioctl = false;
Evgeniy Stepanovb6246062013-06-25 13:50:44 +0000138 cf->log_path = 0;
Sergey Matveev62519eb2013-07-22 12:38:17 +0000139 cf->detect_leaks = false;
Sergey Matveev41f15402013-08-01 14:57:07 +0000140 cf->leak_check_at_exit = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000141
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000142 internal_memset(f, 0, sizeof(*f));
Evgeniy Stepanov7315c262012-09-07 12:13:52 +0000143 f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000144 f->verbosity = 0;
Kostya Serebryanyb1971ca2013-04-04 11:32:49 +0000145 f->redzone = 16;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000146 f->debug = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000147 f->report_globals = 1;
Alexey Samsonov566c0a12013-03-14 11:49:40 +0000148 f->check_initialization_order = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000149 f->replace_str = true;
150 f->replace_intrin = true;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000151 f->mac_ignore_invalid_free = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000152 f->use_fake_stack = true;
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000153 f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K.
154 f->malloc_fill_byte = 0xbe;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000155 f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
156 f->allow_user_poisoning = true;
157 f->sleep_before_dying = 0;
158 f->handle_segv = ASAN_NEEDS_SEGV;
Alexey Samsonov332bf332013-04-25 10:52:15 +0000159 f->allow_user_segv_handler = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000160 f->use_sigaltstack = false;
161 f->check_malloc_usable_size = true;
162 f->unmap_shadow_on_exit = false;
163 f->abort_on_error = false;
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000164 f->print_stats = false;
165 f->print_legend = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000166 f->atexit = false;
Kostya Serebryany5af39e52012-11-21 12:38:58 +0000167 f->disable_core = (SANITIZER_WORDSIZE == 64);
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000168 f->allow_reexec = true;
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000169 f->print_full_thread_history = true;
Kostya Serebryany73bad812012-12-20 11:54:21 +0000170 f->poison_heap = 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);
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000174 f->use_stack_depot = true;
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000175 f->strict_memcmp = true;
Alexey Samsonovdfeef672013-04-19 08:35:16 +0000176 f->strict_init_order = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000177
Alexey Samsonov36ea94d2013-02-19 13:14:48 +0000178 // Override from compile definition.
179 ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
180
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000181 // Override from user-specified string.
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000182 ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000183 if (flags()->verbosity) {
184 Report("Using the defaults from __asan_default_options: %s\n",
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000185 MaybeCallAsanDefaultOptions());
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000186 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000187
188 // Override from command line.
189 ParseFlagsFromString(f, env);
Sergey Matveev71f04112013-05-21 14:15:35 +0000190
191#if !CAN_SANITIZE_LEAKS
Sergey Matveev62519eb2013-07-22 12:38:17 +0000192 if (cf->detect_leaks) {
Sergey Matveev71f04112013-05-21 14:15:35 +0000193 Report("%s: detect_leaks is not supported on this platform.\n",
194 SanitizerToolName);
Sergey Matveev62519eb2013-07-22 12:38:17 +0000195 cf->detect_leaks = false;
Sergey Matveev71f04112013-05-21 14:15:35 +0000196 }
197#endif
198
Sergey Matveev62519eb2013-07-22 12:38:17 +0000199 if (cf->detect_leaks && !f->use_stack_depot) {
Sergey Matveev71f04112013-05-21 14:15:35 +0000200 Report("%s: detect_leaks is ignored (requires use_stack_depot).\n",
201 SanitizerToolName);
Sergey Matveev62519eb2013-07-22 12:38:17 +0000202 cf->detect_leaks = false;
Sergey Matveev71f04112013-05-21 14:15:35 +0000203 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000204}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000205
206// -------------------------- Globals --------------------- {{{1
207int asan_inited;
208bool asan_init_is_running;
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000209void (*death_callback)(void);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000210
211#if !ASAN_FIXED_MAPPING
212uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
213#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000214
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000215// -------------------------- Misc ---------------- {{{1
216void ShowStatsAndAbort() {
217 __asan_print_accumulated_stats();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000218 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000219}
220
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000221// ---------------------- mmap -------------------- {{{1
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000222// Reserve memory range [beg, end].
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000223static void ReserveShadowMemoryRange(uptr beg, uptr end) {
Kostya Serebryanya27bdf72013-04-05 14:40:25 +0000224 CHECK_EQ((beg % GetPageSizeCached()), 0);
225 CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000226 uptr size = end - beg + 1;
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000227 void *res = MmapFixedNoReserve(beg, size);
Alexander Potapenko5aabcb52012-09-07 15:34:40 +0000228 if (res != (void*)beg) {
229 Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
230 "Perhaps you're using ulimit -v\n", size);
231 Abort();
232 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000233}
234
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000235// --------------- LowLevelAllocateCallbac ---------- {{{1
236static void OnLowLevelAllocate(uptr ptr, uptr size) {
237 PoisonShadow(ptr, size, kAsanInternalHeapMagic);
Kostya Serebryanyb89567c2011-12-02 21:02:20 +0000238}
239
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000240// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000241// exported functions
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000242#define ASAN_REPORT_ERROR(type, is_write, size) \
Alexey Samsonov0a4c9062012-06-05 13:50:57 +0000243extern "C" NOINLINE INTERFACE_ATTRIBUTE \
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000244void __asan_report_ ## type ## size(uptr addr); \
245void __asan_report_ ## type ## size(uptr addr) { \
Kostya Serebryany9f311bb2012-03-15 01:36:00 +0000246 GET_CALLER_PC_BP_SP; \
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000247 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000248}
249
250ASAN_REPORT_ERROR(load, false, 1)
251ASAN_REPORT_ERROR(load, false, 2)
252ASAN_REPORT_ERROR(load, false, 4)
253ASAN_REPORT_ERROR(load, false, 8)
254ASAN_REPORT_ERROR(load, false, 16)
255ASAN_REPORT_ERROR(store, true, 1)
256ASAN_REPORT_ERROR(store, true, 2)
257ASAN_REPORT_ERROR(store, true, 4)
258ASAN_REPORT_ERROR(store, true, 8)
259ASAN_REPORT_ERROR(store, true, 16)
260
Kostya Serebryany366984e2013-02-19 11:30:25 +0000261#define ASAN_REPORT_ERROR_N(type, is_write) \
262extern "C" NOINLINE INTERFACE_ATTRIBUTE \
263void __asan_report_ ## type ## _n(uptr addr, uptr size); \
264void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
265 GET_CALLER_PC_BP_SP; \
266 __asan_report_error(pc, bp, sp, addr, is_write, size); \
267}
268
269ASAN_REPORT_ERROR_N(load, false)
270ASAN_REPORT_ERROR_N(store, true)
271
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000272// Force the linker to keep the symbols for various ASan interface functions.
273// We want to keep those in the executable in order to let the instrumented
274// dynamic libraries access the symbol even if it is not used by the executable
275// itself. This should help if the build system is removing dead code at link
276// time.
Alexander Potapenko3fe91352012-02-27 14:06:48 +0000277static NOINLINE void force_interface_symbols() {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000278 volatile int fake_condition = 0; // prevent dead condition elimination.
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000279 // __asan_report_* functions are noreturn, so we need a switch to prevent
280 // the compiler from removing any of them.
281 switch (fake_condition) {
282 case 1: __asan_report_load1(0); break;
283 case 2: __asan_report_load2(0); break;
284 case 3: __asan_report_load4(0); break;
285 case 4: __asan_report_load8(0); break;
286 case 5: __asan_report_load16(0); break;
287 case 6: __asan_report_store1(0); break;
288 case 7: __asan_report_store2(0); break;
289 case 8: __asan_report_store4(0); break;
290 case 9: __asan_report_store8(0); break;
291 case 10: __asan_report_store16(0); break;
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000292 case 12: __asan_register_globals(0, 0); break;
293 case 13: __asan_unregister_globals(0, 0); break;
294 case 14: __asan_set_death_callback(0); break;
295 case 15: __asan_set_error_report_callback(0); break;
296 case 16: __asan_handle_no_return(); break;
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000297 case 17: __asan_address_is_poisoned(0); break;
298 case 18: __asan_get_allocated_size(0); break;
299 case 19: __asan_get_current_allocated_bytes(); break;
300 case 20: __asan_get_estimated_allocated_size(0); break;
301 case 21: __asan_get_free_bytes(); break;
302 case 22: __asan_get_heap_size(); break;
303 case 23: __asan_get_ownership(0); break;
304 case 24: __asan_get_unmapped_bytes(); break;
305 case 25: __asan_poison_memory_region(0, 0); break;
306 case 26: __asan_unpoison_memory_region(0, 0); break;
307 case 27: __asan_set_error_exit_code(0); break;
Alexey Samsonov05e16a02013-03-26 13:06:12 +0000308 case 30: __asan_before_dynamic_init(0); break;
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000309 case 31: __asan_after_dynamic_init(); break;
310 case 32: __asan_poison_stack_memory(0, 0); break;
311 case 33: __asan_unpoison_stack_memory(0, 0); break;
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000312 case 34: __asan_region_is_poisoned(0, 0); break;
Kostya Serebryany17a7c672012-12-29 10:18:31 +0000313 case 35: __asan_describe_address(0); break;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000314 }
315}
316
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000317static void asan_atexit() {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000318 Printf("AddressSanitizer exit stats:\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000319 __asan_print_accumulated_stats();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000320 // Print AsanMappingProfile.
321 for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
322 if (AsanMappingProfile[i] == 0) continue;
323 Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
324 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000325}
326
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000327static void InitializeHighMemEnd() {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000328#if !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000329 kHighMemEnd = GetMaxVirtualAddress();
330 // Increase kHighMemEnd to make sure it's properly
331 // aligned together with kHighMemBeg:
332 kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1;
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000333#endif // !ASAN_FIXED_MAPPING
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000334 CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000335}
336
337static void ProtectGap(uptr a, uptr size) {
338 CHECK_EQ(a, (uptr)Mprotect(a, size));
339}
340
341static void PrintAddressSpaceLayout() {
342 Printf("|| `[%p, %p]` || HighMem ||\n",
343 (void*)kHighMemBeg, (void*)kHighMemEnd);
344 Printf("|| `[%p, %p]` || HighShadow ||\n",
345 (void*)kHighShadowBeg, (void*)kHighShadowEnd);
346 if (kMidMemBeg) {
347 Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
348 (void*)kShadowGap3Beg, (void*)kShadowGap3End);
349 Printf("|| `[%p, %p]` || MidMem ||\n",
350 (void*)kMidMemBeg, (void*)kMidMemEnd);
351 Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
352 (void*)kShadowGap2Beg, (void*)kShadowGap2End);
353 Printf("|| `[%p, %p]` || MidShadow ||\n",
354 (void*)kMidShadowBeg, (void*)kMidShadowEnd);
355 }
356 Printf("|| `[%p, %p]` || ShadowGap ||\n",
357 (void*)kShadowGapBeg, (void*)kShadowGapEnd);
358 if (kLowShadowBeg) {
359 Printf("|| `[%p, %p]` || LowShadow ||\n",
360 (void*)kLowShadowBeg, (void*)kLowShadowEnd);
361 Printf("|| `[%p, %p]` || LowMem ||\n",
362 (void*)kLowMemBeg, (void*)kLowMemEnd);
363 }
364 Printf("MemToShadow(shadow): %p %p %p %p",
365 (void*)MEM_TO_SHADOW(kLowShadowBeg),
366 (void*)MEM_TO_SHADOW(kLowShadowEnd),
367 (void*)MEM_TO_SHADOW(kHighShadowBeg),
368 (void*)MEM_TO_SHADOW(kHighShadowEnd));
369 if (kMidMemBeg) {
370 Printf(" %p %p",
371 (void*)MEM_TO_SHADOW(kMidShadowBeg),
372 (void*)MEM_TO_SHADOW(kMidShadowEnd));
373 }
374 Printf("\n");
375 Printf("red_zone=%zu\n", (uptr)flags()->redzone);
Kostya Serebryany34e3ed12013-09-10 13:16:26 +0000376 Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
Sergey Matveeved20ebe2013-05-06 11:27:58 +0000377 Printf("malloc_context_size=%zu\n",
378 (uptr)common_flags()->malloc_context_size);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000379
380 Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
381 Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
382 Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
383 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
384 if (kMidMemBeg)
385 CHECK(kMidShadowBeg > kLowShadowEnd &&
386 kMidMemBeg > kMidShadowEnd &&
387 kHighShadowBeg > kMidMemEnd);
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000388}
389
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000390} // namespace __asan
391
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000392// ---------------------- Interface ---------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000393using namespace __asan; // NOLINT
394
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000395#if !SANITIZER_SUPPORTS_WEAK_HOOKS
396extern "C" {
Timur Iskhodzhanov3c80c6c2013-08-13 11:42:45 +0000397SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000398const char* __asan_default_options() { return ""; }
399} // extern "C"
400#endif
401
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000402int NOINLINE __asan_set_error_exit_code(int exit_code) {
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000403 int old = flags()->exitcode;
404 flags()->exitcode = exit_code;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000405 return old;
406}
407
Alexander Potapenkodadc45d2012-03-06 11:45:59 +0000408void NOINLINE __asan_handle_no_return() {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000409 int local_stack;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000410 AsanThread *curr_thread = GetCurrentThread();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000411 CHECK(curr_thread);
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000412 uptr PageSize = GetPageSizeCached();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000413 uptr top = curr_thread->stack_top();
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000414 uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
Kostya Serebryany30e970f2013-05-22 08:54:30 +0000415 static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
416 if (top - bottom > kMaxExpectedCleanupSize) {
417 static bool reported_warning = false;
418 if (reported_warning)
419 return;
420 reported_warning = true;
421 Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
422 "stack top: %p; bottom %p; size: %p (%zd)\n"
423 "False positive error reports may follow\n"
424 "For details see "
425 "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
426 top, bottom, top - bottom, top - bottom);
427 return;
428 }
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000429 PoisonShadow(bottom, top - bottom, 0);
430}
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);
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000456
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000457 if (flags()->verbosity && options) {
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000458 Report("Parsed ASAN_OPTIONS: %s\n", options);
459 }
460
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000461 // Re-exec ourselves if we need to set additional env or command line args.
462 MaybeReexec();
463
Alexey Samsonov947fbd12012-08-27 14:04:54 +0000464 // Setup internal allocator callback.
465 SetLowLevelAllocateCallback(OnLowLevelAllocate);
466
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000467 if (flags()->atexit) {
Alexey Samsonovb823e3c2012-02-22 14:07:06 +0000468 Atexit(asan_atexit);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000469 }
470
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000471 // interceptors
472 InitializeAsanInterceptors();
473
474 ReplaceSystemMalloc();
Alexey Samsonov4d5f98d2012-04-06 08:21:08 +0000475 ReplaceOperatorsNewAndDelete();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000476
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000477 uptr shadow_start = kLowShadowBeg;
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000478 if (kLowShadowBeg)
479 shadow_start -= GetMmapGranularity();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000480 bool full_shadow_is_available =
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000481 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000482
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +0000483#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000484 if (!full_shadow_is_available) {
485 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
Kostya Serebryany13577fe2013-02-28 12:28:37 +0000486 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000487 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000488#endif
489
490 if (flags()->verbosity)
491 PrintAddressSpaceLayout();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000492
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000493 if (flags()->disable_core) {
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000494 DisableCoreDumper();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000495 }
496
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000497 if (full_shadow_is_available) {
498 // mmap the low shadow plus at least one page at the left.
499 if (kLowShadowBeg)
500 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000501 // mmap the high shadow.
502 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000503 // protect the gap.
504 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
505 } else if (kMidMemBeg &&
506 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
Timur Iskhodzhanovbb7f2d82013-07-16 09:47:39 +0000507 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000508 CHECK(kLowShadowBeg != kLowShadowEnd);
509 // mmap the low shadow plus at least one page at the left.
510 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
511 // mmap the mid shadow.
512 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
513 // mmap the high shadow.
514 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
515 // protect the gaps.
516 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
517 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
518 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
Alexander Potapenkoc50e8352012-02-13 15:11:23 +0000519 } else {
520 Report("Shadow memory range interleaves with an existing memory mapping. "
521 "ASan cannot proceed correctly. ABORTING.\n");
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000522 DumpProcessMap();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000523 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000524 }
525
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000526 InstallSignalHandlers();
Alexey Samsonovd64bcf42013-06-11 08:13:36 +0000527
528 AsanTSDInit(AsanThread::TSDDtor);
529 // Allocator should be initialized before starting external symbolizer, as
530 // fork() on Mac locks the allocator.
531 InitializeAllocator();
532
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000533 // Start symbolizer process if necessary.
Alexey Samsonov68c016a2013-09-03 13:22:51 +0000534 if (common_flags()->symbolize) {
Alexey Samsonov7847d772013-09-10 14:36:16 +0000535 getSymbolizer()
536 ->InitializeExternal(common_flags()->external_symbolizer_path);
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000537 }
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000538
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000539 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
540 // should be set to 1 prior to initializing the threads.
541 asan_inited = 1;
542 asan_init_is_running = false;
543
Sergey Matveev12d01ba2013-05-29 13:09:44 +0000544 InitTlsSize();
545
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000546 // Create main thread.
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000547 AsanThread *main_thread = AsanThread::Create(0, 0);
548 CreateThreadContextArgs create_main_args = { main_thread, 0 };
549 u32 main_tid = asanThreadRegistry().CreateThread(
550 0, true, 0, &create_main_args);
551 CHECK_EQ(0, main_tid);
552 SetCurrentThread(main_thread);
Peter Collingbourne0b694fc2013-05-17 16:56:53 +0000553 main_thread->ThreadStart(internal_getpid());
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000554 force_interface_symbols(); // no-op.
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000555
Alexey Samsonov975a3292013-05-22 13:20:37 +0000556#if CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000557 __lsan::InitCommonLsan();
Sergey Matveev41f15402013-08-01 14:57:07 +0000558 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
Sergey Matveev4cacb4f2013-05-21 17:56:45 +0000559 Atexit(__lsan::DoLeakCheck);
560 }
Alexey Samsonov975a3292013-05-22 13:20:37 +0000561#endif // CAN_SANITIZE_LEAKS
Sergey Matveev71f04112013-05-21 14:15:35 +0000562
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000563 if (flags()->verbosity) {
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000564 Report("AddressSanitizer Init done\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000565 }
566}