asan_rtl.cc revision 89c1384464848c1ad041becf8b97936fa10de21b
1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//===-- asan_rtl.cc -------------------------------------------------------===//
2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//
3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//                     The LLVM Compiler Infrastructure
4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//
5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// This file is distributed under the University of Illinois Open Source
6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// License. See LICENSE.TXT for details.
7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//
8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//===----------------------------------------------------------------------===//
9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//
10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// This file is a part of AddressSanitizer, an address sanity checker.
11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//
12474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// Main file of the ASan run-time library.
13474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org//===----------------------------------------------------------------------===//
14474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_allocator.h"
15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_interceptors.h"
16474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_internal.h"
17474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_mapping.h"
18474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_report.h"
19474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_stack.h"
20474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_stats.h"
21474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_thread.h"
22474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "asan_thread_registry.h"
23474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "sanitizer_common/sanitizer_atomic.h"
24474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "sanitizer_common/sanitizer_flags.h"
25474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "sanitizer_common/sanitizer_libc.h"
26474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include "sanitizer_common/sanitizer_symbolizer.h"
27474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
28474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgnamespace __asan {
29474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
30474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orguptr AsanMappingProfile[kAsanMappingProfileSize];
31474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
32474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void AsanDie() {
33474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  static atomic_uint32_t num_calls;
34474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
35474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    // Don't die twice - run a busy loop.
36474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    while (1) { }
37474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
38474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (flags()->sleep_before_dying) {
39474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
40474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    SleepForSeconds(flags()->sleep_before_dying);
41474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
42474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (flags()->unmap_shadow_on_exit) {
43474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    if (kMidMemBeg) {
448b26fe55f3e4daa2311dbd2d95e8ac2b4e080685johannkoenig@chromium.org      UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
458b26fe55f3e4daa2311dbd2d95e8ac2b4e080685johannkoenig@chromium.org      UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
46474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    } else {
47474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org      UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
48474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    }
49474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
50dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  if (death_callback)
51dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    death_callback();
52dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  if (flags()->abort_on_error)
53474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Abort();
54474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  internal__exit(flags()->exitcode);
55474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
56474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
57474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void AsanCheckFailed(const char *file, int line, const char *cond,
58474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org                            u64 v1, u64 v2) {
59474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
60474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org             file, line, cond, (uptr)v1, (uptr)v2);
61474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // FIXME: check for infinite recursion without a thread-local counter here.
6276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  PRINT_CURRENT_STACK();
63474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Die();
64474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
65167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org
66474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// -------------------------- Flags ------------------------- {{{1
67474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic const int kDeafultMallocContextSize = 30;
68474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
69474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic Flags asan_flags;
70474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
71474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgFlags *flags() {
72474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  return &asan_flags;
73474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
74474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
75474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic const char *MaybeCallAsanDefaultOptions() {
76474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  return (&__asan_default_options) ? __asan_default_options() : "";
77474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
78474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
79474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
80167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org#ifdef ASAN_DEFAULT_OPTIONS
816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// Stringize the macro value.
82474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org# define ASAN_STRINGIZE(x) #x
83474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options)
84474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS);
85474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#else
86474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  return "";
87474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif
88474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
89474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
90474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void ParseFlagsFromString(Flags *f, const char *str) {
91474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->quarantine_size, "quarantine_size");
92474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->symbolize, "symbolize");
93474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->verbosity, "verbosity");
94474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->redzone, "redzone");
95474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK(f->redzone >= 16);
96474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK(IsPowerOfTwo(f->redzone));
97474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
98474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->debug, "debug");
99474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->report_globals, "report_globals");
10047265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org  ParseFlag(str, &f->check_initialization_order, "initialization_order");
10147265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org  ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
10247265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org  CHECK((uptr)f->malloc_context_size <= kStackTraceMax);
10347265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org
104474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->replace_str, "replace_str");
105474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->replace_intrin, "replace_intrin");
106474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
107474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
108474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
109474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->exitcode, "exitcode");
110474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
111474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
112474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->handle_segv, "handle_segv");
113474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
114474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
115474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  ParseFlag(str, &f->abort_on_error, "abort_on_error");
1176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  ParseFlag(str, &f->print_stats, "print_stats");
118474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->print_legend, "print_legend");
119474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->atexit, "atexit");
120474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->disable_core, "disable_core");
121474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
122474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->allow_reexec, "allow_reexec");
123474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
124474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->log_path, "log_path");
125474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
126474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
127474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->poison_heap, "poison_heap");
128474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
129474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
130474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
131474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
132474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
1336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatic const char *asan_external_symbolizer;
134474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
135474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid InitializeFlags(Flags *f, const char *env) {
136474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  internal_memset(f, 0, sizeof(*f));
137474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
138474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
139474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->symbolize = (asan_external_symbolizer != 0);
140474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->verbosity = 0;
141474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->redzone = ASAN_ALLOCATOR_VERSION == 2 ? 16 : (ASAN_LOW_MEMORY) ? 64 : 128;
142474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->debug = false;
143474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->report_globals = 1;
144474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->check_initialization_order = false;
145474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->malloc_context_size = kDeafultMallocContextSize;
146474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->replace_str = true;
147474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->replace_intrin = true;
148474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->mac_ignore_invalid_free = false;
149474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->use_fake_stack = true;
150474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->max_malloc_fill_size = 0;
151474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
152474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->allow_user_poisoning = true;
153474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->sleep_before_dying = 0;
154474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->handle_segv = ASAN_NEEDS_SEGV;
155474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->use_sigaltstack = false;
156474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->check_malloc_usable_size = true;
15788b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  f->unmap_shadow_on_exit = false;
15888b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  f->abort_on_error = false;
159474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->print_stats = false;
160474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->print_legend = true;
161474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->atexit = false;
162474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->disable_core = (SANITIZER_WORDSIZE == 64);
163474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->strip_path_prefix = "";
164474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->allow_reexec = true;
165474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->print_full_thread_history = true;
166474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->log_path = 0;
167474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->fast_unwind_on_fatal = false;
168474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->fast_unwind_on_malloc = true;
169474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->poison_heap = true;
170474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // Turn off alloc/dealloc mismatch checker on Mac for now.
1716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // TODO(glider): Fix known issues and enable this back.
17288b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0);;
17388b47b29cc274dd19cddc37c1ce1834d97df282efgalligan@chromium.org  f->use_stack_depot = true;  // Only affects allocator2.
174474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  f->strict_memcmp = true;
175474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
176474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // Override from compile definition.
177474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
178474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
179474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // Override from user-specified string.
180474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
181474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (flags()->verbosity) {
182474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Report("Using the defaults from __asan_default_options: %s\n",
183474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org           MaybeCallAsanDefaultOptions());
184474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
185474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
186474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // Override from command line.
187474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  ParseFlagsFromString(f, env);
188474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
189474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
190474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// -------------------------- Globals --------------------- {{{1
191474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgint asan_inited;
192474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgbool asan_init_is_running;
193474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid (*death_callback)(void);
194474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
195474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if !ASAN_FIXED_MAPPING
196474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orguptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
1976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#endif
1986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
1996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// -------------------------- Misc ---------------- {{{1
2006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid ShowStatsAndAbort() {
201474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  __asan_print_accumulated_stats();
202474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Die();
203474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
204474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
205474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// ---------------------- mmap -------------------- {{{1
206474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// Reserve memory range [beg, end].
207474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void ReserveShadowMemoryRange(uptr beg, uptr end) {
208474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK((beg % GetPageSizeCached()) == 0);
209474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK(((end + 1) % GetPageSizeCached()) == 0);
210474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  uptr size = end - beg + 1;
211474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  void *res = MmapFixedNoReserve(beg, size);
212474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (res != (void*)beg) {
213474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
214474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org           "Perhaps you're using ulimit -v\n", size);
215474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    Abort();
216474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
2176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
2186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
219474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// --------------- LowLevelAllocateCallbac ---------- {{{1
22076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgstatic void OnLowLevelAllocate(uptr ptr, uptr size) {
22176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  PoisonShadow(ptr, size, kAsanInternalHeapMagic);
22276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
22376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
22476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// -------------------------- Run-time entry ------------------- {{{1
22576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org// exported functions
22676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#define ASAN_REPORT_ERROR(type, is_write, size)                     \
22776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgextern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
22876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgvoid __asan_report_ ## type ## size(uptr addr);                \
22976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgvoid __asan_report_ ## type ## size(uptr addr) {               \
23076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  GET_CALLER_PC_BP_SP;                                              \
23176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  __asan_report_error(pc, bp, sp, addr, is_write, size);            \
23276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org}
23376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
23476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(load, false, 1)
23576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(load, false, 2)
23676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(load, false, 4)
23776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(load, false, 8)
23876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(load, false, 16)
23976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(store, true, 1)
24076e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(store, true, 2)
24176e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(store, true, 4)
24276e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(store, true, 8)
24376e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgASAN_REPORT_ERROR(store, true, 16)
24476e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org
24576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org#define ASAN_REPORT_ERROR_N(type, is_write)                    \
24676e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgextern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
24776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgvoid __asan_report_ ## type ## _n(uptr addr, uptr size);       \
24876e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.orgvoid __asan_report_ ## type ## _n(uptr addr, uptr size) {      \
24976e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  GET_CALLER_PC_BP_SP;                                         \
250474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  __asan_report_error(pc, bp, sp, addr, is_write, size);       \
251474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
252474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
2536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgASAN_REPORT_ERROR_N(load, false)
2546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgASAN_REPORT_ERROR_N(store, true)
2556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
2566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// Force the linker to keep the symbols for various ASan interface functions.
2576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// We want to keep those in the executable in order to let the instrumented
2586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// dynamic libraries access the symbol even if it is not used by the executable
2596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org// itself. This should help if the build system is removing dead code at link
260474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// time.
261474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic NOINLINE void force_interface_symbols() {
262474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  volatile int fake_condition = 0;  // prevent dead condition elimination.
263474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // __asan_report_* functions are noreturn, so we need a switch to prevent
264474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // the compiler from removing any of them.
265474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  switch (fake_condition) {
266474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 1: __asan_report_load1(0); break;
267474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 2: __asan_report_load2(0); break;
268474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 3: __asan_report_load4(0); break;
269474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 4: __asan_report_load8(0); break;
270167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    case 5: __asan_report_load16(0); break;
271167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    case 6: __asan_report_store1(0); break;
2726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 7: __asan_report_store2(0); break;
273167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    case 8: __asan_report_store4(0); break;
274474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 9: __asan_report_store8(0); break;
275474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 10: __asan_report_store16(0); break;
276474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 12: __asan_register_globals(0, 0); break;
277474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 13: __asan_unregister_globals(0, 0); break;
278474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 14: __asan_set_death_callback(0); break;
279474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 15: __asan_set_error_report_callback(0); break;
280474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 16: __asan_handle_no_return(); break;
281474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 17: __asan_address_is_poisoned(0); break;
282474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 18: __asan_get_allocated_size(0); break;
283474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 19: __asan_get_current_allocated_bytes(); break;
2846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 20: __asan_get_estimated_allocated_size(0); break;
2856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 21: __asan_get_free_bytes(); break;
2866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 22: __asan_get_heap_size(); break;
287474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 23: __asan_get_ownership(0); break;
288474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 24: __asan_get_unmapped_bytes(); break;
289474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 25: __asan_poison_memory_region(0, 0); break;
290474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 26: __asan_unpoison_memory_region(0, 0); break;
291474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 27: __asan_set_error_exit_code(0); break;
292474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    case 28: __asan_stack_free(0, 0, 0); break;
2936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 29: __asan_stack_malloc(0, 0); break;
2946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 30: __asan_before_dynamic_init(0, 0); break;
2956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 31: __asan_after_dynamic_init(); break;
2966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 32: __asan_poison_stack_memory(0, 0); break;
2976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 33: __asan_unpoison_stack_memory(0, 0); break;
2986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 34: __asan_region_is_poisoned(0, 0); break;
2996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    case 35: __asan_describe_address(0); break;
3006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
3016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
30247265f8fe3a36a426773454ad90d20c9aa616c24johannkoenig@chromium.org
3036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatic void asan_atexit() {
3046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  Printf("AddressSanitizer exit stats:\n");
30576e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org  __asan_print_accumulated_stats();
3066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Print AsanMappingProfile.
3076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
30841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    if (AsanMappingProfile[i] == 0) continue;
3096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
3106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  }
3116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
3126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatic void InitializeHighMemEnd() {
3146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#if !ASAN_FIXED_MAPPING
3156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#if SANITIZER_WORDSIZE == 64
3166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org# if defined(__powerpc64__)
317474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // FIXME:
318474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
319474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // We somehow need to figure our which one we are using now and choose
3206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
3216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Note that with 'ulimit -s unlimited' the stack is moved away from the top
3226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // of the address space, so simply checking the stack address is not enough.
3236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  kHighMemEnd = (1ULL << 44) - 1;  // 0x00000fffffffffffUL
3246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org# else
3256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  kHighMemEnd = (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
326474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org# endif
327474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#else  // SANITIZER_WORDSIZE == 32
328474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  kHighMemEnd = (1ULL << 32) - 1;  // 0xffffffff;
329474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif  // SANITIZER_WORDSIZE
330474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif  // !ASAN_FIXED_MAPPING
331474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
332474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
333474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgstatic void ProtectGap(uptr a, uptr size) {
334474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK_EQ(a, (uptr)Mprotect(a, size));
335474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
336474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
3376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatic void PrintAddressSpaceLayout() {
3386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  Printf("|| `[%p, %p]` || HighMem    ||\n",
3396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org         (void*)kHighMemBeg, (void*)kHighMemEnd);
3406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  Printf("|| `[%p, %p]` || HighShadow ||\n",
3416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org         (void*)kHighShadowBeg, (void*)kHighShadowEnd);
3426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  if (kMidMemBeg) {
3436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
3446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org           (void*)kShadowGap3Beg, (void*)kShadowGap3End);
345d95585fb0ec024f6abd96f7b02e0df58019d46afjohannkoenig@chromium.org    Printf("|| `[%p, %p]` || MidMem     ||\n",
3466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org           (void*)kMidMemBeg, (void*)kMidMemEnd);
3476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
3486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org           (void*)kShadowGap2Beg, (void*)kShadowGap2End);
3496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    Printf("|| `[%p, %p]` || MidShadow  ||\n",
3506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org           (void*)kMidShadowBeg, (void*)kMidShadowEnd);
351474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
352474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("|| `[%p, %p]` || ShadowGap  ||\n",
353167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org         (void*)kShadowGapBeg, (void*)kShadowGapEnd);
354167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org  if (kLowShadowBeg) {
355167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    Printf("|| `[%p, %p]` || LowShadow  ||\n",
356167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org           (void*)kLowShadowBeg, (void*)kLowShadowEnd);
357167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org    Printf("|| `[%p, %p]` || LowMem     ||\n",
358167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org           (void*)kLowMemBeg, (void*)kLowMemEnd);
359167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org  }
360167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org  Printf("MemToShadow(shadow): %p %p %p %p",
361167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org         (void*)MEM_TO_SHADOW(kLowShadowBeg),
362167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org         (void*)MEM_TO_SHADOW(kLowShadowEnd),
363167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org         (void*)MEM_TO_SHADOW(kHighShadowBeg),
364474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org         (void*)MEM_TO_SHADOW(kHighShadowEnd));
365474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (kMidMemBeg) {
36641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    Printf(" %p %p",
367474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org           (void*)MEM_TO_SHADOW(kMidShadowBeg),
368474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org           (void*)MEM_TO_SHADOW(kMidShadowEnd));
369474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  }
37041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  Printf("\n");
371474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("red_zone=%zu\n", (uptr)flags()->redzone);
372474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
373474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
374474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
375474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
376474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
377474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
378474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (kMidMemBeg)
379474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org    CHECK(kMidShadowBeg > kLowShadowEnd &&
380474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org          kMidMemBeg > kMidShadowEnd &&
381474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org          kHighShadowBeg > kMidMemEnd);
382474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
383474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
3846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}  // namespace __asan
3856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
386474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org// ---------------------- Interface ---------------- {{{1
387474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgusing namespace __asan;  // NOLINT
388474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
389474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#if !SANITIZER_SUPPORTS_WEAK_HOOKS
390474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgextern "C" {
391474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgSANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
392474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgconst char* __asan_default_options() { return ""; }
3936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}  // extern "C"
3946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#endif
3956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
3966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint NOINLINE __asan_set_error_exit_code(int exit_code) {
397474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  int old = flags()->exitcode;
398474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  flags()->exitcode = exit_code;
399474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  return old;
4006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org}
4016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
4026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid NOINLINE __asan_handle_no_return() {
403474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  int local_stack;
404474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  AsanThread *curr_thread = GetCurrentThread();
4056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  CHECK(curr_thread);
4066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  uptr PageSize = GetPageSizeCached();
407474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  uptr top = curr_thread->stack_top();
408474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
409474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  PoisonShadow(bottom, top - bottom, 0);
410474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
411474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
4126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid NOINLINE __asan_set_death_callback(void (*callback)(void)) {
413474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  death_callback = callback;
414474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org}
415474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org
416474eb7536515fb785e925cc9375d22817c416851hclam@chromium.orgvoid __asan_init() {
417474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  if (asan_inited) return;
418474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  SanitizerToolName = "AddressSanitizer";
419dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  CHECK(!asan_init_is_running && "ASan init calls itself!");
4206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  asan_init_is_running = true;
4216fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  InitializeHighMemEnd();
4226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
4236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  // Make sure we are not statically linked.
4246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org  AsanDoesNotSupportStaticLinkage();
4256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
426474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  // Install tool-specific callbacks in sanitizer_common.
427474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org  SetDieCallback(AsanDie);
42841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  SetCheckFailedCallback(AsanCheckFailed);
42941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
43041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
43141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // Check if external symbolizer is defined before parsing the flags.
43241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  asan_external_symbolizer = GetEnv("ASAN_SYMBOLIZER_PATH");
433dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  // Initialize flags. This must be done early, because most of the
434dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  // initialization steps look at flags().
435dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  const char *options = GetEnv("ASAN_OPTIONS");
436dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org  InitializeFlags(flags(), options);
4378b26fe55f3e4daa2311dbd2d95e8ac2b4e080685johannkoenig@chromium.org  __sanitizer_set_report_path(flags()->log_path);
438
439  if (flags()->verbosity && options) {
440    Report("Parsed ASAN_OPTIONS: %s\n", options);
441  }
442
443  // Re-exec ourselves if we need to set additional env or command line args.
444  MaybeReexec();
445
446  // Setup internal allocator callback.
447  SetLowLevelAllocateCallback(OnLowLevelAllocate);
448
449  if (flags()->atexit) {
450    Atexit(asan_atexit);
451  }
452
453  // interceptors
454  InitializeAsanInterceptors();
455
456  ReplaceSystemMalloc();
457  ReplaceOperatorsNewAndDelete();
458
459  uptr shadow_start = kLowShadowBeg;
460  if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
461  uptr shadow_end = kHighShadowEnd;
462  bool full_shadow_is_available =
463      MemoryRangeIsAvailable(shadow_start, shadow_end);
464
465#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
466  if (!full_shadow_is_available) {
467    kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
468    kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
469  }
470#endif
471
472  if (flags()->verbosity)
473    PrintAddressSpaceLayout();
474
475  if (flags()->disable_core) {
476    DisableCoreDumper();
477  }
478
479  if (full_shadow_is_available) {
480    // mmap the low shadow plus at least one page at the left.
481    if (kLowShadowBeg)
482      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
483    // mmap the high shadow.
484    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
485    // protect the gap.
486    ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
487  } else if (kMidMemBeg &&
488      MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
489      MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) {
490    CHECK(kLowShadowBeg != kLowShadowEnd);
491    // mmap the low shadow plus at least one page at the left.
492    ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
493    // mmap the mid shadow.
494    ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
495    // mmap the high shadow.
496    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
497    // protect the gaps.
498    ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
499    ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
500    ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
501  } else {
502    Report("Shadow memory range interleaves with an existing memory mapping. "
503           "ASan cannot proceed correctly. ABORTING.\n");
504    DumpProcessMap();
505    Die();
506  }
507
508  InstallSignalHandlers();
509  // Start symbolizer process if necessary.
510  if (flags()->symbolize && asan_external_symbolizer &&
511      asan_external_symbolizer[0]) {
512    InitializeExternalSymbolizer(asan_external_symbolizer);
513  }
514
515  // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
516  // should be set to 1 prior to initializing the threads.
517  asan_inited = 1;
518  asan_init_is_running = false;
519
520  asanThreadRegistry().Init();
521  asanThreadRegistry().GetMain()->ThreadStart();
522  force_interface_symbols();  // no-op.
523
524  InitializeAllocator();
525
526  if (flags()->verbosity) {
527    Report("AddressSanitizer Init done\n");
528  }
529}
530