llvm-project
643 строки · 22.4 Кб
1//===-- asan_rtl.cpp ------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// Main file of the ASan run-time library.
12//===----------------------------------------------------------------------===//
13
14#include "asan_activation.h"15#include "asan_allocator.h"16#include "asan_fake_stack.h"17#include "asan_interceptors.h"18#include "asan_interface_internal.h"19#include "asan_internal.h"20#include "asan_mapping.h"21#include "asan_poisoning.h"22#include "asan_report.h"23#include "asan_stack.h"24#include "asan_stats.h"25#include "asan_suppressions.h"26#include "asan_thread.h"27#include "lsan/lsan_common.h"28#include "sanitizer_common/sanitizer_atomic.h"29#include "sanitizer_common/sanitizer_flags.h"30#include "sanitizer_common/sanitizer_interface_internal.h"31#include "sanitizer_common/sanitizer_libc.h"32#include "sanitizer_common/sanitizer_symbolizer.h"33#include "ubsan/ubsan_init.h"34#include "ubsan/ubsan_platform.h"35
36uptr __asan_shadow_memory_dynamic_address; // Global interface symbol.37int __asan_option_detect_stack_use_after_return; // Global interface symbol.38uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.39
40namespace __asan {41
42uptr AsanMappingProfile[kAsanMappingProfileSize];43
44static void AsanDie() {45static atomic_uint32_t num_calls;46if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {47// Don't die twice - run a busy loop.48while (1) {49internal_sched_yield();50}51}52if (common_flags()->print_module_map >= 1)53DumpProcessMap();54
55WaitForDebugger(flags()->sleep_before_dying, "before dying");56
57if (flags()->unmap_shadow_on_exit) {58if (kMidMemBeg) {59UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);60UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);61} else {62if (kHighShadowEnd)63UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);64}65}66}
67
68static void CheckUnwind() {69GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check);70stack.Print();71}
72
73// -------------------------- Globals --------------------- {{{1
74static StaticSpinMutex asan_inited_mutex;75static atomic_uint8_t asan_inited = {0};76
77static void SetAsanInited() {78atomic_store(&asan_inited, 1, memory_order_release);79}
80
81bool AsanInited() {82return atomic_load(&asan_inited, memory_order_acquire) == 1;83}
84
85bool replace_intrin_cached;86
87#if !ASAN_FIXED_MAPPING88uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;89#endif90
91// -------------------------- Misc ---------------- {{{1
92void ShowStatsAndAbort() {93__asan_print_accumulated_stats();94Die();95}
96
97NOINLINE
98static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size,99int exp_arg, bool fatal) {100GET_CALLER_PC_BP_SP;101ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);102}
103
104// --------------- LowLevelAllocateCallbac ---------- {{{1
105static void OnLowLevelAllocate(uptr ptr, uptr size) {106PoisonShadow(ptr, size, kAsanInternalHeapMagic);107}
108
109// -------------------------- Run-time entry ------------------- {{{1
110// exported functions
111#define ASAN_REPORT_ERROR(type, is_write, size) \112extern "C" NOINLINE INTERFACE_ATTRIBUTE \113void __asan_report_ ## type ## size(uptr addr) { \114GET_CALLER_PC_BP_SP; \115ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \116} \117extern "C" NOINLINE INTERFACE_ATTRIBUTE \118void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \119GET_CALLER_PC_BP_SP; \120ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \121} \122extern "C" NOINLINE INTERFACE_ATTRIBUTE \123void __asan_report_ ## type ## size ## _noabort(uptr addr) { \124GET_CALLER_PC_BP_SP; \125ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \126} \127128ASAN_REPORT_ERROR(load, false, 1)129ASAN_REPORT_ERROR(load, false, 2)130ASAN_REPORT_ERROR(load, false, 4)131ASAN_REPORT_ERROR(load, false, 8)132ASAN_REPORT_ERROR(load, false, 16)133ASAN_REPORT_ERROR(store, true, 1)134ASAN_REPORT_ERROR(store, true, 2)135ASAN_REPORT_ERROR(store, true, 4)136ASAN_REPORT_ERROR(store, true, 8)137ASAN_REPORT_ERROR(store, true, 16)138
139#define ASAN_REPORT_ERROR_N(type, is_write) \140extern "C" NOINLINE INTERFACE_ATTRIBUTE \141void __asan_report_ ## type ## _n(uptr addr, uptr size) { \142GET_CALLER_PC_BP_SP; \143ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \144} \145extern "C" NOINLINE INTERFACE_ATTRIBUTE \146void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \147GET_CALLER_PC_BP_SP; \148ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \149} \150extern "C" NOINLINE INTERFACE_ATTRIBUTE \151void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \152GET_CALLER_PC_BP_SP; \153ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \154} \155156ASAN_REPORT_ERROR_N(load, false)157ASAN_REPORT_ERROR_N(store, true)158
159#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \160uptr sp = MEM_TO_SHADOW(addr); \161uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \162: *reinterpret_cast<u16 *>(sp); \163if (UNLIKELY(s)) { \164if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \165((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \166(s8)s)) { \167ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \168} \169}170
171#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \172extern "C" NOINLINE INTERFACE_ATTRIBUTE \173void __asan_##type##size(uptr addr) { \174ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \175} \176extern "C" NOINLINE INTERFACE_ATTRIBUTE \177void __asan_exp_##type##size(uptr addr, u32 exp) { \178ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \179} \180extern "C" NOINLINE INTERFACE_ATTRIBUTE \181void __asan_##type##size ## _noabort(uptr addr) { \182ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \183} \184185ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)186ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)187ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4)188ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8)189ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16)190ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1)191ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2)192ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4)193ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)194ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)195
196extern "C"197NOINLINE INTERFACE_ATTRIBUTE
198void __asan_loadN(uptr addr, uptr size) {199if ((addr = __asan_region_is_poisoned(addr, size))) {200GET_CALLER_PC_BP_SP;201ReportGenericError(pc, bp, sp, addr, false, size, 0, true);202}203}
204
205extern "C"206NOINLINE INTERFACE_ATTRIBUTE
207void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {208if ((addr = __asan_region_is_poisoned(addr, size))) {209GET_CALLER_PC_BP_SP;210ReportGenericError(pc, bp, sp, addr, false, size, exp, true);211}212}
213
214extern "C"215NOINLINE INTERFACE_ATTRIBUTE
216void __asan_loadN_noabort(uptr addr, uptr size) {217if ((addr = __asan_region_is_poisoned(addr, size))) {218GET_CALLER_PC_BP_SP;219ReportGenericError(pc, bp, sp, addr, false, size, 0, false);220}221}
222
223extern "C"224NOINLINE INTERFACE_ATTRIBUTE
225void __asan_storeN(uptr addr, uptr size) {226if ((addr = __asan_region_is_poisoned(addr, size))) {227GET_CALLER_PC_BP_SP;228ReportGenericError(pc, bp, sp, addr, true, size, 0, true);229}230}
231
232extern "C"233NOINLINE INTERFACE_ATTRIBUTE
234void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {235if ((addr = __asan_region_is_poisoned(addr, size))) {236GET_CALLER_PC_BP_SP;237ReportGenericError(pc, bp, sp, addr, true, size, exp, true);238}239}
240
241extern "C"242NOINLINE INTERFACE_ATTRIBUTE
243void __asan_storeN_noabort(uptr addr, uptr size) {244if ((addr = __asan_region_is_poisoned(addr, size))) {245GET_CALLER_PC_BP_SP;246ReportGenericError(pc, bp, sp, addr, true, size, 0, false);247}248}
249
250// Force the linker to keep the symbols for various ASan interface functions.
251// We want to keep those in the executable in order to let the instrumented
252// dynamic libraries access the symbol even if it is not used by the executable
253// itself. This should help if the build system is removing dead code at link
254// time.
255static NOINLINE void force_interface_symbols() {256volatile int fake_condition = 0; // prevent dead condition elimination.257// __asan_report_* functions are noreturn, so we need a switch to prevent258// the compiler from removing any of them.259// clang-format off260switch (fake_condition) {261case 1: __asan_report_load1(0); break;262case 2: __asan_report_load2(0); break;263case 3: __asan_report_load4(0); break;264case 4: __asan_report_load8(0); break;265case 5: __asan_report_load16(0); break;266case 6: __asan_report_load_n(0, 0); break;267case 7: __asan_report_store1(0); break;268case 8: __asan_report_store2(0); break;269case 9: __asan_report_store4(0); break;270case 10: __asan_report_store8(0); break;271case 11: __asan_report_store16(0); break;272case 12: __asan_report_store_n(0, 0); break;273case 13: __asan_report_exp_load1(0, 0); break;274case 14: __asan_report_exp_load2(0, 0); break;275case 15: __asan_report_exp_load4(0, 0); break;276case 16: __asan_report_exp_load8(0, 0); break;277case 17: __asan_report_exp_load16(0, 0); break;278case 18: __asan_report_exp_load_n(0, 0, 0); break;279case 19: __asan_report_exp_store1(0, 0); break;280case 20: __asan_report_exp_store2(0, 0); break;281case 21: __asan_report_exp_store4(0, 0); break;282case 22: __asan_report_exp_store8(0, 0); break;283case 23: __asan_report_exp_store16(0, 0); break;284case 24: __asan_report_exp_store_n(0, 0, 0); break;285case 25: __asan_register_globals(nullptr, 0); break;286case 26: __asan_unregister_globals(nullptr, 0); break;287case 27: __asan_set_death_callback(nullptr); break;288case 28: __asan_set_error_report_callback(nullptr); break;289case 29: __asan_handle_no_return(); break;290case 30: __asan_address_is_poisoned(nullptr); break;291case 31: __asan_poison_memory_region(nullptr, 0); break;292case 32: __asan_unpoison_memory_region(nullptr, 0); break;293case 34: __asan_before_dynamic_init(nullptr); break;294case 35: __asan_after_dynamic_init(); break;295case 36: __asan_poison_stack_memory(0, 0); break;296case 37: __asan_unpoison_stack_memory(0, 0); break;297case 38: __asan_region_is_poisoned(0, 0); break;298case 39: __asan_describe_address(0); break;299case 40: __asan_set_shadow_00(0, 0); break;300case 41: __asan_set_shadow_01(0, 0); break;301case 42: __asan_set_shadow_02(0, 0); break;302case 43: __asan_set_shadow_03(0, 0); break;303case 44: __asan_set_shadow_04(0, 0); break;304case 45: __asan_set_shadow_05(0, 0); break;305case 46: __asan_set_shadow_06(0, 0); break;306case 47: __asan_set_shadow_07(0, 0); break;307case 48: __asan_set_shadow_f1(0, 0); break;308case 49: __asan_set_shadow_f2(0, 0); break;309case 50: __asan_set_shadow_f3(0, 0); break;310case 51: __asan_set_shadow_f5(0, 0); break;311case 52: __asan_set_shadow_f8(0, 0); break;312}313// clang-format on314}
315
316static void asan_atexit() {317Printf("AddressSanitizer exit stats:\n");318__asan_print_accumulated_stats();319// Print AsanMappingProfile.320for (uptr i = 0; i < kAsanMappingProfileSize; i++) {321if (AsanMappingProfile[i] == 0) continue;322Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);323}324}
325
326static void InitializeHighMemEnd() {327#if !ASAN_FIXED_MAPPING328kHighMemEnd = GetMaxUserVirtualAddress();329// Increase kHighMemEnd to make sure it's properly330// aligned together with kHighMemBeg:331kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1;332#endif // !ASAN_FIXED_MAPPING333CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0);334}
335
336void PrintAddressSpaceLayout() {337if (kHighMemBeg) {338Printf("|| `[%p, %p]` || HighMem ||\n",339(void*)kHighMemBeg, (void*)kHighMemEnd);340Printf("|| `[%p, %p]` || HighShadow ||\n",341(void*)kHighShadowBeg, (void*)kHighShadowEnd);342}343if (kMidMemBeg) {344Printf("|| `[%p, %p]` || ShadowGap3 ||\n",345(void*)kShadowGap3Beg, (void*)kShadowGap3End);346Printf("|| `[%p, %p]` || MidMem ||\n",347(void*)kMidMemBeg, (void*)kMidMemEnd);348Printf("|| `[%p, %p]` || ShadowGap2 ||\n",349(void*)kShadowGap2Beg, (void*)kShadowGap2End);350Printf("|| `[%p, %p]` || MidShadow ||\n",351(void*)kMidShadowBeg, (void*)kMidShadowEnd);352}353Printf("|| `[%p, %p]` || ShadowGap ||\n",354(void*)kShadowGapBeg, (void*)kShadowGapEnd);355if (kLowShadowBeg) {356Printf("|| `[%p, %p]` || LowShadow ||\n",357(void*)kLowShadowBeg, (void*)kLowShadowEnd);358Printf("|| `[%p, %p]` || LowMem ||\n",359(void*)kLowMemBeg, (void*)kLowMemEnd);360}361Printf("MemToShadow(shadow): %p %p",362(void*)MEM_TO_SHADOW(kLowShadowBeg),363(void*)MEM_TO_SHADOW(kLowShadowEnd));364if (kHighMemBeg) {365Printf(" %p %p",366(void*)MEM_TO_SHADOW(kHighShadowBeg),367(void*)MEM_TO_SHADOW(kHighShadowEnd));368}369if (kMidMemBeg) {370Printf(" %p %p",371(void*)MEM_TO_SHADOW(kMidShadowBeg),372(void*)MEM_TO_SHADOW(kMidShadowEnd));373}374Printf("\n");375Printf("redzone=%zu\n", (uptr)flags()->redzone);376Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone);377Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb);378Printf("thread_local_quarantine_size_kb=%zuK\n",379(uptr)flags()->thread_local_quarantine_size_kb);380Printf("malloc_context_size=%zu\n",381(uptr)common_flags()->malloc_context_size);382
383Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE);384Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY);385Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)ASAN_SHADOW_OFFSET);386CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7);387if (kMidMemBeg)388CHECK(kMidShadowBeg > kLowShadowEnd &&389kMidMemBeg > kMidShadowEnd &&390kHighShadowBeg > kMidMemEnd);391}
392
393static bool AsanInitInternal() {394if (LIKELY(AsanInited()))395return true;396SanitizerToolName = "AddressSanitizer";397
398CacheBinaryName();399
400// Initialize flags. This must be done early, because most of the401// initialization steps look at flags().402InitializeFlags();403
404WaitForDebugger(flags()->sleep_before_init, "before init");405
406// Stop performing init at this point if we are being loaded via407// dlopen() and the platform supports it.408if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {409VReport(1, "AddressSanitizer init is being performed for dlopen().\n");410return false;411}412
413// Make sure we are not statically linked.414__interception::DoesNotSupportStaticLinking();415AsanCheckIncompatibleRT();416AsanCheckDynamicRTPrereqs();417AvoidCVE_2016_2143();418
419SetCanPoisonMemory(flags()->poison_heap);420SetMallocContextSize(common_flags()->malloc_context_size);421
422InitializePlatformExceptionHandlers();423
424InitializeHighMemEnd();425
426// Install tool-specific callbacks in sanitizer_common.427AddDieCallback(AsanDie);428SetCheckUnwindCallback(CheckUnwind);429SetPrintfAndReportCallback(AppendToErrorMessageBuffer);430
431__sanitizer_set_report_path(common_flags()->log_path);432
433__asan_option_detect_stack_use_after_return =434flags()->detect_stack_use_after_return;435
436__sanitizer::InitializePlatformEarly();437
438// Setup internal allocator callback.439SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY);440SetLowLevelAllocateCallback(OnLowLevelAllocate);441
442InitializeAsanInterceptors();443CheckASLR();444
445// Enable system log ("adb logcat") on Android.446// Doing this before interceptors are initialized crashes in:447// AsanInitInternal -> android_log_write -> __interceptor_strcmp448AndroidLogInit();449
450ReplaceSystemMalloc();451
452DisableCoreDumperIfNecessary();453
454InitializeShadowMemory();455
456AsanTSDInit(PlatformTSDDtor);457InstallDeadlySignalHandlers(AsanOnDeadlySignal);458
459AllocatorOptions allocator_options;460allocator_options.SetFrom(flags(), common_flags());461InitializeAllocator(allocator_options);462
463if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL)464MaybeStartBackgroudThread();465
466// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited467// should be set to 1 prior to initializing the threads.468replace_intrin_cached = flags()->replace_intrin;469SetAsanInited();470
471if (flags()->atexit)472Atexit(asan_atexit);473
474InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);475
476// Now that ASan runtime is (mostly) initialized, deactivate it if477// necessary, so that it can be re-activated when requested.478if (flags()->start_deactivated)479AsanDeactivate();480
481// interceptors482InitTlsSize();483
484// Create main thread.485AsanThread *main_thread = CreateMainThread();486CHECK_EQ(0, main_thread->tid());487force_interface_symbols(); // no-op.488SanitizerInitializeUnwinder();489
490if (CAN_SANITIZE_LEAKS) {491__lsan::InitCommonLsan();492InstallAtExitCheckLeaks();493}494
495InstallAtForkHandler();496
497#if CAN_SANITIZE_UB498__ubsan::InitAsPlugin();499#endif500
501InitializeSuppressions();502
503if (CAN_SANITIZE_LEAKS) {504// LateInitialize() calls dlsym, which can allocate an error string buffer505// in the TLS. Let's ignore the allocation to avoid reporting a leak.506__lsan::ScopedInterceptorDisabler disabler;507Symbolizer::LateInitialize();508} else {509Symbolizer::LateInitialize();510}511
512VReport(1, "AddressSanitizer Init done\n");513
514WaitForDebugger(flags()->sleep_after_init, "after init");515
516return true;517}
518
519// Initialize as requested from some part of ASan runtime library (interceptors,
520// allocator, etc).
521void AsanInitFromRtl() {522if (LIKELY(AsanInited()))523return;524SpinMutexLock lock(&asan_inited_mutex);525AsanInitInternal();526}
527
528bool TryAsanInitFromRtl() {529if (LIKELY(AsanInited()))530return true;531if (!asan_inited_mutex.TryLock())532return false;533bool result = AsanInitInternal();534asan_inited_mutex.Unlock();535return result;536}
537
538#if ASAN_DYNAMIC539// Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable
540// (and thus normal initializers from .preinit_array or modules haven't run).
541
542class AsanInitializer {543public:544AsanInitializer() {545AsanInitFromRtl();546}547};548
549static AsanInitializer asan_initializer;550#endif // ASAN_DYNAMIC551
552void UnpoisonStack(uptr bottom, uptr top, const char *type) {553static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M554if (top - bottom > kMaxExpectedCleanupSize) {555static bool reported_warning = false;556if (reported_warning)557return;558reported_warning = true;559Report(560"WARNING: ASan is ignoring requested __asan_handle_no_return: "561"stack type: %s top: %p; bottom %p; size: %p (%zd)\n"562"False positive error reports may follow\n"563"For details see "564"https://github.com/google/sanitizers/issues/189\n",565type, (void *)top, (void *)bottom, (void *)(top - bottom),566top - bottom);567return;568}569PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0);570}
571
572static void UnpoisonDefaultStack() {573uptr bottom, top;574
575if (AsanThread *curr_thread = GetCurrentThread()) {576int local_stack;577const uptr page_size = GetPageSizeCached();578top = curr_thread->stack_top();579bottom = ((uptr)&local_stack - page_size) & ~(page_size - 1);580} else {581CHECK(!SANITIZER_FUCHSIA);582// If we haven't seen this thread, try asking the OS for stack bounds.583uptr tls_addr, tls_size, stack_size;584GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr,585&tls_size);586top = bottom + stack_size;587}588
589UnpoisonStack(bottom, top, "default");590}
591
592static void UnpoisonFakeStack() {593AsanThread *curr_thread = GetCurrentThread();594if (!curr_thread)595return;596FakeStack *stack = curr_thread->get_fake_stack();597if (!stack)598return;599stack->HandleNoReturn();600}
601
602} // namespace __asan603
604// ---------------------- Interface ---------------- {{{1
605using namespace __asan;606
607void NOINLINE __asan_handle_no_return() {608if (UNLIKELY(!AsanInited()))609return;610
611if (!PlatformUnpoisonStacks())612UnpoisonDefaultStack();613
614UnpoisonFakeStack();615}
616
617extern "C" void *__asan_extra_spill_area() {618AsanThread *t = GetCurrentThread();619CHECK(t);620return t->extra_spill_area();621}
622
623void __asan_handle_vfork(void *sp) {624AsanThread *t = GetCurrentThread();625CHECK(t);626uptr bottom = t->stack_bottom();627PoisonShadow(bottom, (uptr)sp - bottom, 0);628}
629
630void NOINLINE __asan_set_death_callback(void (*callback)(void)) {631SetUserDieCallback(callback);632}
633
634// Initialize as requested from instrumented application code.
635// We use this call as a trigger to wake up ASan from deactivated state.
636void __asan_init() {637AsanActivate();638AsanInitFromRtl();639}
640
641void __asan_version_mismatch_check() {642// Do nothing.643}
644