blob: d205f26d609771c6c099f689c73178b802862f58 [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"
17#include "asan_lock.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000018#include "asan_mapping.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"
23#include "asan_thread_registry.h"
Chandler Carruthd865fec2012-08-29 02:27:54 +000024#include "sanitizer/asan_interface.h"
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000025#include "sanitizer_common/sanitizer_atomic.h"
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000026#include "sanitizer_common/sanitizer_flags.h"
Alexey Samsonov9552db72012-06-05 07:25:47 +000027#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov9c6e5302012-08-23 07:32:06 +000028#include "sanitizer_common/sanitizer_symbolizer.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000029
Alexey Samsonov591616d2012-09-11 09:44:48 +000030namespace __asan {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000031
Alexey Samsonov591616d2012-09-11 09:44:48 +000032static void AsanDie() {
Dmitry Vyukovfce5bd42012-06-29 16:58:33 +000033 static atomic_uint32_t num_calls;
34 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000035 // Don't die twice - run a busy loop.
36 while (1) { }
37 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000038 if (flags()->sleep_before_dying) {
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +000039 Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000040 SleepForSeconds(flags()->sleep_before_dying);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000041 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000042 if (flags()->unmap_shadow_on_exit)
Alexey Samsonova25b3462012-06-06 16:15:07 +000043 UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000044 if (death_callback)
45 death_callback();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000046 if (flags()->abort_on_error)
Alexey Samsonov47657ce2012-06-06 07:02:44 +000047 Abort();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000048 Exit(flags()->exitcode);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000049}
50
Alexey Samsonov591616d2012-09-11 09:44:48 +000051static void AsanCheckFailed(const char *file, int line, const char *cond,
52 u64 v1, u64 v2) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000053 Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
Alexey Samsonov15a77612012-06-06 15:22:20 +000054 file, line, cond, (uptr)v1, (uptr)v2);
Alexander Potapenko8e23d272012-09-07 15:50:19 +000055 // FIXME: check for infinite recursion without a thread-local counter here.
Alexey Samsonov15a77612012-06-06 15:22:20 +000056 PRINT_CURRENT_STACK();
57 ShowStatsAndAbort();
58}
59
Kostya Serebryany1e172b42011-11-30 01:07:02 +000060// -------------------------- Flags ------------------------- {{{1
Kostya Serebryany6d924fa2012-09-06 10:57:03 +000061static const int kDeafultMallocContextSize = 30;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000062
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000063static Flags asan_flags;
64
65Flags *flags() {
66 return &asan_flags;
67}
68
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000069static void ParseFlagsFromString(Flags *f, const char *str) {
70 ParseFlag(str, &f->quarantine_size, "quarantine_size");
71 ParseFlag(str, &f->symbolize, "symbolize");
72 ParseFlag(str, &f->verbosity, "verbosity");
73 ParseFlag(str, &f->redzone, "redzone");
74 CHECK(f->redzone >= 16);
75 CHECK(IsPowerOfTwo(f->redzone));
76
77 ParseFlag(str, &f->debug, "debug");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000078 ParseFlag(str, &f->report_globals, "report_globals");
Kostya Serebryany3945c582012-08-21 14:10:25 +000079 ParseFlag(str, &f->check_initialization_order, "initialization_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000080 ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
Alexander Potapenko78c7f572012-09-06 13:31:13 +000081 CHECK((uptr)f->malloc_context_size <= kStackTraceMax);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000082
83 ParseFlag(str, &f->replace_str, "replace_str");
84 ParseFlag(str, &f->replace_intrin, "replace_intrin");
85 ParseFlag(str, &f->replace_cfallocator, "replace_cfallocator");
86 ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
87 ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
88 ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
89 ParseFlag(str, &f->exitcode, "exitcode");
90 ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
91 ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
92 ParseFlag(str, &f->handle_segv, "handle_segv");
93 ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000094 ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
95 ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
96 ParseFlag(str, &f->abort_on_error, "abort_on_error");
97 ParseFlag(str, &f->atexit, "atexit");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000098 ParseFlag(str, &f->disable_core, "disable_core");
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +000099 ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000100 ParseFlag(str, &f->allow_reexec, "allow_reexec");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000101 ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000102 ParseFlag(str, &f->log_path, "log_path");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000103}
104
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000105extern "C" {
Alexey Samsonovc6b87162012-08-14 13:54:28 +0000106SANITIZER_WEAK_ATTRIBUTE
107SANITIZER_INTERFACE_ATTRIBUTE
108const char* __asan_default_options() { return ""; }
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000109} // extern "C"
110
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000111void InitializeFlags(Flags *f, const char *env) {
112 internal_memset(f, 0, sizeof(*f));
113
Evgeniy Stepanov7315c262012-09-07 12:13:52 +0000114 f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000115 f->symbolize = false;
116 f->verbosity = 0;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000117 f->redzone = (ASAN_LOW_MEMORY) ? 64 : 128;
118 f->debug = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000119 f->report_globals = 1;
Kostya Serebryany3945c582012-08-21 14:10:25 +0000120 f->check_initialization_order = true;
Kostya Serebryany6d924fa2012-09-06 10:57:03 +0000121 f->malloc_context_size = kDeafultMallocContextSize;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000122 f->replace_str = true;
123 f->replace_intrin = true;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000124 f->replace_cfallocator = true;
125 f->mac_ignore_invalid_free = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000126 f->use_fake_stack = true;
127 f->max_malloc_fill_size = 0;
128 f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
129 f->allow_user_poisoning = true;
130 f->sleep_before_dying = 0;
131 f->handle_segv = ASAN_NEEDS_SEGV;
132 f->use_sigaltstack = false;
133 f->check_malloc_usable_size = true;
134 f->unmap_shadow_on_exit = false;
135 f->abort_on_error = false;
136 f->atexit = false;
Kostya Serebryany5af39e52012-11-21 12:38:58 +0000137 f->disable_core = (SANITIZER_WORDSIZE == 64);
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +0000138 f->strip_path_prefix = "";
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000139 f->allow_reexec = true;
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000140 f->print_full_thread_history = true;
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000141 f->log_path = 0;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000142
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000143 // Override from user-specified string.
Alexey Samsonovb750c4c2012-07-25 10:40:57 +0000144 ParseFlagsFromString(f, __asan_default_options());
145 if (flags()->verbosity) {
146 Report("Using the defaults from __asan_default_options: %s\n",
147 __asan_default_options());
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000148 }
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000149
150 // Override from command line.
151 ParseFlagsFromString(f, env);
152}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000153
154// -------------------------- Globals --------------------- {{{1
155int asan_inited;
156bool asan_init_is_running;
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000157void (*death_callback)(void);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000158
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000159// -------------------------- Misc ---------------- {{{1
160void ShowStatsAndAbort() {
161 __asan_print_accumulated_stats();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000162 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000163}
164
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000165// ---------------------- mmap -------------------- {{{1
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000166// Reserve memory range [beg, end].
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000167static void ReserveShadowMemoryRange(uptr beg, uptr end) {
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000168 CHECK((beg % GetPageSizeCached()) == 0);
169 CHECK(((end + 1) % GetPageSizeCached()) == 0);
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000170 uptr size = end - beg + 1;
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000171 void *res = MmapFixedNoReserve(beg, size);
Alexander Potapenko5aabcb52012-09-07 15:34:40 +0000172 if (res != (void*)beg) {
173 Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
174 "Perhaps you're using ulimit -v\n", size);
175 Abort();
176 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000177}
178
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000179// --------------- LowLevelAllocateCallbac ---------- {{{1
180static void OnLowLevelAllocate(uptr ptr, uptr size) {
181 PoisonShadow(ptr, size, kAsanInternalHeapMagic);
Kostya Serebryanyb89567c2011-12-02 21:02:20 +0000182}
183
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000184// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000185// exported functions
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000186#define ASAN_REPORT_ERROR(type, is_write, size) \
Alexey Samsonov0a4c9062012-06-05 13:50:57 +0000187extern "C" NOINLINE INTERFACE_ATTRIBUTE \
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000188void __asan_report_ ## type ## size(uptr addr); \
189void __asan_report_ ## type ## size(uptr addr) { \
Kostya Serebryany9f311bb2012-03-15 01:36:00 +0000190 GET_CALLER_PC_BP_SP; \
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000191 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000192}
193
194ASAN_REPORT_ERROR(load, false, 1)
195ASAN_REPORT_ERROR(load, false, 2)
196ASAN_REPORT_ERROR(load, false, 4)
197ASAN_REPORT_ERROR(load, false, 8)
198ASAN_REPORT_ERROR(load, false, 16)
199ASAN_REPORT_ERROR(store, true, 1)
200ASAN_REPORT_ERROR(store, true, 2)
201ASAN_REPORT_ERROR(store, true, 4)
202ASAN_REPORT_ERROR(store, true, 8)
203ASAN_REPORT_ERROR(store, true, 16)
204
205// Force the linker to keep the symbols for various ASan interface functions.
206// We want to keep those in the executable in order to let the instrumented
207// dynamic libraries access the symbol even if it is not used by the executable
208// itself. This should help if the build system is removing dead code at link
209// time.
Alexander Potapenko3fe91352012-02-27 14:06:48 +0000210static NOINLINE void force_interface_symbols() {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000211 volatile int fake_condition = 0; // prevent dead condition elimination.
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000212 // __asan_report_* functions are noreturn, so we need a switch to prevent
213 // the compiler from removing any of them.
214 switch (fake_condition) {
215 case 1: __asan_report_load1(0); break;
216 case 2: __asan_report_load2(0); break;
217 case 3: __asan_report_load4(0); break;
218 case 4: __asan_report_load8(0); break;
219 case 5: __asan_report_load16(0); break;
220 case 6: __asan_report_store1(0); break;
221 case 7: __asan_report_store2(0); break;
222 case 8: __asan_report_store4(0); break;
223 case 9: __asan_report_store8(0); break;
224 case 10: __asan_report_store16(0); break;
225 case 11: __asan_register_global(0, 0, 0); break;
226 case 12: __asan_register_globals(0, 0); break;
227 case 13: __asan_unregister_globals(0, 0); break;
228 case 14: __asan_set_death_callback(0); break;
229 case 15: __asan_set_error_report_callback(0); break;
230 case 16: __asan_handle_no_return(); break;
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000231 case 17: __asan_address_is_poisoned(0); break;
232 case 18: __asan_get_allocated_size(0); break;
233 case 19: __asan_get_current_allocated_bytes(); break;
234 case 20: __asan_get_estimated_allocated_size(0); break;
235 case 21: __asan_get_free_bytes(); break;
236 case 22: __asan_get_heap_size(); break;
237 case 23: __asan_get_ownership(0); break;
238 case 24: __asan_get_unmapped_bytes(); break;
239 case 25: __asan_poison_memory_region(0, 0); break;
240 case 26: __asan_unpoison_memory_region(0, 0); break;
241 case 27: __asan_set_error_exit_code(0); break;
242 case 28: __asan_stack_free(0, 0, 0); break;
243 case 29: __asan_stack_malloc(0, 0); break;
Alexey Samsonov86633432012-10-02 14:06:39 +0000244 case 30: __asan_on_error(); break;
Alexey Samsonov08d97882012-08-14 15:03:24 +0000245 case 31: __asan_default_options(); break;
Kostya Serebryany128892c2012-08-21 14:43:36 +0000246 case 32: __asan_before_dynamic_init(0, 0); break;
247 case 33: __asan_after_dynamic_init(); break;
Alexey Samsonovb21de9e2012-08-22 10:12:47 +0000248 case 34: __asan_malloc_hook(0, 0); break;
249 case 35: __asan_free_hook(0); break;
Alexey Samsonov1ca53572012-10-02 12:11:17 +0000250 case 36: __asan_symbolize(0, 0, 0); break;
Alexey Samsonovd4b5db82012-12-04 01:38:15 +0000251 case 37: __asan_poison_stack_memory(0, 0); break;
252 case 38: __asan_unpoison_stack_memory(0, 0); break;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000253 }
254}
255
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000256static void asan_atexit() {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000257 Printf("AddressSanitizer exit stats:\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000258 __asan_print_accumulated_stats();
259}
260
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000261} // namespace __asan
262
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000263// ---------------------- Interface ---------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000264using namespace __asan; // NOLINT
265
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000266int NOINLINE __asan_set_error_exit_code(int exit_code) {
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000267 int old = flags()->exitcode;
268 flags()->exitcode = exit_code;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000269 return old;
270}
271
Alexander Potapenkodadc45d2012-03-06 11:45:59 +0000272void NOINLINE __asan_handle_no_return() {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000273 int local_stack;
274 AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
275 CHECK(curr_thread);
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000276 uptr PageSize = GetPageSizeCached();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000277 uptr top = curr_thread->stack_top();
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000278 uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000279 PoisonShadow(bottom, top - bottom, 0);
280}
281
Alexander Potapenko2f3f9622012-03-01 14:39:21 +0000282void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
Kostya Serebryanye1fe0fd2012-02-13 21:24:29 +0000283 death_callback = callback;
284}
285
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000286void __asan_init() {
287 if (asan_inited) return;
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000288 CHECK(!asan_init_is_running && "ASan init calls itself!");
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000289 asan_init_is_running = true;
290
291 // Make sure we are not statically linked.
292 AsanDoesNotSupportStaticLinkage();
293
Alexey Samsonov591616d2012-09-11 09:44:48 +0000294 // Install tool-specific callbacks in sanitizer_common.
295 SetDieCallback(AsanDie);
296 SetCheckFailedCallback(AsanCheckFailed);
Kostya Serebryany283c2962012-08-28 11:34:40 +0000297 SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
298
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000299 // Initialize flags. This must be done early, because most of the
300 // initialization steps look at flags().
Alexey Samsonov3dbeabb2012-06-14 14:07:21 +0000301 const char *options = GetEnv("ASAN_OPTIONS");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000302 InitializeFlags(flags(), options);
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000303 __sanitizer_set_report_path(flags()->log_path);
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000304
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000305 if (flags()->verbosity && options) {
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000306 Report("Parsed ASAN_OPTIONS: %s\n", options);
307 }
308
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000309 // Re-exec ourselves if we need to set additional env or command line args.
310 MaybeReexec();
311
Alexey Samsonov947fbd12012-08-27 14:04:54 +0000312 // Setup internal allocator callback.
313 SetLowLevelAllocateCallback(OnLowLevelAllocate);
314
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000315 if (flags()->atexit) {
Alexey Samsonovb823e3c2012-02-22 14:07:06 +0000316 Atexit(asan_atexit);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000317 }
318
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000319 // interceptors
320 InitializeAsanInterceptors();
321
322 ReplaceSystemMalloc();
Alexey Samsonov4d5f98d2012-04-06 08:21:08 +0000323 ReplaceOperatorsNewAndDelete();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000324
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000325 if (flags()->verbosity) {
Alexey Samsonove4309e82012-06-06 10:54:25 +0000326 Printf("|| `[%p, %p]` || HighMem ||\n",
327 (void*)kHighMemBeg, (void*)kHighMemEnd);
328 Printf("|| `[%p, %p]` || HighShadow ||\n",
329 (void*)kHighShadowBeg, (void*)kHighShadowEnd);
330 Printf("|| `[%p, %p]` || ShadowGap ||\n",
331 (void*)kShadowGapBeg, (void*)kShadowGapEnd);
332 Printf("|| `[%p, %p]` || LowShadow ||\n",
333 (void*)kLowShadowBeg, (void*)kLowShadowEnd);
334 Printf("|| `[%p, %p]` || LowMem ||\n",
335 (void*)kLowMemBeg, (void*)kLowMemEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000336 Printf("MemToShadow(shadow): %p %p %p %p\n",
Alexey Samsonove4309e82012-06-06 10:54:25 +0000337 (void*)MEM_TO_SHADOW(kLowShadowBeg),
338 (void*)MEM_TO_SHADOW(kLowShadowEnd),
339 (void*)MEM_TO_SHADOW(kHighShadowBeg),
340 (void*)MEM_TO_SHADOW(kHighShadowEnd));
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000341 Printf("red_zone=%zu\n", (uptr)flags()->redzone);
342 Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000343
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000344 Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
345 Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
346 Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000347 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
348 }
349
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000350 if (flags()->disable_core) {
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000351 DisableCoreDumper();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000352 }
353
Alexey Samsonovdd3a9112012-06-15 07:29:14 +0000354 uptr shadow_start = kLowShadowBeg;
Kostya Serebryanye89f1842012-11-24 05:03:11 +0000355 if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity();
Alexey Samsonovdd3a9112012-06-15 07:29:14 +0000356 uptr shadow_end = kHighShadowEnd;
357 if (MemoryRangeIsAvailable(shadow_start, shadow_end)) {
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000358 if (kLowShadowBeg != kLowShadowEnd) {
Timur Iskhodzhanov3e81fe42012-02-09 17:20:14 +0000359 // mmap the low shadow plus at least one page.
Kostya Serebryanye89f1842012-11-24 05:03:11 +0000360 ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(),
361 kLowShadowEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000362 }
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000363 // mmap the high shadow.
364 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000365 // protect the gap
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000366 void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000367 CHECK(prot == (void*)kShadowGapBeg);
Alexander Potapenkoc50e8352012-02-13 15:11:23 +0000368 } else {
369 Report("Shadow memory range interleaves with an existing memory mapping. "
370 "ASan cannot proceed correctly. ABORTING.\n");
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000371 DumpProcessMap();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000372 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000373 }
374
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000375 InstallSignalHandlers();
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000376 // Start symbolizer process if necessary.
377 if (flags()->symbolize) {
378 const char *external_symbolizer = GetEnv("ASAN_SYMBOLIZER_PATH");
379 if (external_symbolizer) {
380 InitializeExternalSymbolizer(external_symbolizer);
381 }
382 }
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000383
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000384 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
385 // should be set to 1 prior to initializing the threads.
386 asan_inited = 1;
387 asan_init_is_running = false;
388
389 asanThreadRegistry().Init();
390 asanThreadRegistry().GetMain()->ThreadStart();
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000391 force_interface_symbols(); // no-op.
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000392
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000393 if (flags()->verbosity) {
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000394 Report("AddressSanitizer Init done\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000395 }
396}
Evgeniy Stepanov8bcc6b92012-01-11 08:17:19 +0000397
398#if defined(ASAN_USE_PREINIT_ARRAY)
Timur Iskhodzhanov38ed7362012-02-21 16:24:23 +0000399 // On Linux, we force __asan_init to be called before anyone else
400 // by placing it into .preinit_array section.
401 // FIXME: do we have anything like this on Mac?
402 __attribute__((section(".preinit_array")))
403 typeof(__asan_init) *__asan_preinit =__asan_init;
404#elif defined(_WIN32) && defined(_DLL)
405 // On Windows, when using dynamic CRT (/MD), we can put a pointer
406 // to __asan_init into the global list of C initializers.
407 // See crt0dat.c in the CRT sources for the details.
Timur Iskhodzhanov39c22ee2012-02-22 09:28:14 +0000408 #pragma section(".CRT$XIB", long, read) // NOLINT
Timur Iskhodzhanov38ed7362012-02-21 16:24:23 +0000409 __declspec(allocate(".CRT$XIB")) void (*__asan_preinit)() = __asan_init;
Evgeniy Stepanov8bcc6b92012-01-11 08:17:19 +0000410#endif