blob: 07c2551d672299d853a52dc283094213c6057d1c [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"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000027
Alexey Samsonov591616d2012-09-11 09:44:48 +000028namespace __asan {
Alexey Samsonov47657ce2012-06-06 07:02:44 +000029
Kostya Serebryanye31eca92013-02-15 12:00:24 +000030uptr AsanMappingProfile[kAsanMappingProfileSize];
31
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 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +000042 if (flags()->unmap_shadow_on_exit) {
43 if (kMidMemBeg) {
44 UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
45 UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
46 } else {
47 UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
48 }
49 }
Alexey Samsonov47657ce2012-06-06 07:02:44 +000050 if (death_callback)
51 death_callback();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000052 if (flags()->abort_on_error)
Alexey Samsonov47657ce2012-06-06 07:02:44 +000053 Abort();
Alexey Samsonovf8822472013-02-20 13:54:32 +000054 internal__exit(flags()->exitcode);
Alexey Samsonov47657ce2012-06-06 07:02:44 +000055}
56
Alexey Samsonov591616d2012-09-11 09:44:48 +000057static void AsanCheckFailed(const char *file, int line, const char *cond,
58 u64 v1, u64 v2) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000059 Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
Alexey Samsonov15a77612012-06-06 15:22:20 +000060 file, line, cond, (uptr)v1, (uptr)v2);
Alexander Potapenko8e23d272012-09-07 15:50:19 +000061 // FIXME: check for infinite recursion without a thread-local counter here.
Alexey Samsonov15a77612012-06-06 15:22:20 +000062 PRINT_CURRENT_STACK();
Alexey Samsonov570c2a02012-12-13 11:09:26 +000063 Die();
Alexey Samsonov15a77612012-06-06 15:22:20 +000064}
65
Kostya Serebryany1e172b42011-11-30 01:07:02 +000066// -------------------------- Flags ------------------------- {{{1
Kostya Serebryany6d924fa2012-09-06 10:57:03 +000067static const int kDeafultMallocContextSize = 30;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000068
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000069static Flags asan_flags;
70
71Flags *flags() {
72 return &asan_flags;
73}
74
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) {
91 ParseFlag(str, &f->quarantine_size, "quarantine_size");
92 ParseFlag(str, &f->symbolize, "symbolize");
93 ParseFlag(str, &f->verbosity, "verbosity");
94 ParseFlag(str, &f->redzone, "redzone");
95 CHECK(f->redzone >= 16);
96 CHECK(IsPowerOfTwo(f->redzone));
97
98 ParseFlag(str, &f->debug, "debug");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +000099 ParseFlag(str, &f->report_globals, "report_globals");
Alexey Samsonov6e7dca72013-03-28 09:11:20 +0000100 ParseFlag(str, &f->check_initialization_order, "check_initialization_order");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000101 ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
Alexander Potapenko78c7f572012-09-06 13:31:13 +0000102 CHECK((uptr)f->malloc_context_size <= kStackTraceMax);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000103
104 ParseFlag(str, &f->replace_str, "replace_str");
105 ParseFlag(str, &f->replace_intrin, "replace_intrin");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000106 ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
107 ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
108 ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
Kostya Serebryany2a3619e2013-04-04 11:17:14 +0000109 ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000110 ParseFlag(str, &f->exitcode, "exitcode");
111 ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
112 ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
113 ParseFlag(str, &f->handle_segv, "handle_segv");
114 ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000115 ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
116 ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
117 ParseFlag(str, &f->abort_on_error, "abort_on_error");
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000118 ParseFlag(str, &f->print_stats, "print_stats");
119 ParseFlag(str, &f->print_legend, "print_legend");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000120 ParseFlag(str, &f->atexit, "atexit");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000121 ParseFlag(str, &f->disable_core, "disable_core");
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +0000122 ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000123 ParseFlag(str, &f->allow_reexec, "allow_reexec");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000124 ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000125 ParseFlag(str, &f->log_path, "log_path");
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000126 ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
127 ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
Kostya Serebryany73bad812012-12-20 11:54:21 +0000128 ParseFlag(str, &f->poison_heap, "poison_heap");
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +0000129 ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
Kostya Serebryany9e3bd382012-12-26 06:30:02 +0000130 ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000131 ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000132}
133
Alexey Samsonov1a253792013-03-14 10:07:40 +0000134static const char *asan_external_symbolizer;
135
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000136void InitializeFlags(Flags *f, const char *env) {
137 internal_memset(f, 0, sizeof(*f));
138
Evgeniy Stepanov7315c262012-09-07 12:13:52 +0000139 f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
Alexey Samsonov1a253792013-03-14 10:07:40 +0000140 f->symbolize = (asan_external_symbolizer != 0);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000141 f->verbosity = 0;
Kostya Serebryanyc35314a2012-12-26 10:41:24 +0000142 f->redzone = ASAN_ALLOCATOR_VERSION == 2 ? 16 : (ASAN_LOW_MEMORY) ? 64 : 128;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000143 f->debug = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000144 f->report_globals = 1;
Alexey Samsonov566c0a12013-03-14 11:49:40 +0000145 f->check_initialization_order = false;
Kostya Serebryany6d924fa2012-09-06 10:57:03 +0000146 f->malloc_context_size = kDeafultMallocContextSize;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000147 f->replace_str = true;
148 f->replace_intrin = true;
Alexey Samsonov7ed1d2b2012-07-10 07:41:27 +0000149 f->mac_ignore_invalid_free = false;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000150 f->use_fake_stack = true;
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;
157 f->use_sigaltstack = false;
158 f->check_malloc_usable_size = true;
159 f->unmap_shadow_on_exit = false;
160 f->abort_on_error = false;
Kostya Serebryany95f630a2013-01-28 07:34:22 +0000161 f->print_stats = false;
162 f->print_legend = true;
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000163 f->atexit = false;
Kostya Serebryany5af39e52012-11-21 12:38:58 +0000164 f->disable_core = (SANITIZER_WORDSIZE == 64);
Alexey Samsonov4e21c6b2012-08-06 13:00:21 +0000165 f->strip_path_prefix = "";
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000166 f->allow_reexec = true;
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000167 f->print_full_thread_history = true;
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000168 f->log_path = 0;
Kostya Serebryanyf7de01f2013-01-14 11:01:34 +0000169 f->fast_unwind_on_fatal = false;
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000170 f->fast_unwind_on_malloc = true;
Kostya Serebryany73bad812012-12-20 11:54:21 +0000171 f->poison_heap = true;
Alexander Potapenkobc3a2d12013-02-21 17:12:21 +0000172 // Turn off alloc/dealloc mismatch checker on Mac for now.
173 // TODO(glider): Fix known issues and enable this back.
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +0000174 f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0);;
Kostya Serebryany9e3bd382012-12-26 06:30:02 +0000175 f->use_stack_depot = true; // Only affects allocator2.
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000176 f->strict_memcmp = true;
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);
190}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000191
192// -------------------------- Globals --------------------- {{{1
193int asan_inited;
194bool asan_init_is_running;
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000195void (*death_callback)(void);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000196
197#if !ASAN_FIXED_MAPPING
198uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
199#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000200
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000201// -------------------------- Misc ---------------- {{{1
202void ShowStatsAndAbort() {
203 __asan_print_accumulated_stats();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000204 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000205}
206
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000207// ---------------------- mmap -------------------- {{{1
Kostya Serebryanya874fe52011-12-28 23:28:54 +0000208// Reserve memory range [beg, end].
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000209static void ReserveShadowMemoryRange(uptr beg, uptr end) {
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000210 CHECK((beg % GetPageSizeCached()) == 0);
211 CHECK(((end + 1) % GetPageSizeCached()) == 0);
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000212 uptr size = end - beg + 1;
Alexey Samsonovf607fc12012-06-14 14:42:58 +0000213 void *res = MmapFixedNoReserve(beg, size);
Alexander Potapenko5aabcb52012-09-07 15:34:40 +0000214 if (res != (void*)beg) {
215 Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
216 "Perhaps you're using ulimit -v\n", size);
217 Abort();
218 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000219}
220
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000221// --------------- LowLevelAllocateCallbac ---------- {{{1
222static void OnLowLevelAllocate(uptr ptr, uptr size) {
223 PoisonShadow(ptr, size, kAsanInternalHeapMagic);
Kostya Serebryanyb89567c2011-12-02 21:02:20 +0000224}
225
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000226// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000227// exported functions
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000228#define ASAN_REPORT_ERROR(type, is_write, size) \
Alexey Samsonov0a4c9062012-06-05 13:50:57 +0000229extern "C" NOINLINE INTERFACE_ATTRIBUTE \
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000230void __asan_report_ ## type ## size(uptr addr); \
231void __asan_report_ ## type ## size(uptr addr) { \
Kostya Serebryany9f311bb2012-03-15 01:36:00 +0000232 GET_CALLER_PC_BP_SP; \
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000233 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000234}
235
236ASAN_REPORT_ERROR(load, false, 1)
237ASAN_REPORT_ERROR(load, false, 2)
238ASAN_REPORT_ERROR(load, false, 4)
239ASAN_REPORT_ERROR(load, false, 8)
240ASAN_REPORT_ERROR(load, false, 16)
241ASAN_REPORT_ERROR(store, true, 1)
242ASAN_REPORT_ERROR(store, true, 2)
243ASAN_REPORT_ERROR(store, true, 4)
244ASAN_REPORT_ERROR(store, true, 8)
245ASAN_REPORT_ERROR(store, true, 16)
246
Kostya Serebryany366984e2013-02-19 11:30:25 +0000247#define ASAN_REPORT_ERROR_N(type, is_write) \
248extern "C" NOINLINE INTERFACE_ATTRIBUTE \
249void __asan_report_ ## type ## _n(uptr addr, uptr size); \
250void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
251 GET_CALLER_PC_BP_SP; \
252 __asan_report_error(pc, bp, sp, addr, is_write, size); \
253}
254
255ASAN_REPORT_ERROR_N(load, false)
256ASAN_REPORT_ERROR_N(store, true)
257
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000258// Force the linker to keep the symbols for various ASan interface functions.
259// We want to keep those in the executable in order to let the instrumented
260// dynamic libraries access the symbol even if it is not used by the executable
261// itself. This should help if the build system is removing dead code at link
262// time.
Alexander Potapenko3fe91352012-02-27 14:06:48 +0000263static NOINLINE void force_interface_symbols() {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000264 volatile int fake_condition = 0; // prevent dead condition elimination.
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000265 // __asan_report_* functions are noreturn, so we need a switch to prevent
266 // the compiler from removing any of them.
267 switch (fake_condition) {
268 case 1: __asan_report_load1(0); break;
269 case 2: __asan_report_load2(0); break;
270 case 3: __asan_report_load4(0); break;
271 case 4: __asan_report_load8(0); break;
272 case 5: __asan_report_load16(0); break;
273 case 6: __asan_report_store1(0); break;
274 case 7: __asan_report_store2(0); break;
275 case 8: __asan_report_store4(0); break;
276 case 9: __asan_report_store8(0); break;
277 case 10: __asan_report_store16(0); break;
Alexander Potapenko448fe9a2012-08-09 09:46:12 +0000278 case 12: __asan_register_globals(0, 0); break;
279 case 13: __asan_unregister_globals(0, 0); break;
280 case 14: __asan_set_death_callback(0); break;
281 case 15: __asan_set_error_report_callback(0); break;
282 case 16: __asan_handle_no_return(); break;
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000283 case 17: __asan_address_is_poisoned(0); break;
284 case 18: __asan_get_allocated_size(0); break;
285 case 19: __asan_get_current_allocated_bytes(); break;
286 case 20: __asan_get_estimated_allocated_size(0); break;
287 case 21: __asan_get_free_bytes(); break;
288 case 22: __asan_get_heap_size(); break;
289 case 23: __asan_get_ownership(0); break;
290 case 24: __asan_get_unmapped_bytes(); break;
291 case 25: __asan_poison_memory_region(0, 0); break;
292 case 26: __asan_unpoison_memory_region(0, 0); break;
293 case 27: __asan_set_error_exit_code(0); break;
294 case 28: __asan_stack_free(0, 0, 0); break;
295 case 29: __asan_stack_malloc(0, 0); break;
Alexey Samsonov05e16a02013-03-26 13:06:12 +0000296 case 30: __asan_before_dynamic_init(0); break;
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000297 case 31: __asan_after_dynamic_init(); break;
298 case 32: __asan_poison_stack_memory(0, 0); break;
299 case 33: __asan_unpoison_stack_memory(0, 0); break;
Kostya Serebryanyeb280932012-12-28 15:24:16 +0000300 case 34: __asan_region_is_poisoned(0, 0); break;
Kostya Serebryany17a7c672012-12-29 10:18:31 +0000301 case 35: __asan_describe_address(0); break;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000302 }
303}
304
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000305static void asan_atexit() {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000306 Printf("AddressSanitizer exit stats:\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000307 __asan_print_accumulated_stats();
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000308 // Print AsanMappingProfile.
309 for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
310 if (AsanMappingProfile[i] == 0) continue;
311 Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
312 }
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000313}
314
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000315static void InitializeHighMemEnd() {
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000316#if !ASAN_FIXED_MAPPING
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000317#if SANITIZER_WORDSIZE == 64
318# if defined(__powerpc64__)
319 // FIXME:
320 // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
321 // We somehow need to figure our which one we are using now and choose
322 // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
323 // Note that with 'ulimit -s unlimited' the stack is moved away from the top
324 // of the address space, so simply checking the stack address is not enough.
325 kHighMemEnd = (1ULL << 44) - 1; // 0x00000fffffffffffUL
326# else
327 kHighMemEnd = (1ULL << 47) - 1; // 0x00007fffffffffffUL;
328# endif
329#else // SANITIZER_WORDSIZE == 32
330 kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff;
331#endif // SANITIZER_WORDSIZE
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000332#endif // !ASAN_FIXED_MAPPING
333}
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);
374 Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
375
376 Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
377 Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
378 Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
379 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
380 if (kMidMemBeg)
381 CHECK(kMidShadowBeg > kLowShadowEnd &&
382 kMidMemBeg > kMidShadowEnd &&
383 kHighShadowBeg > kMidMemEnd);
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000384}
385
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000386} // namespace __asan
387
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000388// ---------------------- Interface ---------------- {{{1
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000389using namespace __asan; // NOLINT
390
Alexey Samsonov6a08d292012-12-07 22:01:28 +0000391#if !SANITIZER_SUPPORTS_WEAK_HOOKS
392extern "C" {
393SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
394const char* __asan_default_options() { return ""; }
395} // extern "C"
396#endif
397
Alexander Potapenko5a9938d2012-08-09 16:05:17 +0000398int NOINLINE __asan_set_error_exit_code(int exit_code) {
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000399 int old = flags()->exitcode;
400 flags()->exitcode = exit_code;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000401 return old;
402}
403
Alexander Potapenkodadc45d2012-03-06 11:45:59 +0000404void NOINLINE __asan_handle_no_return() {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000405 int local_stack;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000406 AsanThread *curr_thread = GetCurrentThread();
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000407 CHECK(curr_thread);
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000408 uptr PageSize = GetPageSizeCached();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000409 uptr top = curr_thread->stack_top();
Kostya Serebryanyf67ec2b2012-11-23 15:38:49 +0000410 uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000411 PoisonShadow(bottom, top - bottom, 0);
412}
413
Alexander Potapenko2f3f9622012-03-01 14:39:21 +0000414void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
Kostya Serebryanye1fe0fd2012-02-13 21:24:29 +0000415 death_callback = callback;
416}
417
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000418void __asan_init() {
419 if (asan_inited) return;
Kostya Serebryany859778a2013-01-31 14:11:21 +0000420 SanitizerToolName = "AddressSanitizer";
Alexey Samsonov70e177e2012-08-27 09:30:58 +0000421 CHECK(!asan_init_is_running && "ASan init calls itself!");
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000422 asan_init_is_running = true;
Kostya Serebryanye5ab9682013-01-23 13:27:43 +0000423 InitializeHighMemEnd();
Alexander Potapenkofca72fd2012-05-25 15:37:16 +0000424
425 // Make sure we are not statically linked.
426 AsanDoesNotSupportStaticLinkage();
427
Alexey Samsonov591616d2012-09-11 09:44:48 +0000428 // Install tool-specific callbacks in sanitizer_common.
429 SetDieCallback(AsanDie);
430 SetCheckFailedCallback(AsanCheckFailed);
Kostya Serebryany283c2962012-08-28 11:34:40 +0000431 SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
432
Alexey Samsonov1a253792013-03-14 10:07:40 +0000433 // Check if external symbolizer is defined before parsing the flags.
434 asan_external_symbolizer = GetEnv("ASAN_SYMBOLIZER_PATH");
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000435 // Initialize flags. This must be done early, because most of the
436 // initialization steps look at flags().
Alexey Samsonov3dbeabb2012-06-14 14:07:21 +0000437 const char *options = GetEnv("ASAN_OPTIONS");
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000438 InitializeFlags(flags(), options);
Kostya Serebryany81dfbb72012-09-14 04:35:14 +0000439 __sanitizer_set_report_path(flags()->log_path);
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000440
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000441 if (flags()->verbosity && options) {
Alexander Potapenkofeb47932012-03-16 16:38:31 +0000442 Report("Parsed ASAN_OPTIONS: %s\n", options);
443 }
444
Alexander Potapenkoeb8c46e2012-08-24 09:22:05 +0000445 // Re-exec ourselves if we need to set additional env or command line args.
446 MaybeReexec();
447
Alexey Samsonov947fbd12012-08-27 14:04:54 +0000448 // Setup internal allocator callback.
449 SetLowLevelAllocateCallback(OnLowLevelAllocate);
450
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000451 if (flags()->atexit) {
Alexey Samsonovb823e3c2012-02-22 14:07:06 +0000452 Atexit(asan_atexit);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000453 }
454
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000455 // interceptors
456 InitializeAsanInterceptors();
457
458 ReplaceSystemMalloc();
Alexey Samsonov4d5f98d2012-04-06 08:21:08 +0000459 ReplaceOperatorsNewAndDelete();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000460
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000461 uptr shadow_start = kLowShadowBeg;
462 if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
463 uptr shadow_end = kHighShadowEnd;
464 bool full_shadow_is_available =
465 MemoryRangeIsAvailable(shadow_start, shadow_end);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000466
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +0000467#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000468 if (!full_shadow_is_available) {
469 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
Kostya Serebryany13577fe2013-02-28 12:28:37 +0000470 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000471 }
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000472#endif
473
474 if (flags()->verbosity)
475 PrintAddressSpaceLayout();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000476
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000477 if (flags()->disable_core) {
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000478 DisableCoreDumper();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000479 }
480
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000481 if (full_shadow_is_available) {
482 // mmap the low shadow plus at least one page at the left.
483 if (kLowShadowBeg)
484 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
Kostya Serebryanya7e760a2012-01-09 19:18:27 +0000485 // mmap the high shadow.
486 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryanye31eca92013-02-15 12:00:24 +0000487 // protect the gap.
488 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
489 } else if (kMidMemBeg &&
490 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
491 MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) {
492 CHECK(kLowShadowBeg != kLowShadowEnd);
493 // mmap the low shadow plus at least one page at the left.
494 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
495 // mmap the mid shadow.
496 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
497 // mmap the high shadow.
498 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
499 // protect the gaps.
500 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
501 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
502 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
Alexander Potapenkoc50e8352012-02-13 15:11:23 +0000503 } else {
504 Report("Shadow memory range interleaves with an existing memory mapping. "
505 "ASan cannot proceed correctly. ABORTING.\n");
Alexey Samsonovbe7420c2012-06-15 06:08:19 +0000506 DumpProcessMap();
Alexey Samsonov47657ce2012-06-06 07:02:44 +0000507 Die();
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000508 }
509
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000510 InstallSignalHandlers();
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000511 // Start symbolizer process if necessary.
Alexey Samsonov1a253792013-03-14 10:07:40 +0000512 if (flags()->symbolize && asan_external_symbolizer &&
513 asan_external_symbolizer[0]) {
514 InitializeExternalSymbolizer(asan_external_symbolizer);
Alexey Samsonov9c6e5302012-08-23 07:32:06 +0000515 }
Alexander Potapenkof03d8af2012-04-05 10:54:52 +0000516
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000517 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
518 // should be set to 1 prior to initializing the threads.
519 asan_inited = 1;
520 asan_init_is_running = false;
521
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000522 // Create main thread.
523 AsanTSDInit(AsanThread::TSDDtor);
524 AsanThread *main_thread = AsanThread::Create(0, 0);
525 CreateThreadContextArgs create_main_args = { main_thread, 0 };
526 u32 main_tid = asanThreadRegistry().CreateThread(
527 0, true, 0, &create_main_args);
528 CHECK_EQ(0, main_tid);
529 SetCurrentThread(main_thread);
530 main_thread->ThreadStart(GetPid());
Kostya Serebryany51e75c42011-12-28 00:59:39 +0000531 force_interface_symbols(); // no-op.
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000532
Kostya Serebryanyb4782602013-01-28 08:05:47 +0000533 InitializeAllocator();
534
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000535 if (flags()->verbosity) {
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000536 Report("AddressSanitizer Init done\n");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000537 }
538}