blob: 96e34045f3bb08f2d3d017fd7b63209e19af34d1 [file] [log] [blame]
Kostya Serebryany019b76f2011-11-30 01:07:021//===-- asan_rtl.cc ---------------------------------------------*- C++ -*-===//
2//
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"
16#include "asan_interface.h"
17#include "asan_internal.h"
18#include "asan_lock.h"
Kostya Serebryany019b76f2011-11-30 01:07:0219#include "asan_mac.h"
Kostya Serebryany019b76f2011-11-30 01:07:0220#include "asan_mapping.h"
Kostya Serebryanycd271f52012-01-05 00:44:3321#include "asan_procmaps.h"
Kostya Serebryany019b76f2011-11-30 01:07:0222#include "asan_stack.h"
23#include "asan_stats.h"
24#include "asan_thread.h"
25#include "asan_thread_registry.h"
26
Kostya Serebryany019b76f2011-11-30 01:07:0227namespace __asan {
28
29// -------------------------- Flags ------------------------- {{{1
30static const size_t kMallocContextSize = 30;
31static int FLAG_atexit;
32bool FLAG_fast_unwind = true;
33
34size_t FLAG_redzone; // power of two, >= 32
Kostya Serebryany019b76f2011-11-30 01:07:0235size_t FLAG_quarantine_size;
36int FLAG_demangle;
37bool FLAG_symbolize;
38int FLAG_v;
39int FLAG_debug;
40bool FLAG_poison_shadow;
41int FLAG_report_globals;
42size_t FLAG_malloc_context_size = kMallocContextSize;
43uintptr_t FLAG_large_malloc;
Kostya Serebryany019b76f2011-11-30 01:07:0244bool FLAG_handle_segv;
Kostya Serebryany019b76f2011-11-30 01:07:0245bool FLAG_replace_str;
46bool FLAG_replace_intrin;
47bool FLAG_replace_cfallocator; // Used on Mac only.
Kostya Serebryany019b76f2011-11-30 01:07:0248size_t FLAG_max_malloc_fill_size = 0;
49bool FLAG_use_fake_stack;
50int FLAG_exitcode = EXIT_FAILURE;
51bool FLAG_allow_user_poisoning;
52
53// -------------------------- Globals --------------------- {{{1
54int asan_inited;
55bool asan_init_is_running;
56
Kostya Serebryany019b76f2011-11-30 01:07:0257// -------------------------- Misc ---------------- {{{1
58void ShowStatsAndAbort() {
59 __asan_print_accumulated_stats();
Kostya Serebryanyedb4a8a2012-01-09 23:11:2660 AsanDie();
Kostya Serebryany019b76f2011-11-30 01:07:0261}
62
63static void PrintBytes(const char *before, uintptr_t *a) {
64 uint8_t *bytes = (uint8_t*)a;
65 size_t byte_num = (__WORDSIZE) / 8;
66 Printf("%s%p:", before, (uintptr_t)a);
67 for (size_t i = 0; i < byte_num; i++) {
68 Printf(" %lx%lx", bytes[i] >> 4, bytes[i] & 15);
69 }
70 Printf("\n");
71}
72
Kostya Serebryanyedb4a8a2012-01-09 23:11:2673size_t ReadFileToBuffer(const char *file_name, char **buff,
Kostya Serebryanycd271f52012-01-05 00:44:3374 size_t *buff_size, size_t max_len) {
Kostya Serebryany6c4bd802011-12-28 22:58:0175 const size_t kMinFileLen = kPageSize;
Kostya Serebryanyedb4a8a2012-01-09 23:11:2676 size_t read_len = 0;
Kostya Serebryany6c4bd802011-12-28 22:58:0177 *buff = 0;
Kostya Serebryanycd271f52012-01-05 00:44:3378 *buff_size = 0;
Kostya Serebryany6c4bd802011-12-28 22:58:0179 // The files we usually open are not seekable, so try different buffer sizes.
80 for (size_t size = kMinFileLen; size <= max_len; size *= 2) {
81 int fd = AsanOpenReadonly(file_name);
82 if (fd < 0) return -1;
Kostya Serebryanycd271f52012-01-05 00:44:3383 AsanUnmapOrDie(*buff, *buff_size);
Kostya Serebryany6c4bd802011-12-28 22:58:0184 *buff = (char*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
Kostya Serebryanycd271f52012-01-05 00:44:3385 *buff_size = size;
Kostya Serebryany6c4bd802011-12-28 22:58:0186 read_len = AsanRead(fd, *buff, size);
87 AsanClose(fd);
88 if (read_len < size) // We've read the whole file.
89 break;
90 }
91 return read_len;
92}
93
94// Like getenv, but reads env directly from /proc and does not use libc.
95// This function should be called first inside __asan_init.
96static const char* GetEnvFromProcSelfEnviron(const char* name) {
97 static char *environ;
98 static ssize_t len;
99 static bool inited;
100 if (!inited) {
101 inited = true;
Kostya Serebryanycd271f52012-01-05 00:44:33102 size_t environ_size;
103 len = ReadFileToBuffer("/proc/self/environ",
104 &environ, &environ_size, 1 << 20);
Kostya Serebryany6c4bd802011-12-28 22:58:01105 }
106 if (!environ || len <= 0) return NULL;
107 size_t namelen = internal_strlen(name);
108 const char *p = environ;
109 while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
110 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
111 const char* endp =
112 (char*)internal_memchr(p, '\0', len - (p - environ));
113 if (endp == NULL) // this entry isn't NUL terminated
114 return NULL;
115 else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
116 return p + namelen + 1; // point after =
117 p = endp + 1;
118 }
119 return NULL; // Not found.
120}
121
Kostya Serebryany019b76f2011-11-30 01:07:02122// ---------------------- mmap -------------------- {{{1
Kostya Serebryany6c4bd802011-12-28 22:58:01123void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) {
Kostya Serebryany019b76f2011-11-30 01:07:02124 Report("ERROR: AddressSanitizer failed to allocate "
125 "0x%lx (%ld) bytes of %s\n",
126 size, size, mem_type);
Kostya Serebryany6c4bd802011-12-28 22:58:01127 PRINT_CURRENT_STACK();
128 ShowStatsAndAbort();
Kostya Serebryany019b76f2011-11-30 01:07:02129}
130
Kostya Serebryanya7720962011-12-28 23:28:54131// Reserve memory range [beg, end].
132static void ReserveShadowMemoryRange(uintptr_t beg, uintptr_t end) {
Kostya Serebryany019b76f2011-11-30 01:07:02133 CHECK((beg % kPageSize) == 0);
134 CHECK(((end + 1) % kPageSize) == 0);
Kostya Serebryanya7720962011-12-28 23:28:54135 size_t size = end - beg + 1;
136 void *res = AsanMmapFixedNoReserve(beg, size);
137 CHECK(res == (void*)beg && "ReserveShadowMemoryRange failed");
Kostya Serebryany019b76f2011-11-30 01:07:02138}
139
Kostya Serebryanye4bada22011-12-02 21:02:20140// ---------------------- LowLevelAllocator ------------- {{{1
141void *LowLevelAllocator::Allocate(size_t size) {
142 CHECK((size & (size - 1)) == 0 && "size must be a power of two");
143 if (allocated_end_ - allocated_current_ < size) {
144 size_t size_to_allocate = Max(size, kPageSize);
Kostya Serebryany6c4bd802011-12-28 22:58:01145 allocated_current_ =
146 (char*)AsanMmapSomewhereOrDie(size_to_allocate, __FUNCTION__);
Kostya Serebryanye4bada22011-12-02 21:02:20147 allocated_end_ = allocated_current_ + size_to_allocate;
Kostya Serebryany7fb33a32011-12-15 17:41:30148 PoisonShadow((uintptr_t)allocated_current_, size_to_allocate,
149 kAsanInternalHeapMagic);
Kostya Serebryanye4bada22011-12-02 21:02:20150 }
151 CHECK(allocated_end_ - allocated_current_ >= size);
152 void *res = allocated_current_;
153 allocated_current_ += size;
154 return res;
155}
156
Kostya Serebryany019b76f2011-11-30 01:07:02157// ---------------------- DescribeAddress -------------------- {{{1
158static bool DescribeStackAddress(uintptr_t addr, uintptr_t access_size) {
159 AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
160 if (!t) return false;
161 const intptr_t kBufSize = 4095;
162 char buf[kBufSize];
163 uintptr_t offset = 0;
164 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
165 // This string is created by the compiler and has the following form:
166 // "FunctioName n alloc_1 alloc_2 ... alloc_n"
167 // where alloc_i looks like "offset size len ObjectName ".
168 CHECK(frame_descr);
169 // Report the function name and the offset.
170 const char *name_end = real_strchr(frame_descr, ' ');
171 CHECK(name_end);
172 buf[0] = 0;
Kostya Serebryany65518012012-01-09 22:20:49173 internal_strncat(buf, frame_descr,
174 Min(kBufSize,
175 static_cast<intptr_t>(name_end - frame_descr)));
Kostya Serebryany019b76f2011-11-30 01:07:02176 Printf("Address %p is located at offset %ld "
177 "in frame <%s> of T%d's stack:\n",
178 addr, offset, buf, t->tid());
179 // Report the number of stack objects.
180 char *p;
181 size_t n_objects = strtol(name_end, &p, 10);
182 CHECK(n_objects > 0);
183 Printf(" This frame has %ld object(s):\n", n_objects);
184 // Report all objects in this frame.
185 for (size_t i = 0; i < n_objects; i++) {
186 size_t beg, size;
187 intptr_t len;
188 beg = strtol(p, &p, 10);
189 size = strtol(p, &p, 10);
190 len = strtol(p, &p, 10);
191 if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
192 Printf("AddressSanitizer can't parse the stack frame descriptor: |%s|\n",
193 frame_descr);
194 break;
195 }
196 p++;
197 buf[0] = 0;
Kostya Serebryany65518012012-01-09 22:20:49198 internal_strncat(buf, p, Min(kBufSize, len));
Kostya Serebryany019b76f2011-11-30 01:07:02199 p += len;
200 Printf(" [%ld, %ld) '%s'\n", beg, beg + size, buf);
201 }
202 Printf("HINT: this may be a false positive if your program uses "
203 "some custom stack unwind mechanism\n"
204 " (longjmp and C++ exceptions *are* supported)\n");
205 t->summary()->Announce();
206 return true;
207}
208
209__attribute__((noinline))
210static void DescribeAddress(uintptr_t addr, uintptr_t access_size) {
211 // Check if this is a global.
212 if (DescribeAddrIfGlobal(addr))
213 return;
214
215 if (DescribeStackAddress(addr, access_size))
216 return;
217
218 // finally, check if this is a heap.
219 DescribeHeapAddress(addr, access_size);
220}
221
222// -------------------------- Run-time entry ------------------- {{{1
Kostya Serebryany019b76f2011-11-30 01:07:02223// exported functions
Kostya Serebryany46c70d32011-12-28 00:59:39224#define ASAN_REPORT_ERROR(type, is_write, size) \
225extern "C" void __asan_report_ ## type ## size(uintptr_t addr) \
226 __attribute__((visibility("default"))) __attribute__((noinline)); \
227extern "C" void __asan_report_ ## type ## size(uintptr_t addr) { \
228 GET_BP_PC_SP; \
229 __asan_report_error(pc, bp, sp, addr, is_write, size); \
Kostya Serebryany019b76f2011-11-30 01:07:02230}
231
232ASAN_REPORT_ERROR(load, false, 1)
233ASAN_REPORT_ERROR(load, false, 2)
234ASAN_REPORT_ERROR(load, false, 4)
235ASAN_REPORT_ERROR(load, false, 8)
236ASAN_REPORT_ERROR(load, false, 16)
237ASAN_REPORT_ERROR(store, true, 1)
238ASAN_REPORT_ERROR(store, true, 2)
239ASAN_REPORT_ERROR(store, true, 4)
240ASAN_REPORT_ERROR(store, true, 8)
241ASAN_REPORT_ERROR(store, true, 16)
242
243// Force the linker to keep the symbols for various ASan interface functions.
244// We want to keep those in the executable in order to let the instrumented
245// dynamic libraries access the symbol even if it is not used by the executable
246// itself. This should help if the build system is removing dead code at link
247// time.
Kostya Serebryany46c70d32011-12-28 00:59:39248static void force_interface_symbols() {
Kostya Serebryany019b76f2011-11-30 01:07:02249 volatile int fake_condition = 0; // prevent dead condition elimination.
250 if (fake_condition) {
251 __asan_report_load1(NULL);
252 __asan_report_load2(NULL);
253 __asan_report_load4(NULL);
254 __asan_report_load8(NULL);
255 __asan_report_load16(NULL);
256 __asan_report_store1(NULL);
257 __asan_report_store2(NULL);
258 __asan_report_store4(NULL);
259 __asan_report_store8(NULL);
260 __asan_report_store16(NULL);
261 __asan_register_global(0, 0, NULL);
262 __asan_register_globals(NULL, 0);
Kostya Serebryanyd2d043b2011-12-28 23:35:46263 __asan_unregister_globals(NULL, 0);
Kostya Serebryany019b76f2011-11-30 01:07:02264 }
265}
266
267// -------------------------- Init ------------------- {{{1
268static int64_t IntFlagValue(const char *flags, const char *flag,
269 int64_t default_val) {
270 if (!flags) return default_val;
Kostya Serebryany65518012012-01-09 22:20:49271 const char *str = internal_strstr(flags, flag);
Kostya Serebryany019b76f2011-11-30 01:07:02272 if (!str) return default_val;
273 return atoll(str + internal_strlen(flag));
274}
275
276static void asan_atexit() {
277 Printf("AddressSanitizer exit stats:\n");
278 __asan_print_accumulated_stats();
279}
280
281void CheckFailed(const char *cond, const char *file, int line) {
Kostya Serebryany5be458c2012-01-09 19:18:27282 Report("CHECK failed: %s at %s:%d\n", cond, file, line);
Kostya Serebryany019b76f2011-11-30 01:07:02283 PRINT_CURRENT_STACK();
284 ShowStatsAndAbort();
285}
286
287} // namespace __asan
288
Kostya Serebryany9fd01e52012-01-09 18:53:15289// ---------------------- Interface ---------------- {{{1
Kostya Serebryany019b76f2011-11-30 01:07:02290using namespace __asan; // NOLINT
291
Kostya Serebryany019b76f2011-11-30 01:07:02292int __asan_set_error_exit_code(int exit_code) {
293 int old = FLAG_exitcode;
294 FLAG_exitcode = exit_code;
295 return old;
296}
297
298void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp,
299 uintptr_t addr, bool is_write, size_t access_size) {
300 // Do not print more than one report, otherwise they will mix up.
301 static int num_calls = 0;
302 if (AtomicInc(&num_calls) > 1) return;
303
304 Printf("=================================================================\n");
305 const char *bug_descr = "unknown-crash";
306 if (AddrIsInMem(addr)) {
307 uint8_t *shadow_addr = (uint8_t*)MemToShadow(addr);
Kostya Serebryanyf0d799a2011-12-07 21:30:20308 // If we are accessing 16 bytes, look at the second shadow byte.
309 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
310 shadow_addr++;
311 // If we are in the partial right redzone, look at the next shadow byte.
312 if (*shadow_addr > 0 && *shadow_addr < 128)
313 shadow_addr++;
314 switch (*shadow_addr) {
Kostya Serebryany019b76f2011-11-30 01:07:02315 case kAsanHeapLeftRedzoneMagic:
316 case kAsanHeapRightRedzoneMagic:
317 bug_descr = "heap-buffer-overflow";
318 break;
319 case kAsanHeapFreeMagic:
320 bug_descr = "heap-use-after-free";
321 break;
322 case kAsanStackLeftRedzoneMagic:
323 bug_descr = "stack-buffer-underflow";
324 break;
325 case kAsanStackMidRedzoneMagic:
326 case kAsanStackRightRedzoneMagic:
327 case kAsanStackPartialRedzoneMagic:
328 bug_descr = "stack-buffer-overflow";
329 break;
330 case kAsanStackAfterReturnMagic:
331 bug_descr = "stack-use-after-return";
332 break;
333 case kAsanUserPoisonedMemoryMagic:
334 bug_descr = "use-after-poison";
335 break;
336 case kAsanGlobalRedzoneMagic:
337 bug_descr = "global-buffer-overflow";
338 break;
339 }
340 }
341
Kostya Serebryany72fde372011-12-09 01:49:31342 AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
343 int curr_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
344
345 if (curr_thread) {
346 // We started reporting an error message. Stop using the fake stack
347 // in case we will call an instrumented function from a symbolizer.
348 curr_thread->fake_stack().StopUsingFakeStack();
349 }
350
Kostya Serebryany019b76f2011-11-30 01:07:02351 Report("ERROR: AddressSanitizer %s on address "
352 "%p at pc 0x%lx bp 0x%lx sp 0x%lx\n",
353 bug_descr, addr, pc, bp, sp);
354
355 Printf("%s of size %d at %p thread T%d\n",
356 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
Kostya Serebryany72fde372011-12-09 01:49:31357 access_size, addr, curr_tid);
Kostya Serebryany019b76f2011-11-30 01:07:02358
359 if (FLAG_debug) {
360 PrintBytes("PC: ", (uintptr_t*)pc);
361 }
362
363 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax,
364 false, // FLAG_fast_unwind,
365 pc, bp);
366 stack.PrintStack();
367
368 CHECK(AddrIsInMem(addr));
369
370 DescribeAddress(addr, access_size);
371
372 uintptr_t shadow_addr = MemToShadow(addr);
373 Report("ABORTING\n");
374 __asan_print_accumulated_stats();
375 Printf("Shadow byte and word:\n");
376 Printf(" %p: %x\n", shadow_addr, *(unsigned char*)shadow_addr);
377 uintptr_t aligned_shadow = shadow_addr & ~(kWordSize - 1);
378 PrintBytes(" ", (uintptr_t*)(aligned_shadow));
379 Printf("More shadow bytes:\n");
380 PrintBytes(" ", (uintptr_t*)(aligned_shadow-4*kWordSize));
381 PrintBytes(" ", (uintptr_t*)(aligned_shadow-3*kWordSize));
382 PrintBytes(" ", (uintptr_t*)(aligned_shadow-2*kWordSize));
383 PrintBytes(" ", (uintptr_t*)(aligned_shadow-1*kWordSize));
384 PrintBytes("=>", (uintptr_t*)(aligned_shadow+0*kWordSize));
385 PrintBytes(" ", (uintptr_t*)(aligned_shadow+1*kWordSize));
386 PrintBytes(" ", (uintptr_t*)(aligned_shadow+2*kWordSize));
387 PrintBytes(" ", (uintptr_t*)(aligned_shadow+3*kWordSize));
388 PrintBytes(" ", (uintptr_t*)(aligned_shadow+4*kWordSize));
Kostya Serebryanyedb4a8a2012-01-09 23:11:26389 AsanDie();
Kostya Serebryany019b76f2011-11-30 01:07:02390}
391
392void __asan_init() {
393 if (asan_inited) return;
394 asan_init_is_running = true;
395
396 // Make sure we are not statically linked.
397 AsanDoesNotSupportStaticLinkage();
398
399 // flags
Kostya Serebryany6c4bd802011-12-28 22:58:01400 const char *options = GetEnvFromProcSelfEnviron("ASAN_OPTIONS");
Kostya Serebryany019b76f2011-11-30 01:07:02401 FLAG_malloc_context_size =
402 IntFlagValue(options, "malloc_context_size=", kMallocContextSize);
403 CHECK(FLAG_malloc_context_size <= kMallocContextSize);
404
405 FLAG_max_malloc_fill_size =
406 IntFlagValue(options, "max_malloc_fill_size=", 0);
407
408 FLAG_v = IntFlagValue(options, "verbosity=", 0);
409
410 FLAG_redzone = IntFlagValue(options, "redzone=", 128);
411 CHECK(FLAG_redzone >= 32);
412 CHECK((FLAG_redzone & (FLAG_redzone - 1)) == 0);
413
414 FLAG_atexit = IntFlagValue(options, "atexit=", 0);
415 FLAG_poison_shadow = IntFlagValue(options, "poison_shadow=", 1);
416 FLAG_report_globals = IntFlagValue(options, "report_globals=", 1);
Kostya Serebryanyb50a5392011-12-08 18:30:42417 FLAG_handle_segv = IntFlagValue(options, "handle_segv=", ASAN_NEEDS_SEGV);
Kostya Serebryany019b76f2011-11-30 01:07:02418 FLAG_symbolize = IntFlagValue(options, "symbolize=", 1);
419 FLAG_demangle = IntFlagValue(options, "demangle=", 1);
420 FLAG_debug = IntFlagValue(options, "debug=", 0);
421 FLAG_replace_cfallocator = IntFlagValue(options, "replace_cfallocator=", 1);
422 FLAG_fast_unwind = IntFlagValue(options, "fast_unwind=", 1);
Kostya Serebryany019b76f2011-11-30 01:07:02423 FLAG_replace_str = IntFlagValue(options, "replace_str=", 1);
Kostya Serebryany76eca5e2011-12-28 19:55:30424 FLAG_replace_intrin = IntFlagValue(options, "replace_intrin=", 1);
Kostya Serebryany019b76f2011-11-30 01:07:02425 FLAG_use_fake_stack = IntFlagValue(options, "use_fake_stack=", 1);
426 FLAG_exitcode = IntFlagValue(options, "exitcode=", EXIT_FAILURE);
427 FLAG_allow_user_poisoning = IntFlagValue(options,
428 "allow_user_poisoning=", 1);
429
430 if (FLAG_atexit) {
431 atexit(asan_atexit);
432 }
433
434 FLAG_quarantine_size =
435 IntFlagValue(options, "quarantine_size=", 1UL << 28);
436
437 // interceptors
438 InitializeAsanInterceptors();
439
440 ReplaceSystemMalloc();
Kostya Serebryany5be458c2012-01-09 19:18:27441 InstallSignalHandlers();
Kostya Serebryany019b76f2011-11-30 01:07:02442
443 if (FLAG_v) {
444 Printf("|| `[%p, %p]` || HighMem ||\n", kHighMemBeg, kHighMemEnd);
445 Printf("|| `[%p, %p]` || HighShadow ||\n",
446 kHighShadowBeg, kHighShadowEnd);
447 Printf("|| `[%p, %p]` || ShadowGap ||\n",
448 kShadowGapBeg, kShadowGapEnd);
449 Printf("|| `[%p, %p]` || LowShadow ||\n",
450 kLowShadowBeg, kLowShadowEnd);
451 Printf("|| `[%p, %p]` || LowMem ||\n", kLowMemBeg, kLowMemEnd);
452 Printf("MemToShadow(shadow): %p %p %p %p\n",
453 MEM_TO_SHADOW(kLowShadowBeg),
454 MEM_TO_SHADOW(kLowShadowEnd),
455 MEM_TO_SHADOW(kHighShadowBeg),
456 MEM_TO_SHADOW(kHighShadowEnd));
457 Printf("red_zone=%ld\n", FLAG_redzone);
458 Printf("malloc_context_size=%ld\n", (int)FLAG_malloc_context_size);
459 Printf("fast_unwind=%d\n", (int)FLAG_fast_unwind);
460
461 Printf("SHADOW_SCALE: %lx\n", SHADOW_SCALE);
462 Printf("SHADOW_GRANULARITY: %lx\n", SHADOW_GRANULARITY);
463 Printf("SHADOW_OFFSET: %lx\n", SHADOW_OFFSET);
464 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
465 }
466
467 if (__WORDSIZE == 64) {
468 // Disable core dumper -- it makes little sense to dump 16T+ core.
Kostya Serebryany2b087182012-01-06 02:12:25469 AsanDisableCoreDumper();
Kostya Serebryany019b76f2011-11-30 01:07:02470 }
471
472 {
Kostya Serebryany5be458c2012-01-09 19:18:27473 if (kLowShadowBeg != kLowShadowEnd) {
474 // mmap the low shadow plus one page.
475 ReserveShadowMemoryRange(kLowShadowBeg - kPageSize, kLowShadowEnd);
Kostya Serebryany019b76f2011-11-30 01:07:02476 }
Kostya Serebryany5be458c2012-01-09 19:18:27477 // mmap the high shadow.
478 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
Kostya Serebryany019b76f2011-11-30 01:07:02479 // protect the gap
Kostya Serebryanya7720962011-12-28 23:28:54480 void *prot = AsanMprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
481 CHECK(prot == (void*)kShadowGapBeg);
Kostya Serebryany019b76f2011-11-30 01:07:02482 }
483
484 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
485 // should be set to 1 prior to initializing the threads.
486 asan_inited = 1;
487 asan_init_is_running = false;
488
489 asanThreadRegistry().Init();
490 asanThreadRegistry().GetMain()->ThreadStart();
Kostya Serebryany46c70d32011-12-28 00:59:39491 force_interface_symbols(); // no-op.
Kostya Serebryany019b76f2011-11-30 01:07:02492
493 if (FLAG_v) {
Kostya Serebryany5dfa4da2011-12-01 21:40:52494 Report("AddressSanitizer Init done\n");
Kostya Serebryany019b76f2011-11-30 01:07:02495 }
496}