168d75effSDimitry Andric //===-- msan.cpp ----------------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of MemorySanitizer. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // MemorySanitizer runtime. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "msan.h" 1581ad6265SDimitry Andric 1668d75effSDimitry Andric #include "msan_chained_origin_depot.h" 1768d75effSDimitry Andric #include "msan_origin.h" 1881ad6265SDimitry Andric #include "msan_poisoning.h" 1968d75effSDimitry Andric #include "msan_report.h" 2068d75effSDimitry Andric #include "msan_thread.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 2481ad6265SDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 2581ad6265SDimitry Andric #include "sanitizer_common/sanitizer_interface_internal.h" 2668d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 2768d75effSDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h" 2881ad6265SDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 2968d75effSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h" 3068d75effSDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 3168d75effSDimitry Andric #include "ubsan/ubsan_flags.h" 3268d75effSDimitry Andric #include "ubsan/ubsan_init.h" 3368d75effSDimitry Andric 3468d75effSDimitry Andric // ACHTUNG! No system header includes in this file. 3568d75effSDimitry Andric 3668d75effSDimitry Andric using namespace __sanitizer; 3768d75effSDimitry Andric 3868d75effSDimitry Andric // Globals. 3968d75effSDimitry Andric static THREADLOCAL int msan_expect_umr = 0; 4068d75effSDimitry Andric static THREADLOCAL int msan_expected_umr_found = 0; 4168d75effSDimitry Andric 4268d75effSDimitry Andric // Function argument shadow. Each argument starts at the next available 8-byte 4368d75effSDimitry Andric // aligned address. 4468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 4568d75effSDimitry Andric THREADLOCAL u64 __msan_param_tls[kMsanParamTlsSize / sizeof(u64)]; 4668d75effSDimitry Andric 4768d75effSDimitry Andric // Function argument origin. Each argument starts at the same offset as the 4868d75effSDimitry Andric // corresponding shadow in (__msan_param_tls). Slightly weird, but changing this 4968d75effSDimitry Andric // would break compatibility with older prebuilt binaries. 5068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5168d75effSDimitry Andric THREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 5268d75effSDimitry Andric 5368d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5468d75effSDimitry Andric THREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSize / sizeof(u64)]; 5568d75effSDimitry Andric 5668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5768d75effSDimitry Andric THREADLOCAL u32 __msan_retval_origin_tls; 5868d75effSDimitry Andric 59*0fca6ea1SDimitry Andric alignas(16) SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64 60*0fca6ea1SDimitry Andric __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; 6168d75effSDimitry Andric 62*0fca6ea1SDimitry Andric alignas(16) SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 63*0fca6ea1SDimitry Andric __msan_va_arg_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 6468d75effSDimitry Andric 6568d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6668d75effSDimitry Andric THREADLOCAL u64 __msan_va_arg_overflow_size_tls; 6768d75effSDimitry Andric 6868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6968d75effSDimitry Andric THREADLOCAL u32 __msan_origin_tls; 7068d75effSDimitry Andric 7168d75effSDimitry Andric extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; 7268d75effSDimitry Andric 7368d75effSDimitry Andric int __msan_get_track_origins() { 7468d75effSDimitry Andric return &__msan_track_origins ? __msan_track_origins : 0; 7568d75effSDimitry Andric } 7668d75effSDimitry Andric 7768d75effSDimitry Andric extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going; 7868d75effSDimitry Andric 7968d75effSDimitry Andric namespace __msan { 8068d75effSDimitry Andric 8181ad6265SDimitry Andric static THREADLOCAL int is_in_symbolizer_or_unwinder; 8281ad6265SDimitry Andric static void EnterSymbolizerOrUnwider() { ++is_in_symbolizer_or_unwinder; } 8381ad6265SDimitry Andric static void ExitSymbolizerOrUnwider() { --is_in_symbolizer_or_unwinder; } 8481ad6265SDimitry Andric bool IsInSymbolizerOrUnwider() { return is_in_symbolizer_or_unwinder; } 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric struct UnwinderScope { 8781ad6265SDimitry Andric UnwinderScope() { EnterSymbolizerOrUnwider(); } 8881ad6265SDimitry Andric ~UnwinderScope() { ExitSymbolizerOrUnwider(); } 8981ad6265SDimitry Andric }; 9068d75effSDimitry Andric 9168d75effSDimitry Andric static Flags msan_flags; 9268d75effSDimitry Andric 9381ad6265SDimitry Andric Flags *flags() { return &msan_flags; } 9468d75effSDimitry Andric 9568d75effSDimitry Andric int msan_inited = 0; 9668d75effSDimitry Andric bool msan_init_is_running; 9768d75effSDimitry Andric 9868d75effSDimitry Andric int msan_report_count = 0; 9968d75effSDimitry Andric 10068d75effSDimitry Andric // Array of stack origins. 10168d75effSDimitry Andric // FIXME: make it resizable. 102*0fca6ea1SDimitry Andric // Although BSS memory doesn't cost anything until used, it is limited to 2GB 103*0fca6ea1SDimitry Andric // in some configurations (e.g., "relocation R_X86_64_PC32 out of range: 104*0fca6ea1SDimitry Andric // ... is not in [-2147483648, 2147483647]; references section '.bss'"). 105*0fca6ea1SDimitry Andric // We use kNumStackOriginDescrs * (sizeof(char*) + sizeof(uptr)) == 64MB. 106*0fca6ea1SDimitry Andric #if SANITIZER_PPC 107*0fca6ea1SDimitry Andric // soft_rss_limit test (release_origin.c) fails on PPC if kNumStackOriginDescrs 108*0fca6ea1SDimitry Andric // is too high 109*0fca6ea1SDimitry Andric static const uptr kNumStackOriginDescrs = 1 * 1024 * 1024; 110*0fca6ea1SDimitry Andric #else 111*0fca6ea1SDimitry Andric static const uptr kNumStackOriginDescrs = 4 * 1024 * 1024; 112*0fca6ea1SDimitry Andric #endif // SANITIZER_PPC 11368d75effSDimitry Andric static const char *StackOriginDescr[kNumStackOriginDescrs]; 11468d75effSDimitry Andric static uptr StackOriginPC[kNumStackOriginDescrs]; 11568d75effSDimitry Andric static atomic_uint32_t NumStackOriginDescrs; 11668d75effSDimitry Andric 11768d75effSDimitry Andric void Flags::SetDefaults() { 11868d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 11968d75effSDimitry Andric #include "msan_flags.inc" 12068d75effSDimitry Andric #undef MSAN_FLAG 12168d75effSDimitry Andric } 12268d75effSDimitry Andric 12368d75effSDimitry Andric // keep_going is an old name for halt_on_error, 12468d75effSDimitry Andric // and it has inverse meaning. 125e8d8bef9SDimitry Andric class FlagHandlerKeepGoing final : public FlagHandlerBase { 12668d75effSDimitry Andric bool *halt_on_error_; 12768d75effSDimitry Andric 12868d75effSDimitry Andric public: 12968d75effSDimitry Andric explicit FlagHandlerKeepGoing(bool *halt_on_error) 13068d75effSDimitry Andric : halt_on_error_(halt_on_error) {} 13168d75effSDimitry Andric bool Parse(const char *value) final { 13268d75effSDimitry Andric bool tmp; 13368d75effSDimitry Andric FlagHandler<bool> h(&tmp); 13468d75effSDimitry Andric if (!h.Parse(value)) return false; 13568d75effSDimitry Andric *halt_on_error_ = !tmp; 13668d75effSDimitry Andric return true; 13768d75effSDimitry Andric } 138480093f4SDimitry Andric bool Format(char *buffer, uptr size) final { 139480093f4SDimitry Andric const char *keep_going_str = (*halt_on_error_) ? "false" : "true"; 140480093f4SDimitry Andric return FormatString(buffer, size, keep_going_str); 141480093f4SDimitry Andric } 14268d75effSDimitry Andric }; 14368d75effSDimitry Andric 14468d75effSDimitry Andric static void RegisterMsanFlags(FlagParser *parser, Flags *f) { 14568d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) \ 14668d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 14768d75effSDimitry Andric #include "msan_flags.inc" 14868d75effSDimitry Andric #undef MSAN_FLAG 14968d75effSDimitry Andric 1505f757f3fSDimitry Andric FlagHandlerKeepGoing *fh_keep_going = new (GetGlobalLowLevelAllocator()) 1515f757f3fSDimitry Andric FlagHandlerKeepGoing(&f->halt_on_error); 15268d75effSDimitry Andric parser->RegisterHandler("keep_going", fh_keep_going, 15368d75effSDimitry Andric "deprecated, use halt_on_error"); 15468d75effSDimitry Andric } 15568d75effSDimitry Andric 15668d75effSDimitry Andric static void InitializeFlags() { 15768d75effSDimitry Andric SetCommonFlagsDefaults(); 15868d75effSDimitry Andric { 15968d75effSDimitry Andric CommonFlags cf; 16068d75effSDimitry Andric cf.CopyFrom(*common_flags()); 16168d75effSDimitry Andric cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); 16268d75effSDimitry Andric cf.malloc_context_size = 20; 16368d75effSDimitry Andric cf.handle_ioctl = true; 16468d75effSDimitry Andric // FIXME: test and enable. 16568d75effSDimitry Andric cf.check_printf = false; 16668d75effSDimitry Andric cf.intercept_tls_get_addr = true; 16768d75effSDimitry Andric OverrideCommonFlags(cf); 16868d75effSDimitry Andric } 16968d75effSDimitry Andric 17068d75effSDimitry Andric Flags *f = flags(); 17168d75effSDimitry Andric f->SetDefaults(); 17268d75effSDimitry Andric 17368d75effSDimitry Andric FlagParser parser; 17468d75effSDimitry Andric RegisterMsanFlags(&parser, f); 17568d75effSDimitry Andric RegisterCommonFlags(&parser); 17668d75effSDimitry Andric 17768d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 17868d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 17968d75effSDimitry Andric uf->SetDefaults(); 18068d75effSDimitry Andric 18168d75effSDimitry Andric FlagParser ubsan_parser; 18268d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 18368d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 18468d75effSDimitry Andric #endif 18568d75effSDimitry Andric 18668d75effSDimitry Andric // Override from user-specified string. 18768d75effSDimitry Andric parser.ParseString(__msan_default_options()); 18868d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 189e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 19068d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 19168d75effSDimitry Andric #endif 19268d75effSDimitry Andric 19368d75effSDimitry Andric parser.ParseStringFromEnv("MSAN_OPTIONS"); 19468d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 19568d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 19668d75effSDimitry Andric #endif 19768d75effSDimitry Andric 19868d75effSDimitry Andric InitializeCommonFlags(); 19968d75effSDimitry Andric 20068d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 20168d75effSDimitry Andric 20268d75effSDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 20368d75effSDimitry Andric 20468d75effSDimitry Andric // Check if deprecated exit_code MSan flag is set. 20568d75effSDimitry Andric if (f->exit_code != -1) { 20668d75effSDimitry Andric if (Verbosity()) 20768d75effSDimitry Andric Printf("MSAN_OPTIONS=exit_code is deprecated! " 20868d75effSDimitry Andric "Please use MSAN_OPTIONS=exitcode instead.\n"); 20968d75effSDimitry Andric CommonFlags cf; 21068d75effSDimitry Andric cf.CopyFrom(*common_flags()); 21168d75effSDimitry Andric cf.exitcode = f->exit_code; 21268d75effSDimitry Andric OverrideCommonFlags(cf); 21368d75effSDimitry Andric } 21468d75effSDimitry Andric 21568d75effSDimitry Andric // Check flag values: 21668d75effSDimitry Andric if (f->origin_history_size < 0 || 21768d75effSDimitry Andric f->origin_history_size > Origin::kMaxDepth) { 21868d75effSDimitry Andric Printf( 21968d75effSDimitry Andric "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " 22068d75effSDimitry Andric "range.\n", 22168d75effSDimitry Andric f->origin_history_size, Origin::kMaxDepth); 22268d75effSDimitry Andric Die(); 22368d75effSDimitry Andric } 22468d75effSDimitry Andric // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in 22568d75effSDimitry Andric // StackDepotHandle::inc_use_count_unsafe. 22668d75effSDimitry Andric if (f->origin_history_per_stack_limit < 0 || 22768d75effSDimitry Andric f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { 22868d75effSDimitry Andric Printf( 22968d75effSDimitry Andric "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " 23068d75effSDimitry Andric "%d] range.\n", 23168d75effSDimitry Andric f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); 23268d75effSDimitry Andric Die(); 23368d75effSDimitry Andric } 23468d75effSDimitry Andric if (f->store_context_size < 1) f->store_context_size = 1; 23568d75effSDimitry Andric } 23668d75effSDimitry Andric 23768d75effSDimitry Andric void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) { 23868d75effSDimitry Andric if (msan_expect_umr) { 23968d75effSDimitry Andric // Printf("Expected UMR\n"); 24068d75effSDimitry Andric __msan_origin_tls = origin; 24168d75effSDimitry Andric msan_expected_umr_found = 1; 24268d75effSDimitry Andric return; 24368d75effSDimitry Andric } 24468d75effSDimitry Andric 24568d75effSDimitry Andric ++msan_report_count; 24668d75effSDimitry Andric 24768d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 24868d75effSDimitry Andric 24968d75effSDimitry Andric u32 report_origin = 25068d75effSDimitry Andric (__msan_get_track_origins() && Origin::isValidId(origin)) ? origin : 0; 25168d75effSDimitry Andric ReportUMR(&stack, report_origin); 25268d75effSDimitry Andric 25368d75effSDimitry Andric if (__msan_get_track_origins() && !Origin::isValidId(origin)) { 25468d75effSDimitry Andric Printf( 25568d75effSDimitry Andric " ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin " 25668d75effSDimitry Andric "tracking.\n This could still be a bug in your code, too!\n", 25768d75effSDimitry Andric origin); 25868d75effSDimitry Andric } 25968d75effSDimitry Andric } 26068d75effSDimitry Andric 26168d75effSDimitry Andric void UnpoisonParam(uptr n) { 26268d75effSDimitry Andric internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls)); 26368d75effSDimitry Andric } 26468d75effSDimitry Andric 26568d75effSDimitry Andric // Backup MSan runtime TLS state. 26668d75effSDimitry Andric // Implementation must be async-signal-safe. 26768d75effSDimitry Andric // Instances of this class may live on the signal handler stack, and data size 26868d75effSDimitry Andric // may be an issue. 26968d75effSDimitry Andric void ScopedThreadLocalStateBackup::Backup() { 27068d75effSDimitry Andric va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls; 27168d75effSDimitry Andric } 27268d75effSDimitry Andric 27368d75effSDimitry Andric void ScopedThreadLocalStateBackup::Restore() { 27468d75effSDimitry Andric // A lame implementation that only keeps essential state and resets the rest. 27568d75effSDimitry Andric __msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls; 27668d75effSDimitry Andric 27768d75effSDimitry Andric internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 27868d75effSDimitry Andric internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 27968d75effSDimitry Andric internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 28068d75effSDimitry Andric internal_memset(__msan_va_arg_origin_tls, 0, 28168d75effSDimitry Andric sizeof(__msan_va_arg_origin_tls)); 28268d75effSDimitry Andric 28368d75effSDimitry Andric if (__msan_get_track_origins()) { 28468d75effSDimitry Andric internal_memset(&__msan_retval_origin_tls, 0, 28568d75effSDimitry Andric sizeof(__msan_retval_origin_tls)); 28668d75effSDimitry Andric internal_memset(__msan_param_origin_tls, 0, 28768d75effSDimitry Andric sizeof(__msan_param_origin_tls)); 28868d75effSDimitry Andric } 28968d75effSDimitry Andric } 29068d75effSDimitry Andric 29168d75effSDimitry Andric void UnpoisonThreadLocalState() { 29268d75effSDimitry Andric } 29368d75effSDimitry Andric 29468d75effSDimitry Andric const char *GetStackOriginDescr(u32 id, uptr *pc) { 29568d75effSDimitry Andric CHECK_LT(id, kNumStackOriginDescrs); 29668d75effSDimitry Andric if (pc) *pc = StackOriginPC[id]; 29768d75effSDimitry Andric return StackOriginDescr[id]; 29868d75effSDimitry Andric } 29968d75effSDimitry Andric 30068d75effSDimitry Andric u32 ChainOrigin(u32 id, StackTrace *stack) { 30168d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 30268d75effSDimitry Andric if (t && t->InSignalHandler()) 30368d75effSDimitry Andric return id; 30468d75effSDimitry Andric 30568d75effSDimitry Andric Origin o = Origin::FromRawId(id); 30668d75effSDimitry Andric stack->tag = StackTrace::TAG_UNKNOWN; 30768d75effSDimitry Andric Origin chained = Origin::CreateChainedOrigin(o, stack); 30868d75effSDimitry Andric return chained.raw_id(); 30968d75effSDimitry Andric } 31068d75effSDimitry Andric 311bdd1243dSDimitry Andric // Current implementation separates the 'id_ptr' from the 'descr' and makes 312bdd1243dSDimitry Andric // 'descr' constant. 313bdd1243dSDimitry Andric // Previous implementation 'descr' is created at compile time and contains 314bdd1243dSDimitry Andric // '----' in the beginning. When we see descr for the first time we replace 315bdd1243dSDimitry Andric // '----' with a uniq id and set the origin to (id | (31-th bit)). 316bdd1243dSDimitry Andric static inline void SetAllocaOrigin(void *a, uptr size, u32 *id_ptr, char *descr, 317bdd1243dSDimitry Andric uptr pc) { 318bdd1243dSDimitry Andric static const u32 dash = '-'; 319bdd1243dSDimitry Andric static const u32 first_timer = 320bdd1243dSDimitry Andric dash + (dash << 8) + (dash << 16) + (dash << 24); 321bdd1243dSDimitry Andric u32 id = *id_ptr; 322bdd1243dSDimitry Andric if (id == 0 || id == first_timer) { 323bdd1243dSDimitry Andric u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); 324bdd1243dSDimitry Andric CHECK_LT(idx, kNumStackOriginDescrs); 325bdd1243dSDimitry Andric StackOriginDescr[idx] = descr; 326bdd1243dSDimitry Andric StackOriginPC[idx] = pc; 327bdd1243dSDimitry Andric id = Origin::CreateStackOrigin(idx).raw_id(); 328bdd1243dSDimitry Andric *id_ptr = id; 329bdd1243dSDimitry Andric } 330bdd1243dSDimitry Andric __msan_set_origin(a, size, id); 331bdd1243dSDimitry Andric } 332bdd1243dSDimitry Andric 33368d75effSDimitry Andric } // namespace __msan 33468d75effSDimitry Andric 33568d75effSDimitry Andric void __sanitizer::BufferedStackTrace::UnwindImpl( 33668d75effSDimitry Andric uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 33768d75effSDimitry Andric using namespace __msan; 33868d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 33968d75effSDimitry Andric if (!t || !StackTrace::WillUseFastUnwind(request_fast)) { 34068d75effSDimitry Andric // Block reports from our interceptors during _Unwind_Backtrace. 34181ad6265SDimitry Andric UnwinderScope sym_scope; 342fe6060f1SDimitry Andric return Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0, 343fe6060f1SDimitry Andric t ? t->stack_bottom() : 0, false); 34468d75effSDimitry Andric } 34568d75effSDimitry Andric if (StackTrace::WillUseFastUnwind(request_fast)) 34668d75effSDimitry Andric Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true); 34768d75effSDimitry Andric else 34868d75effSDimitry Andric Unwind(max_depth, pc, 0, context, 0, 0, false); 34968d75effSDimitry Andric } 35068d75effSDimitry Andric 35168d75effSDimitry Andric // Interface. 35268d75effSDimitry Andric 35368d75effSDimitry Andric using namespace __msan; 35468d75effSDimitry Andric 35568d75effSDimitry Andric #define MSAN_MAYBE_WARNING(type, size) \ 35668d75effSDimitry Andric void __msan_maybe_warning_##size(type s, u32 o) { \ 35706c3fb27SDimitry Andric GET_CALLER_PC_BP; \ 35868d75effSDimitry Andric if (UNLIKELY(s)) { \ 35968d75effSDimitry Andric PrintWarningWithOrigin(pc, bp, o); \ 36068d75effSDimitry Andric if (__msan::flags()->halt_on_error) { \ 36168d75effSDimitry Andric Printf("Exiting\n"); \ 36268d75effSDimitry Andric Die(); \ 36368d75effSDimitry Andric } \ 36468d75effSDimitry Andric } \ 36568d75effSDimitry Andric } 36668d75effSDimitry Andric 36768d75effSDimitry Andric MSAN_MAYBE_WARNING(u8, 1) 36868d75effSDimitry Andric MSAN_MAYBE_WARNING(u16, 2) 36968d75effSDimitry Andric MSAN_MAYBE_WARNING(u32, 4) 37068d75effSDimitry Andric MSAN_MAYBE_WARNING(u64, 8) 37168d75effSDimitry Andric 37268d75effSDimitry Andric #define MSAN_MAYBE_STORE_ORIGIN(type, size) \ 37368d75effSDimitry Andric void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \ 37468d75effSDimitry Andric if (UNLIKELY(s)) { \ 37568d75effSDimitry Andric if (__msan_get_track_origins() > 1) { \ 37606c3fb27SDimitry Andric GET_CALLER_PC_BP; \ 37768d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); \ 37868d75effSDimitry Andric o = ChainOrigin(o, &stack); \ 37968d75effSDimitry Andric } \ 38068d75effSDimitry Andric *(u32 *)MEM_TO_ORIGIN((uptr)p & ~3UL) = o; \ 38168d75effSDimitry Andric } \ 38268d75effSDimitry Andric } 38368d75effSDimitry Andric 38468d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u8, 1) 38568d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u16, 2) 38668d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u32, 4) 38768d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u64, 8) 38868d75effSDimitry Andric 38968d75effSDimitry Andric void __msan_warning() { 39006c3fb27SDimitry Andric GET_CALLER_PC_BP; 391bdd1243dSDimitry Andric PrintWarningWithOrigin(pc, bp, 0); 39268d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 39368d75effSDimitry Andric if (__msan::flags()->print_stats) 39468d75effSDimitry Andric ReportStats(); 39568d75effSDimitry Andric Printf("Exiting\n"); 39668d75effSDimitry Andric Die(); 39768d75effSDimitry Andric } 39868d75effSDimitry Andric } 39968d75effSDimitry Andric 40068d75effSDimitry Andric void __msan_warning_noreturn() { 40106c3fb27SDimitry Andric GET_CALLER_PC_BP; 402bdd1243dSDimitry Andric PrintWarningWithOrigin(pc, bp, 0); 40368d75effSDimitry Andric if (__msan::flags()->print_stats) 40468d75effSDimitry Andric ReportStats(); 40568d75effSDimitry Andric Printf("Exiting\n"); 40668d75effSDimitry Andric Die(); 40768d75effSDimitry Andric } 40868d75effSDimitry Andric 4095ffd83dbSDimitry Andric void __msan_warning_with_origin(u32 origin) { 41006c3fb27SDimitry Andric GET_CALLER_PC_BP; 4115ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 4125ffd83dbSDimitry Andric if (__msan::flags()->halt_on_error) { 4135ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 4145ffd83dbSDimitry Andric ReportStats(); 4155ffd83dbSDimitry Andric Printf("Exiting\n"); 4165ffd83dbSDimitry Andric Die(); 4175ffd83dbSDimitry Andric } 4185ffd83dbSDimitry Andric } 4195ffd83dbSDimitry Andric 4205ffd83dbSDimitry Andric void __msan_warning_with_origin_noreturn(u32 origin) { 42106c3fb27SDimitry Andric GET_CALLER_PC_BP; 4225ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 4235ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 4245ffd83dbSDimitry Andric ReportStats(); 4255ffd83dbSDimitry Andric Printf("Exiting\n"); 4265ffd83dbSDimitry Andric Die(); 4275ffd83dbSDimitry Andric } 4285ffd83dbSDimitry Andric 42968d75effSDimitry Andric static void OnStackUnwind(const SignalContext &sig, const void *, 43068d75effSDimitry Andric BufferedStackTrace *stack) { 43168d75effSDimitry Andric stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 43268d75effSDimitry Andric common_flags()->fast_unwind_on_fatal); 43368d75effSDimitry Andric } 43468d75effSDimitry Andric 43568d75effSDimitry Andric static void MsanOnDeadlySignal(int signo, void *siginfo, void *context) { 43668d75effSDimitry Andric HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr); 43768d75effSDimitry Andric } 43868d75effSDimitry Andric 439fe6060f1SDimitry Andric static void CheckUnwind() { 440fe6060f1SDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 441fe6060f1SDimitry Andric stack.Print(); 44268d75effSDimitry Andric } 44368d75effSDimitry Andric 44468d75effSDimitry Andric void __msan_init() { 44568d75effSDimitry Andric CHECK(!msan_init_is_running); 44668d75effSDimitry Andric if (msan_inited) return; 44768d75effSDimitry Andric msan_init_is_running = 1; 44868d75effSDimitry Andric SanitizerToolName = "MemorySanitizer"; 44968d75effSDimitry Andric 45068d75effSDimitry Andric AvoidCVE_2016_2143(); 45168d75effSDimitry Andric 45268d75effSDimitry Andric CacheBinaryName(); 45368d75effSDimitry Andric InitializeFlags(); 45468d75effSDimitry Andric 45568d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 456fe6060f1SDimitry Andric SetCheckUnwindCallback(CheckUnwind); 45768d75effSDimitry Andric 45868d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 45968d75effSDimitry Andric 46068d75effSDimitry Andric InitializeInterceptors(); 4615f757f3fSDimitry Andric InstallAtForkHandler(); 46268d75effSDimitry Andric CheckASLR(); 46368d75effSDimitry Andric InitTlsSize(); 46468d75effSDimitry Andric InstallDeadlySignalHandlers(MsanOnDeadlySignal); 46568d75effSDimitry Andric InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 46668d75effSDimitry Andric 46768d75effSDimitry Andric DisableCoreDumperIfNecessary(); 46868d75effSDimitry Andric if (StackSizeIsUnlimited()) { 46968d75effSDimitry Andric VPrintf(1, "Unlimited stack, doing reexec\n"); 47068d75effSDimitry Andric // A reasonably large stack size. It is bigger than the usual 8Mb, because, 47168d75effSDimitry Andric // well, the program could have been run with unlimited stack for a reason. 47268d75effSDimitry Andric SetStackSizeLimitInBytes(32 * 1024 * 1024); 47368d75effSDimitry Andric ReExec(); 47468d75effSDimitry Andric } 47568d75effSDimitry Andric 47668d75effSDimitry Andric __msan_clear_on_return(); 47768d75effSDimitry Andric if (__msan_get_track_origins()) 47868d75effSDimitry Andric VPrintf(1, "msan_track_origins\n"); 479439352acSDimitry Andric if (!InitShadowWithReExec(__msan_get_track_origins())) { 48068d75effSDimitry Andric Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); 48168d75effSDimitry Andric Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 48268d75effSDimitry Andric Printf("FATAL: Disabling ASLR is known to cause this error.\n"); 48368d75effSDimitry Andric Printf("FATAL: If running under GDB, try " 48468d75effSDimitry Andric "'set disable-randomization off'.\n"); 48568d75effSDimitry Andric DumpProcessMap(); 48668d75effSDimitry Andric Die(); 48768d75effSDimitry Andric } 48868d75effSDimitry Andric 48981ad6265SDimitry Andric Symbolizer::GetOrInit()->AddHooks(EnterSymbolizerOrUnwider, 49081ad6265SDimitry Andric ExitSymbolizerOrUnwider); 49168d75effSDimitry Andric 49268d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 49368d75effSDimitry Andric 49468d75effSDimitry Andric MsanTSDInit(MsanTSDDtor); 49568d75effSDimitry Andric 49668d75effSDimitry Andric MsanAllocatorInit(); 49768d75effSDimitry Andric 49868d75effSDimitry Andric MsanThread *main_thread = MsanThread::Create(nullptr, nullptr); 49968d75effSDimitry Andric SetCurrentThread(main_thread); 500349cc55cSDimitry Andric main_thread->Init(); 50168d75effSDimitry Andric 50268d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 50368d75effSDimitry Andric __ubsan::InitAsPlugin(); 50468d75effSDimitry Andric #endif 50568d75effSDimitry Andric 50668d75effSDimitry Andric VPrintf(1, "MemorySanitizer init done\n"); 50768d75effSDimitry Andric 50868d75effSDimitry Andric msan_init_is_running = 0; 50968d75effSDimitry Andric msan_inited = 1; 51068d75effSDimitry Andric } 51168d75effSDimitry Andric 51268d75effSDimitry Andric void __msan_set_keep_going(int keep_going) { 51368d75effSDimitry Andric flags()->halt_on_error = !keep_going; 51468d75effSDimitry Andric } 51568d75effSDimitry Andric 51668d75effSDimitry Andric void __msan_set_expect_umr(int expect_umr) { 51768d75effSDimitry Andric if (expect_umr) { 51868d75effSDimitry Andric msan_expected_umr_found = 0; 51968d75effSDimitry Andric } else if (!msan_expected_umr_found) { 52006c3fb27SDimitry Andric GET_CALLER_PC_BP; 52168d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 52268d75effSDimitry Andric ReportExpectedUMRNotFound(&stack); 52368d75effSDimitry Andric Die(); 52468d75effSDimitry Andric } 52568d75effSDimitry Andric msan_expect_umr = expect_umr; 52668d75effSDimitry Andric } 52768d75effSDimitry Andric 52868d75effSDimitry Andric void __msan_print_shadow(const void *x, uptr size) { 52968d75effSDimitry Andric if (!MEM_IS_APP(x)) { 53068d75effSDimitry Andric Printf("Not a valid application address: %p\n", x); 53168d75effSDimitry Andric return; 53268d75effSDimitry Andric } 53368d75effSDimitry Andric 53468d75effSDimitry Andric DescribeMemoryRange(x, size); 53568d75effSDimitry Andric } 53668d75effSDimitry Andric 53768d75effSDimitry Andric void __msan_dump_shadow(const void *x, uptr size) { 53868d75effSDimitry Andric if (!MEM_IS_APP(x)) { 53968d75effSDimitry Andric Printf("Not a valid application address: %p\n", x); 54068d75effSDimitry Andric return; 54168d75effSDimitry Andric } 54268d75effSDimitry Andric 54368d75effSDimitry Andric unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); 544349cc55cSDimitry Andric Printf("%p[%p] ", (void *)s, x); 54568d75effSDimitry Andric for (uptr i = 0; i < size; i++) 54668d75effSDimitry Andric Printf("%x%x ", s[i] >> 4, s[i] & 0xf); 54768d75effSDimitry Andric Printf("\n"); 54868d75effSDimitry Andric } 54968d75effSDimitry Andric 55068d75effSDimitry Andric sptr __msan_test_shadow(const void *x, uptr size) { 55168d75effSDimitry Andric if (!MEM_IS_APP(x)) return -1; 55268d75effSDimitry Andric unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x); 553e8d8bef9SDimitry Andric if (__sanitizer::mem_is_zero((const char *)s, size)) 554e8d8bef9SDimitry Andric return -1; 555e8d8bef9SDimitry Andric // Slow path: loop through again to find the location. 55668d75effSDimitry Andric for (uptr i = 0; i < size; ++i) 55768d75effSDimitry Andric if (s[i]) 55868d75effSDimitry Andric return i; 55968d75effSDimitry Andric return -1; 56068d75effSDimitry Andric } 56168d75effSDimitry Andric 56268d75effSDimitry Andric void __msan_check_mem_is_initialized(const void *x, uptr size) { 56368d75effSDimitry Andric if (!__msan::flags()->report_umrs) return; 56468d75effSDimitry Andric sptr offset = __msan_test_shadow(x, size); 56568d75effSDimitry Andric if (offset < 0) 56668d75effSDimitry Andric return; 56768d75effSDimitry Andric 56806c3fb27SDimitry Andric GET_CALLER_PC_BP; 56968d75effSDimitry Andric ReportUMRInsideAddressRange(__func__, x, size, offset); 57068d75effSDimitry Andric __msan::PrintWarningWithOrigin(pc, bp, 57168d75effSDimitry Andric __msan_get_origin(((const char *)x) + offset)); 57268d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 57368d75effSDimitry Andric Printf("Exiting\n"); 57468d75effSDimitry Andric Die(); 57568d75effSDimitry Andric } 57668d75effSDimitry Andric } 57768d75effSDimitry Andric 57868d75effSDimitry Andric int __msan_set_poison_in_malloc(int do_poison) { 57968d75effSDimitry Andric int old = flags()->poison_in_malloc; 58068d75effSDimitry Andric flags()->poison_in_malloc = do_poison; 58168d75effSDimitry Andric return old; 58268d75effSDimitry Andric } 58368d75effSDimitry Andric 58468d75effSDimitry Andric int __msan_has_dynamic_component() { return false; } 58568d75effSDimitry Andric 58668d75effSDimitry Andric NOINLINE 58768d75effSDimitry Andric void __msan_clear_on_return() { 58868d75effSDimitry Andric __msan_param_tls[0] = 0; 58968d75effSDimitry Andric } 59068d75effSDimitry Andric 59168d75effSDimitry Andric void __msan_partial_poison(const void* data, void* shadow, uptr size) { 59268d75effSDimitry Andric internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); 59368d75effSDimitry Andric } 59468d75effSDimitry Andric 59568d75effSDimitry Andric void __msan_load_unpoisoned(const void *src, uptr size, void *dst) { 59668d75effSDimitry Andric internal_memcpy(dst, src, size); 59768d75effSDimitry Andric __msan_unpoison(dst, size); 59868d75effSDimitry Andric } 59968d75effSDimitry Andric 60068d75effSDimitry Andric void __msan_set_origin(const void *a, uptr size, u32 origin) { 60168d75effSDimitry Andric if (__msan_get_track_origins()) SetOrigin(a, size, origin); 60268d75effSDimitry Andric } 60368d75effSDimitry Andric 60468d75effSDimitry Andric void __msan_set_alloca_origin(void *a, uptr size, char *descr) { 605bdd1243dSDimitry Andric SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4, 606bdd1243dSDimitry Andric GET_CALLER_PC()); 60768d75effSDimitry Andric } 60868d75effSDimitry Andric 60968d75effSDimitry Andric void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) { 610bdd1243dSDimitry Andric // Intentionally ignore pc and use return address. This function is here for 611bdd1243dSDimitry Andric // compatibility, in case program is linked with library instrumented by 612bdd1243dSDimitry Andric // older clang. 613bdd1243dSDimitry Andric SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4, 614bdd1243dSDimitry Andric GET_CALLER_PC()); 61568d75effSDimitry Andric } 616bdd1243dSDimitry Andric 617bdd1243dSDimitry Andric void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr, 618bdd1243dSDimitry Andric char *descr) { 619bdd1243dSDimitry Andric SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC()); 620bdd1243dSDimitry Andric } 621bdd1243dSDimitry Andric 622bdd1243dSDimitry Andric void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr) { 623bdd1243dSDimitry Andric SetAllocaOrigin(a, size, id_ptr, nullptr, GET_CALLER_PC()); 62468d75effSDimitry Andric } 62568d75effSDimitry Andric 62668d75effSDimitry Andric u32 __msan_chain_origin(u32 id) { 62706c3fb27SDimitry Andric GET_CALLER_PC_BP; 62868d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); 62968d75effSDimitry Andric return ChainOrigin(id, &stack); 63068d75effSDimitry Andric } 63168d75effSDimitry Andric 63268d75effSDimitry Andric u32 __msan_get_origin(const void *a) { 63368d75effSDimitry Andric if (!__msan_get_track_origins()) return 0; 63468d75effSDimitry Andric uptr x = (uptr)a; 63568d75effSDimitry Andric uptr aligned = x & ~3ULL; 63668d75effSDimitry Andric uptr origin_ptr = MEM_TO_ORIGIN(aligned); 63768d75effSDimitry Andric return *(u32*)origin_ptr; 63868d75effSDimitry Andric } 63968d75effSDimitry Andric 64068d75effSDimitry Andric int __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id) { 64168d75effSDimitry Andric Origin o = Origin::FromRawId(this_id); 64268d75effSDimitry Andric while (o.raw_id() != prev_id && o.isChainedOrigin()) 64368d75effSDimitry Andric o = o.getNextChainedOrigin(nullptr); 64468d75effSDimitry Andric return o.raw_id() == prev_id; 64568d75effSDimitry Andric } 64668d75effSDimitry Andric 64768d75effSDimitry Andric u32 __msan_get_umr_origin() { 64868d75effSDimitry Andric return __msan_origin_tls; 64968d75effSDimitry Andric } 65068d75effSDimitry Andric 65168d75effSDimitry Andric u16 __sanitizer_unaligned_load16(const uu16 *p) { 6525ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6535ffd83dbSDimitry Andric sizeof(uu16)); 65468d75effSDimitry Andric if (__msan_get_track_origins()) 65568d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 65668d75effSDimitry Andric return *p; 65768d75effSDimitry Andric } 65868d75effSDimitry Andric u32 __sanitizer_unaligned_load32(const uu32 *p) { 6595ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6605ffd83dbSDimitry Andric sizeof(uu32)); 66168d75effSDimitry Andric if (__msan_get_track_origins()) 66268d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 66368d75effSDimitry Andric return *p; 66468d75effSDimitry Andric } 66568d75effSDimitry Andric u64 __sanitizer_unaligned_load64(const uu64 *p) { 6665ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6675ffd83dbSDimitry Andric sizeof(uu64)); 66868d75effSDimitry Andric if (__msan_get_track_origins()) 66968d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 67068d75effSDimitry Andric return *p; 67168d75effSDimitry Andric } 67268d75effSDimitry Andric void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 6735ffd83dbSDimitry Andric static_assert(sizeof(uu16) == sizeof(u16), "incompatible types"); 6745ffd83dbSDimitry Andric u16 s; 6755ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu16)); 6765ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu16)); 67768d75effSDimitry Andric if (s && __msan_get_track_origins()) 67868d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 67968d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 68068d75effSDimitry Andric *p = x; 68168d75effSDimitry Andric } 68268d75effSDimitry Andric void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 6835ffd83dbSDimitry Andric static_assert(sizeof(uu32) == sizeof(u32), "incompatible types"); 6845ffd83dbSDimitry Andric u32 s; 6855ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu32)); 6865ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu32)); 68768d75effSDimitry Andric if (s && __msan_get_track_origins()) 68868d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 68968d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 69068d75effSDimitry Andric *p = x; 69168d75effSDimitry Andric } 69268d75effSDimitry Andric void __sanitizer_unaligned_store64(uu64 *p, u64 x) { 69368d75effSDimitry Andric u64 s = __msan_param_tls[1]; 69468d75effSDimitry Andric *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; 69568d75effSDimitry Andric if (s && __msan_get_track_origins()) 69668d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 69768d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 69868d75effSDimitry Andric *p = x; 69968d75effSDimitry Andric } 70068d75effSDimitry Andric 70168d75effSDimitry Andric void __msan_set_death_callback(void (*callback)(void)) { 70268d75effSDimitry Andric SetUserDieCallback(callback); 70368d75effSDimitry Andric } 70468d75effSDimitry Andric 705e8d8bef9SDimitry Andric void __msan_start_switch_fiber(const void *bottom, uptr size) { 706e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 707e8d8bef9SDimitry Andric if (!t) { 708e8d8bef9SDimitry Andric VReport(1, "__msan_start_switch_fiber called from unknown thread\n"); 709e8d8bef9SDimitry Andric return; 710e8d8bef9SDimitry Andric } 711e8d8bef9SDimitry Andric t->StartSwitchFiber((uptr)bottom, size); 712e8d8bef9SDimitry Andric } 713e8d8bef9SDimitry Andric 714e8d8bef9SDimitry Andric void __msan_finish_switch_fiber(const void **bottom_old, uptr *size_old) { 715e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 716e8d8bef9SDimitry Andric if (!t) { 717e8d8bef9SDimitry Andric VReport(1, "__msan_finish_switch_fiber called from unknown thread\n"); 718e8d8bef9SDimitry Andric return; 719e8d8bef9SDimitry Andric } 720e8d8bef9SDimitry Andric t->FinishSwitchFiber((uptr *)bottom_old, (uptr *)size_old); 721e8d8bef9SDimitry Andric 722e8d8bef9SDimitry Andric internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 723e8d8bef9SDimitry Andric internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 724e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 725e8d8bef9SDimitry Andric 726e8d8bef9SDimitry Andric if (__msan_get_track_origins()) { 727e8d8bef9SDimitry Andric internal_memset(__msan_param_origin_tls, 0, 728e8d8bef9SDimitry Andric sizeof(__msan_param_origin_tls)); 729e8d8bef9SDimitry Andric internal_memset(&__msan_retval_origin_tls, 0, 730e8d8bef9SDimitry Andric sizeof(__msan_retval_origin_tls)); 731e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_origin_tls, 0, 732e8d8bef9SDimitry Andric sizeof(__msan_va_arg_origin_tls)); 733e8d8bef9SDimitry Andric } 734e8d8bef9SDimitry Andric } 735e8d8bef9SDimitry Andric 736e8d8bef9SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char *, __msan_default_options, void) { 737e8d8bef9SDimitry Andric return ""; 738e8d8bef9SDimitry Andric } 73968d75effSDimitry Andric 74068d75effSDimitry Andric extern "C" { 74168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 74268d75effSDimitry Andric void __sanitizer_print_stack_trace() { 74368d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 74468d75effSDimitry Andric stack.Print(); 74568d75effSDimitry Andric } 74668d75effSDimitry Andric } // extern "C" 747