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" 1568d75effSDimitry Andric #include "msan_chained_origin_depot.h" 1668d75effSDimitry Andric #include "msan_origin.h" 1768d75effSDimitry Andric #include "msan_report.h" 1868d75effSDimitry Andric #include "msan_thread.h" 1968d75effSDimitry Andric #include "msan_poisoning.h" 2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h" 2668d75effSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h" 2768d75effSDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 2868d75effSDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 2968d75effSDimitry Andric #include "ubsan/ubsan_flags.h" 3068d75effSDimitry Andric #include "ubsan/ubsan_init.h" 3168d75effSDimitry Andric 3268d75effSDimitry Andric // ACHTUNG! No system header includes in this file. 3368d75effSDimitry Andric 3468d75effSDimitry Andric using namespace __sanitizer; 3568d75effSDimitry Andric 3668d75effSDimitry Andric // Globals. 3768d75effSDimitry Andric static THREADLOCAL int msan_expect_umr = 0; 3868d75effSDimitry Andric static THREADLOCAL int msan_expected_umr_found = 0; 3968d75effSDimitry Andric 4068d75effSDimitry Andric // Function argument shadow. Each argument starts at the next available 8-byte 4168d75effSDimitry Andric // aligned address. 4268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 4368d75effSDimitry Andric THREADLOCAL u64 __msan_param_tls[kMsanParamTlsSize / sizeof(u64)]; 4468d75effSDimitry Andric 4568d75effSDimitry Andric // Function argument origin. Each argument starts at the same offset as the 4668d75effSDimitry Andric // corresponding shadow in (__msan_param_tls). Slightly weird, but changing this 4768d75effSDimitry Andric // would break compatibility with older prebuilt binaries. 4868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 4968d75effSDimitry Andric THREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 5068d75effSDimitry Andric 5168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5268d75effSDimitry Andric THREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSize / sizeof(u64)]; 5368d75effSDimitry Andric 5468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5568d75effSDimitry Andric THREADLOCAL u32 __msan_retval_origin_tls; 5668d75effSDimitry Andric 5768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5868d75effSDimitry Andric ALIGNED(16) THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; 5968d75effSDimitry Andric 6068d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6168d75effSDimitry Andric ALIGNED(16) 6268d75effSDimitry Andric THREADLOCAL u32 __msan_va_arg_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 6368d75effSDimitry Andric 6468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6568d75effSDimitry Andric THREADLOCAL u64 __msan_va_arg_overflow_size_tls; 6668d75effSDimitry Andric 6768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6868d75effSDimitry Andric THREADLOCAL u32 __msan_origin_tls; 6968d75effSDimitry Andric 7068d75effSDimitry Andric static THREADLOCAL int is_in_symbolizer; 7168d75effSDimitry Andric 7268d75effSDimitry Andric extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; 7368d75effSDimitry Andric 7468d75effSDimitry Andric int __msan_get_track_origins() { 7568d75effSDimitry Andric return &__msan_track_origins ? __msan_track_origins : 0; 7668d75effSDimitry Andric } 7768d75effSDimitry Andric 7868d75effSDimitry Andric extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going; 7968d75effSDimitry Andric 8068d75effSDimitry Andric namespace __msan { 8168d75effSDimitry Andric 8268d75effSDimitry Andric void EnterSymbolizer() { ++is_in_symbolizer; } 8368d75effSDimitry Andric void ExitSymbolizer() { --is_in_symbolizer; } 8468d75effSDimitry Andric bool IsInSymbolizer() { return is_in_symbolizer; } 8568d75effSDimitry Andric 8668d75effSDimitry Andric static Flags msan_flags; 8768d75effSDimitry Andric 8868d75effSDimitry Andric Flags *flags() { 8968d75effSDimitry Andric return &msan_flags; 9068d75effSDimitry Andric } 9168d75effSDimitry Andric 9268d75effSDimitry Andric int msan_inited = 0; 9368d75effSDimitry Andric bool msan_init_is_running; 9468d75effSDimitry Andric 9568d75effSDimitry Andric int msan_report_count = 0; 9668d75effSDimitry Andric 9768d75effSDimitry Andric // Array of stack origins. 9868d75effSDimitry Andric // FIXME: make it resizable. 9968d75effSDimitry Andric static const uptr kNumStackOriginDescrs = 1024 * 1024; 10068d75effSDimitry Andric static const char *StackOriginDescr[kNumStackOriginDescrs]; 10168d75effSDimitry Andric static uptr StackOriginPC[kNumStackOriginDescrs]; 10268d75effSDimitry Andric static atomic_uint32_t NumStackOriginDescrs; 10368d75effSDimitry Andric 10468d75effSDimitry Andric void Flags::SetDefaults() { 10568d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 10668d75effSDimitry Andric #include "msan_flags.inc" 10768d75effSDimitry Andric #undef MSAN_FLAG 10868d75effSDimitry Andric } 10968d75effSDimitry Andric 11068d75effSDimitry Andric // keep_going is an old name for halt_on_error, 11168d75effSDimitry Andric // and it has inverse meaning. 112e8d8bef9SDimitry Andric class FlagHandlerKeepGoing final : public FlagHandlerBase { 11368d75effSDimitry Andric bool *halt_on_error_; 11468d75effSDimitry Andric 11568d75effSDimitry Andric public: 11668d75effSDimitry Andric explicit FlagHandlerKeepGoing(bool *halt_on_error) 11768d75effSDimitry Andric : halt_on_error_(halt_on_error) {} 11868d75effSDimitry Andric bool Parse(const char *value) final { 11968d75effSDimitry Andric bool tmp; 12068d75effSDimitry Andric FlagHandler<bool> h(&tmp); 12168d75effSDimitry Andric if (!h.Parse(value)) return false; 12268d75effSDimitry Andric *halt_on_error_ = !tmp; 12368d75effSDimitry Andric return true; 12468d75effSDimitry Andric } 125480093f4SDimitry Andric bool Format(char *buffer, uptr size) final { 126480093f4SDimitry Andric const char *keep_going_str = (*halt_on_error_) ? "false" : "true"; 127480093f4SDimitry Andric return FormatString(buffer, size, keep_going_str); 128480093f4SDimitry Andric } 12968d75effSDimitry Andric }; 13068d75effSDimitry Andric 13168d75effSDimitry Andric static void RegisterMsanFlags(FlagParser *parser, Flags *f) { 13268d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) \ 13368d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 13468d75effSDimitry Andric #include "msan_flags.inc" 13568d75effSDimitry Andric #undef MSAN_FLAG 13668d75effSDimitry Andric 13768d75effSDimitry Andric FlagHandlerKeepGoing *fh_keep_going = 13868d75effSDimitry Andric new (FlagParser::Alloc) FlagHandlerKeepGoing(&f->halt_on_error); 13968d75effSDimitry Andric parser->RegisterHandler("keep_going", fh_keep_going, 14068d75effSDimitry Andric "deprecated, use halt_on_error"); 14168d75effSDimitry Andric } 14268d75effSDimitry Andric 14368d75effSDimitry Andric static void InitializeFlags() { 14468d75effSDimitry Andric SetCommonFlagsDefaults(); 14568d75effSDimitry Andric { 14668d75effSDimitry Andric CommonFlags cf; 14768d75effSDimitry Andric cf.CopyFrom(*common_flags()); 14868d75effSDimitry Andric cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); 14968d75effSDimitry Andric cf.malloc_context_size = 20; 15068d75effSDimitry Andric cf.handle_ioctl = true; 15168d75effSDimitry Andric // FIXME: test and enable. 15268d75effSDimitry Andric cf.check_printf = false; 15368d75effSDimitry Andric cf.intercept_tls_get_addr = true; 15468d75effSDimitry Andric OverrideCommonFlags(cf); 15568d75effSDimitry Andric } 15668d75effSDimitry Andric 15768d75effSDimitry Andric Flags *f = flags(); 15868d75effSDimitry Andric f->SetDefaults(); 15968d75effSDimitry Andric 16068d75effSDimitry Andric FlagParser parser; 16168d75effSDimitry Andric RegisterMsanFlags(&parser, f); 16268d75effSDimitry Andric RegisterCommonFlags(&parser); 16368d75effSDimitry Andric 16468d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 16568d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 16668d75effSDimitry Andric uf->SetDefaults(); 16768d75effSDimitry Andric 16868d75effSDimitry Andric FlagParser ubsan_parser; 16968d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 17068d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 17168d75effSDimitry Andric #endif 17268d75effSDimitry Andric 17368d75effSDimitry Andric // Override from user-specified string. 17468d75effSDimitry Andric parser.ParseString(__msan_default_options()); 17568d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 176e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 17768d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 17868d75effSDimitry Andric #endif 17968d75effSDimitry Andric 18068d75effSDimitry Andric parser.ParseStringFromEnv("MSAN_OPTIONS"); 18168d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 18268d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 18368d75effSDimitry Andric #endif 18468d75effSDimitry Andric 18568d75effSDimitry Andric InitializeCommonFlags(); 18668d75effSDimitry Andric 18768d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 18868d75effSDimitry Andric 18968d75effSDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 19068d75effSDimitry Andric 19168d75effSDimitry Andric // Check if deprecated exit_code MSan flag is set. 19268d75effSDimitry Andric if (f->exit_code != -1) { 19368d75effSDimitry Andric if (Verbosity()) 19468d75effSDimitry Andric Printf("MSAN_OPTIONS=exit_code is deprecated! " 19568d75effSDimitry Andric "Please use MSAN_OPTIONS=exitcode instead.\n"); 19668d75effSDimitry Andric CommonFlags cf; 19768d75effSDimitry Andric cf.CopyFrom(*common_flags()); 19868d75effSDimitry Andric cf.exitcode = f->exit_code; 19968d75effSDimitry Andric OverrideCommonFlags(cf); 20068d75effSDimitry Andric } 20168d75effSDimitry Andric 20268d75effSDimitry Andric // Check flag values: 20368d75effSDimitry Andric if (f->origin_history_size < 0 || 20468d75effSDimitry Andric f->origin_history_size > Origin::kMaxDepth) { 20568d75effSDimitry Andric Printf( 20668d75effSDimitry Andric "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " 20768d75effSDimitry Andric "range.\n", 20868d75effSDimitry Andric f->origin_history_size, Origin::kMaxDepth); 20968d75effSDimitry Andric Die(); 21068d75effSDimitry Andric } 21168d75effSDimitry Andric // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in 21268d75effSDimitry Andric // StackDepotHandle::inc_use_count_unsafe. 21368d75effSDimitry Andric if (f->origin_history_per_stack_limit < 0 || 21468d75effSDimitry Andric f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { 21568d75effSDimitry Andric Printf( 21668d75effSDimitry Andric "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " 21768d75effSDimitry Andric "%d] range.\n", 21868d75effSDimitry Andric f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); 21968d75effSDimitry Andric Die(); 22068d75effSDimitry Andric } 22168d75effSDimitry Andric if (f->store_context_size < 1) f->store_context_size = 1; 22268d75effSDimitry Andric } 22368d75effSDimitry Andric 22468d75effSDimitry Andric void PrintWarning(uptr pc, uptr bp) { 22568d75effSDimitry Andric PrintWarningWithOrigin(pc, bp, __msan_origin_tls); 22668d75effSDimitry Andric } 22768d75effSDimitry Andric 22868d75effSDimitry Andric void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) { 22968d75effSDimitry Andric if (msan_expect_umr) { 23068d75effSDimitry Andric // Printf("Expected UMR\n"); 23168d75effSDimitry Andric __msan_origin_tls = origin; 23268d75effSDimitry Andric msan_expected_umr_found = 1; 23368d75effSDimitry Andric return; 23468d75effSDimitry Andric } 23568d75effSDimitry Andric 23668d75effSDimitry Andric ++msan_report_count; 23768d75effSDimitry Andric 23868d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 23968d75effSDimitry Andric 24068d75effSDimitry Andric u32 report_origin = 24168d75effSDimitry Andric (__msan_get_track_origins() && Origin::isValidId(origin)) ? origin : 0; 24268d75effSDimitry Andric ReportUMR(&stack, report_origin); 24368d75effSDimitry Andric 24468d75effSDimitry Andric if (__msan_get_track_origins() && !Origin::isValidId(origin)) { 24568d75effSDimitry Andric Printf( 24668d75effSDimitry Andric " ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin " 24768d75effSDimitry Andric "tracking.\n This could still be a bug in your code, too!\n", 24868d75effSDimitry Andric origin); 24968d75effSDimitry Andric } 25068d75effSDimitry Andric } 25168d75effSDimitry Andric 25268d75effSDimitry Andric void UnpoisonParam(uptr n) { 25368d75effSDimitry Andric internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls)); 25468d75effSDimitry Andric } 25568d75effSDimitry Andric 25668d75effSDimitry Andric // Backup MSan runtime TLS state. 25768d75effSDimitry Andric // Implementation must be async-signal-safe. 25868d75effSDimitry Andric // Instances of this class may live on the signal handler stack, and data size 25968d75effSDimitry Andric // may be an issue. 26068d75effSDimitry Andric void ScopedThreadLocalStateBackup::Backup() { 26168d75effSDimitry Andric va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls; 26268d75effSDimitry Andric } 26368d75effSDimitry Andric 26468d75effSDimitry Andric void ScopedThreadLocalStateBackup::Restore() { 26568d75effSDimitry Andric // A lame implementation that only keeps essential state and resets the rest. 26668d75effSDimitry Andric __msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls; 26768d75effSDimitry Andric 26868d75effSDimitry Andric internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 26968d75effSDimitry Andric internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 27068d75effSDimitry Andric internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 27168d75effSDimitry Andric internal_memset(__msan_va_arg_origin_tls, 0, 27268d75effSDimitry Andric sizeof(__msan_va_arg_origin_tls)); 27368d75effSDimitry Andric 27468d75effSDimitry Andric if (__msan_get_track_origins()) { 27568d75effSDimitry Andric internal_memset(&__msan_retval_origin_tls, 0, 27668d75effSDimitry Andric sizeof(__msan_retval_origin_tls)); 27768d75effSDimitry Andric internal_memset(__msan_param_origin_tls, 0, 27868d75effSDimitry Andric sizeof(__msan_param_origin_tls)); 27968d75effSDimitry Andric } 28068d75effSDimitry Andric } 28168d75effSDimitry Andric 28268d75effSDimitry Andric void UnpoisonThreadLocalState() { 28368d75effSDimitry Andric } 28468d75effSDimitry Andric 28568d75effSDimitry Andric const char *GetStackOriginDescr(u32 id, uptr *pc) { 28668d75effSDimitry Andric CHECK_LT(id, kNumStackOriginDescrs); 28768d75effSDimitry Andric if (pc) *pc = StackOriginPC[id]; 28868d75effSDimitry Andric return StackOriginDescr[id]; 28968d75effSDimitry Andric } 29068d75effSDimitry Andric 29168d75effSDimitry Andric u32 ChainOrigin(u32 id, StackTrace *stack) { 29268d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 29368d75effSDimitry Andric if (t && t->InSignalHandler()) 29468d75effSDimitry Andric return id; 29568d75effSDimitry Andric 29668d75effSDimitry Andric Origin o = Origin::FromRawId(id); 29768d75effSDimitry Andric stack->tag = StackTrace::TAG_UNKNOWN; 29868d75effSDimitry Andric Origin chained = Origin::CreateChainedOrigin(o, stack); 29968d75effSDimitry Andric return chained.raw_id(); 30068d75effSDimitry Andric } 30168d75effSDimitry Andric 30268d75effSDimitry Andric } // namespace __msan 30368d75effSDimitry Andric 30468d75effSDimitry Andric void __sanitizer::BufferedStackTrace::UnwindImpl( 30568d75effSDimitry Andric uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 30668d75effSDimitry Andric using namespace __msan; 30768d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 30868d75effSDimitry Andric if (!t || !StackTrace::WillUseFastUnwind(request_fast)) { 30968d75effSDimitry Andric // Block reports from our interceptors during _Unwind_Backtrace. 31068d75effSDimitry Andric SymbolizerScope sym_scope; 311fe6060f1SDimitry Andric return Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0, 312fe6060f1SDimitry Andric t ? t->stack_bottom() : 0, false); 31368d75effSDimitry Andric } 31468d75effSDimitry Andric if (StackTrace::WillUseFastUnwind(request_fast)) 31568d75effSDimitry Andric Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true); 31668d75effSDimitry Andric else 31768d75effSDimitry Andric Unwind(max_depth, pc, 0, context, 0, 0, false); 31868d75effSDimitry Andric } 31968d75effSDimitry Andric 32068d75effSDimitry Andric // Interface. 32168d75effSDimitry Andric 32268d75effSDimitry Andric using namespace __msan; 32368d75effSDimitry Andric 32468d75effSDimitry Andric #define MSAN_MAYBE_WARNING(type, size) \ 32568d75effSDimitry Andric void __msan_maybe_warning_##size(type s, u32 o) { \ 32668d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 32768d75effSDimitry Andric (void) sp; \ 32868d75effSDimitry Andric if (UNLIKELY(s)) { \ 32968d75effSDimitry Andric PrintWarningWithOrigin(pc, bp, o); \ 33068d75effSDimitry Andric if (__msan::flags()->halt_on_error) { \ 33168d75effSDimitry Andric Printf("Exiting\n"); \ 33268d75effSDimitry Andric Die(); \ 33368d75effSDimitry Andric } \ 33468d75effSDimitry Andric } \ 33568d75effSDimitry Andric } 33668d75effSDimitry Andric 33768d75effSDimitry Andric MSAN_MAYBE_WARNING(u8, 1) 33868d75effSDimitry Andric MSAN_MAYBE_WARNING(u16, 2) 33968d75effSDimitry Andric MSAN_MAYBE_WARNING(u32, 4) 34068d75effSDimitry Andric MSAN_MAYBE_WARNING(u64, 8) 34168d75effSDimitry Andric 34268d75effSDimitry Andric #define MSAN_MAYBE_STORE_ORIGIN(type, size) \ 34368d75effSDimitry Andric void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \ 34468d75effSDimitry Andric if (UNLIKELY(s)) { \ 34568d75effSDimitry Andric if (__msan_get_track_origins() > 1) { \ 34668d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 34768d75effSDimitry Andric (void) sp; \ 34868d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); \ 34968d75effSDimitry Andric o = ChainOrigin(o, &stack); \ 35068d75effSDimitry Andric } \ 35168d75effSDimitry Andric *(u32 *)MEM_TO_ORIGIN((uptr)p & ~3UL) = o; \ 35268d75effSDimitry Andric } \ 35368d75effSDimitry Andric } 35468d75effSDimitry Andric 35568d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u8, 1) 35668d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u16, 2) 35768d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u32, 4) 35868d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u64, 8) 35968d75effSDimitry Andric 36068d75effSDimitry Andric void __msan_warning() { 36168d75effSDimitry Andric GET_CALLER_PC_BP_SP; 36268d75effSDimitry Andric (void)sp; 36368d75effSDimitry Andric PrintWarning(pc, bp); 36468d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 36568d75effSDimitry Andric if (__msan::flags()->print_stats) 36668d75effSDimitry Andric ReportStats(); 36768d75effSDimitry Andric Printf("Exiting\n"); 36868d75effSDimitry Andric Die(); 36968d75effSDimitry Andric } 37068d75effSDimitry Andric } 37168d75effSDimitry Andric 37268d75effSDimitry Andric void __msan_warning_noreturn() { 37368d75effSDimitry Andric GET_CALLER_PC_BP_SP; 37468d75effSDimitry Andric (void)sp; 37568d75effSDimitry Andric PrintWarning(pc, bp); 37668d75effSDimitry Andric if (__msan::flags()->print_stats) 37768d75effSDimitry Andric ReportStats(); 37868d75effSDimitry Andric Printf("Exiting\n"); 37968d75effSDimitry Andric Die(); 38068d75effSDimitry Andric } 38168d75effSDimitry Andric 3825ffd83dbSDimitry Andric void __msan_warning_with_origin(u32 origin) { 3835ffd83dbSDimitry Andric GET_CALLER_PC_BP_SP; 3845ffd83dbSDimitry Andric (void)sp; 3855ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 3865ffd83dbSDimitry Andric if (__msan::flags()->halt_on_error) { 3875ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 3885ffd83dbSDimitry Andric ReportStats(); 3895ffd83dbSDimitry Andric Printf("Exiting\n"); 3905ffd83dbSDimitry Andric Die(); 3915ffd83dbSDimitry Andric } 3925ffd83dbSDimitry Andric } 3935ffd83dbSDimitry Andric 3945ffd83dbSDimitry Andric void __msan_warning_with_origin_noreturn(u32 origin) { 3955ffd83dbSDimitry Andric GET_CALLER_PC_BP_SP; 3965ffd83dbSDimitry Andric (void)sp; 3975ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 3985ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 3995ffd83dbSDimitry Andric ReportStats(); 4005ffd83dbSDimitry Andric Printf("Exiting\n"); 4015ffd83dbSDimitry Andric Die(); 4025ffd83dbSDimitry Andric } 4035ffd83dbSDimitry Andric 40468d75effSDimitry Andric static void OnStackUnwind(const SignalContext &sig, const void *, 40568d75effSDimitry Andric BufferedStackTrace *stack) { 40668d75effSDimitry Andric stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 40768d75effSDimitry Andric common_flags()->fast_unwind_on_fatal); 40868d75effSDimitry Andric } 40968d75effSDimitry Andric 41068d75effSDimitry Andric static void MsanOnDeadlySignal(int signo, void *siginfo, void *context) { 41168d75effSDimitry Andric HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr); 41268d75effSDimitry Andric } 41368d75effSDimitry Andric 414fe6060f1SDimitry Andric static void CheckUnwind() { 415fe6060f1SDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 416fe6060f1SDimitry Andric stack.Print(); 41768d75effSDimitry Andric } 41868d75effSDimitry Andric 41968d75effSDimitry Andric void __msan_init() { 42068d75effSDimitry Andric CHECK(!msan_init_is_running); 42168d75effSDimitry Andric if (msan_inited) return; 42268d75effSDimitry Andric msan_init_is_running = 1; 42368d75effSDimitry Andric SanitizerToolName = "MemorySanitizer"; 42468d75effSDimitry Andric 42568d75effSDimitry Andric AvoidCVE_2016_2143(); 42668d75effSDimitry Andric 42768d75effSDimitry Andric CacheBinaryName(); 42868d75effSDimitry Andric InitializeFlags(); 42968d75effSDimitry Andric 43068d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 431fe6060f1SDimitry Andric SetCheckUnwindCallback(CheckUnwind); 43268d75effSDimitry Andric 43368d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 43468d75effSDimitry Andric 43568d75effSDimitry Andric InitializeInterceptors(); 43668d75effSDimitry Andric CheckASLR(); 43768d75effSDimitry Andric InitTlsSize(); 43868d75effSDimitry Andric InstallDeadlySignalHandlers(MsanOnDeadlySignal); 43968d75effSDimitry Andric InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 44068d75effSDimitry Andric 44168d75effSDimitry Andric DisableCoreDumperIfNecessary(); 44268d75effSDimitry Andric if (StackSizeIsUnlimited()) { 44368d75effSDimitry Andric VPrintf(1, "Unlimited stack, doing reexec\n"); 44468d75effSDimitry Andric // A reasonably large stack size. It is bigger than the usual 8Mb, because, 44568d75effSDimitry Andric // well, the program could have been run with unlimited stack for a reason. 44668d75effSDimitry Andric SetStackSizeLimitInBytes(32 * 1024 * 1024); 44768d75effSDimitry Andric ReExec(); 44868d75effSDimitry Andric } 44968d75effSDimitry Andric 45068d75effSDimitry Andric __msan_clear_on_return(); 45168d75effSDimitry Andric if (__msan_get_track_origins()) 45268d75effSDimitry Andric VPrintf(1, "msan_track_origins\n"); 45368d75effSDimitry Andric if (!InitShadow(__msan_get_track_origins())) { 45468d75effSDimitry Andric Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); 45568d75effSDimitry Andric Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 45668d75effSDimitry Andric Printf("FATAL: Disabling ASLR is known to cause this error.\n"); 45768d75effSDimitry Andric Printf("FATAL: If running under GDB, try " 45868d75effSDimitry Andric "'set disable-randomization off'.\n"); 45968d75effSDimitry Andric DumpProcessMap(); 46068d75effSDimitry Andric Die(); 46168d75effSDimitry Andric } 46268d75effSDimitry Andric 46368d75effSDimitry Andric Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer); 46468d75effSDimitry Andric 46568d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 46668d75effSDimitry Andric 46768d75effSDimitry Andric MsanTSDInit(MsanTSDDtor); 46868d75effSDimitry Andric 46968d75effSDimitry Andric MsanAllocatorInit(); 47068d75effSDimitry Andric 47168d75effSDimitry Andric MsanThread *main_thread = MsanThread::Create(nullptr, nullptr); 47268d75effSDimitry Andric SetCurrentThread(main_thread); 473*349cc55cSDimitry Andric main_thread->Init(); 47468d75effSDimitry Andric 47568d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 47668d75effSDimitry Andric __ubsan::InitAsPlugin(); 47768d75effSDimitry Andric #endif 47868d75effSDimitry Andric 47968d75effSDimitry Andric VPrintf(1, "MemorySanitizer init done\n"); 48068d75effSDimitry Andric 48168d75effSDimitry Andric msan_init_is_running = 0; 48268d75effSDimitry Andric msan_inited = 1; 48368d75effSDimitry Andric } 48468d75effSDimitry Andric 48568d75effSDimitry Andric void __msan_set_keep_going(int keep_going) { 48668d75effSDimitry Andric flags()->halt_on_error = !keep_going; 48768d75effSDimitry Andric } 48868d75effSDimitry Andric 48968d75effSDimitry Andric void __msan_set_expect_umr(int expect_umr) { 49068d75effSDimitry Andric if (expect_umr) { 49168d75effSDimitry Andric msan_expected_umr_found = 0; 49268d75effSDimitry Andric } else if (!msan_expected_umr_found) { 49368d75effSDimitry Andric GET_CALLER_PC_BP_SP; 49468d75effSDimitry Andric (void)sp; 49568d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 49668d75effSDimitry Andric ReportExpectedUMRNotFound(&stack); 49768d75effSDimitry Andric Die(); 49868d75effSDimitry Andric } 49968d75effSDimitry Andric msan_expect_umr = expect_umr; 50068d75effSDimitry Andric } 50168d75effSDimitry Andric 50268d75effSDimitry Andric void __msan_print_shadow(const void *x, uptr size) { 50368d75effSDimitry Andric if (!MEM_IS_APP(x)) { 50468d75effSDimitry Andric Printf("Not a valid application address: %p\n", x); 50568d75effSDimitry Andric return; 50668d75effSDimitry Andric } 50768d75effSDimitry Andric 50868d75effSDimitry Andric DescribeMemoryRange(x, size); 50968d75effSDimitry Andric } 51068d75effSDimitry Andric 51168d75effSDimitry Andric void __msan_dump_shadow(const void *x, uptr size) { 51268d75effSDimitry Andric if (!MEM_IS_APP(x)) { 51368d75effSDimitry Andric Printf("Not a valid application address: %p\n", x); 51468d75effSDimitry Andric return; 51568d75effSDimitry Andric } 51668d75effSDimitry Andric 51768d75effSDimitry Andric unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); 518*349cc55cSDimitry Andric Printf("%p[%p] ", (void *)s, x); 51968d75effSDimitry Andric for (uptr i = 0; i < size; i++) 52068d75effSDimitry Andric Printf("%x%x ", s[i] >> 4, s[i] & 0xf); 52168d75effSDimitry Andric Printf("\n"); 52268d75effSDimitry Andric } 52368d75effSDimitry Andric 52468d75effSDimitry Andric sptr __msan_test_shadow(const void *x, uptr size) { 52568d75effSDimitry Andric if (!MEM_IS_APP(x)) return -1; 52668d75effSDimitry Andric unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x); 527e8d8bef9SDimitry Andric if (__sanitizer::mem_is_zero((const char *)s, size)) 528e8d8bef9SDimitry Andric return -1; 529e8d8bef9SDimitry Andric // Slow path: loop through again to find the location. 53068d75effSDimitry Andric for (uptr i = 0; i < size; ++i) 53168d75effSDimitry Andric if (s[i]) 53268d75effSDimitry Andric return i; 53368d75effSDimitry Andric return -1; 53468d75effSDimitry Andric } 53568d75effSDimitry Andric 53668d75effSDimitry Andric void __msan_check_mem_is_initialized(const void *x, uptr size) { 53768d75effSDimitry Andric if (!__msan::flags()->report_umrs) return; 53868d75effSDimitry Andric sptr offset = __msan_test_shadow(x, size); 53968d75effSDimitry Andric if (offset < 0) 54068d75effSDimitry Andric return; 54168d75effSDimitry Andric 54268d75effSDimitry Andric GET_CALLER_PC_BP_SP; 54368d75effSDimitry Andric (void)sp; 54468d75effSDimitry Andric ReportUMRInsideAddressRange(__func__, x, size, offset); 54568d75effSDimitry Andric __msan::PrintWarningWithOrigin(pc, bp, 54668d75effSDimitry Andric __msan_get_origin(((const char *)x) + offset)); 54768d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 54868d75effSDimitry Andric Printf("Exiting\n"); 54968d75effSDimitry Andric Die(); 55068d75effSDimitry Andric } 55168d75effSDimitry Andric } 55268d75effSDimitry Andric 55368d75effSDimitry Andric int __msan_set_poison_in_malloc(int do_poison) { 55468d75effSDimitry Andric int old = flags()->poison_in_malloc; 55568d75effSDimitry Andric flags()->poison_in_malloc = do_poison; 55668d75effSDimitry Andric return old; 55768d75effSDimitry Andric } 55868d75effSDimitry Andric 55968d75effSDimitry Andric int __msan_has_dynamic_component() { return false; } 56068d75effSDimitry Andric 56168d75effSDimitry Andric NOINLINE 56268d75effSDimitry Andric void __msan_clear_on_return() { 56368d75effSDimitry Andric __msan_param_tls[0] = 0; 56468d75effSDimitry Andric } 56568d75effSDimitry Andric 56668d75effSDimitry Andric void __msan_partial_poison(const void* data, void* shadow, uptr size) { 56768d75effSDimitry Andric internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); 56868d75effSDimitry Andric } 56968d75effSDimitry Andric 57068d75effSDimitry Andric void __msan_load_unpoisoned(const void *src, uptr size, void *dst) { 57168d75effSDimitry Andric internal_memcpy(dst, src, size); 57268d75effSDimitry Andric __msan_unpoison(dst, size); 57368d75effSDimitry Andric } 57468d75effSDimitry Andric 57568d75effSDimitry Andric void __msan_set_origin(const void *a, uptr size, u32 origin) { 57668d75effSDimitry Andric if (__msan_get_track_origins()) SetOrigin(a, size, origin); 57768d75effSDimitry Andric } 57868d75effSDimitry Andric 57968d75effSDimitry Andric // 'descr' is created at compile time and contains '----' in the beginning. 58068d75effSDimitry Andric // When we see descr for the first time we replace '----' with a uniq id 58168d75effSDimitry Andric // and set the origin to (id | (31-th bit)). 58268d75effSDimitry Andric void __msan_set_alloca_origin(void *a, uptr size, char *descr) { 58368d75effSDimitry Andric __msan_set_alloca_origin4(a, size, descr, 0); 58468d75effSDimitry Andric } 58568d75effSDimitry Andric 58668d75effSDimitry Andric void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) { 58768d75effSDimitry Andric static const u32 dash = '-'; 58868d75effSDimitry Andric static const u32 first_timer = 58968d75effSDimitry Andric dash + (dash << 8) + (dash << 16) + (dash << 24); 59068d75effSDimitry Andric u32 *id_ptr = (u32*)descr; 59168d75effSDimitry Andric bool print = false; // internal_strstr(descr + 4, "AllocaTOTest") != 0; 59268d75effSDimitry Andric u32 id = *id_ptr; 59368d75effSDimitry Andric if (id == first_timer) { 59468d75effSDimitry Andric u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); 59568d75effSDimitry Andric CHECK_LT(idx, kNumStackOriginDescrs); 59668d75effSDimitry Andric StackOriginDescr[idx] = descr + 4; 59768d75effSDimitry Andric #if SANITIZER_PPC64V1 59868d75effSDimitry Andric // On PowerPC64 ELFv1, the address of a function actually points to a 59968d75effSDimitry Andric // three-doubleword data structure with the first field containing 60068d75effSDimitry Andric // the address of the function's code. 60168d75effSDimitry Andric if (pc) 60268d75effSDimitry Andric pc = *reinterpret_cast<uptr*>(pc); 60368d75effSDimitry Andric #endif 60468d75effSDimitry Andric StackOriginPC[idx] = pc; 60568d75effSDimitry Andric id = Origin::CreateStackOrigin(idx).raw_id(); 60668d75effSDimitry Andric *id_ptr = id; 60768d75effSDimitry Andric if (print) 608*349cc55cSDimitry Andric Printf("First time: idx=%d id=%d %s 0x%zx \n", idx, id, descr + 4, pc); 60968d75effSDimitry Andric } 61068d75effSDimitry Andric if (print) 61168d75effSDimitry Andric Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id); 61268d75effSDimitry Andric __msan_set_origin(a, size, id); 61368d75effSDimitry Andric } 61468d75effSDimitry Andric 61568d75effSDimitry Andric u32 __msan_chain_origin(u32 id) { 61668d75effSDimitry Andric GET_CALLER_PC_BP_SP; 61768d75effSDimitry Andric (void)sp; 61868d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); 61968d75effSDimitry Andric return ChainOrigin(id, &stack); 62068d75effSDimitry Andric } 62168d75effSDimitry Andric 62268d75effSDimitry Andric u32 __msan_get_origin(const void *a) { 62368d75effSDimitry Andric if (!__msan_get_track_origins()) return 0; 62468d75effSDimitry Andric uptr x = (uptr)a; 62568d75effSDimitry Andric uptr aligned = x & ~3ULL; 62668d75effSDimitry Andric uptr origin_ptr = MEM_TO_ORIGIN(aligned); 62768d75effSDimitry Andric return *(u32*)origin_ptr; 62868d75effSDimitry Andric } 62968d75effSDimitry Andric 63068d75effSDimitry Andric int __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id) { 63168d75effSDimitry Andric Origin o = Origin::FromRawId(this_id); 63268d75effSDimitry Andric while (o.raw_id() != prev_id && o.isChainedOrigin()) 63368d75effSDimitry Andric o = o.getNextChainedOrigin(nullptr); 63468d75effSDimitry Andric return o.raw_id() == prev_id; 63568d75effSDimitry Andric } 63668d75effSDimitry Andric 63768d75effSDimitry Andric u32 __msan_get_umr_origin() { 63868d75effSDimitry Andric return __msan_origin_tls; 63968d75effSDimitry Andric } 64068d75effSDimitry Andric 64168d75effSDimitry Andric u16 __sanitizer_unaligned_load16(const uu16 *p) { 6425ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6435ffd83dbSDimitry Andric sizeof(uu16)); 64468d75effSDimitry Andric if (__msan_get_track_origins()) 64568d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 64668d75effSDimitry Andric return *p; 64768d75effSDimitry Andric } 64868d75effSDimitry Andric u32 __sanitizer_unaligned_load32(const uu32 *p) { 6495ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6505ffd83dbSDimitry Andric sizeof(uu32)); 65168d75effSDimitry Andric if (__msan_get_track_origins()) 65268d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 65368d75effSDimitry Andric return *p; 65468d75effSDimitry Andric } 65568d75effSDimitry Andric u64 __sanitizer_unaligned_load64(const uu64 *p) { 6565ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6575ffd83dbSDimitry Andric sizeof(uu64)); 65868d75effSDimitry Andric if (__msan_get_track_origins()) 65968d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 66068d75effSDimitry Andric return *p; 66168d75effSDimitry Andric } 66268d75effSDimitry Andric void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 6635ffd83dbSDimitry Andric static_assert(sizeof(uu16) == sizeof(u16), "incompatible types"); 6645ffd83dbSDimitry Andric u16 s; 6655ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu16)); 6665ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu16)); 66768d75effSDimitry Andric if (s && __msan_get_track_origins()) 66868d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 66968d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 67068d75effSDimitry Andric *p = x; 67168d75effSDimitry Andric } 67268d75effSDimitry Andric void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 6735ffd83dbSDimitry Andric static_assert(sizeof(uu32) == sizeof(u32), "incompatible types"); 6745ffd83dbSDimitry Andric u32 s; 6755ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu32)); 6765ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu32)); 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_store64(uu64 *p, u64 x) { 68368d75effSDimitry Andric u64 s = __msan_param_tls[1]; 68468d75effSDimitry Andric *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; 68568d75effSDimitry Andric if (s && __msan_get_track_origins()) 68668d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 68768d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 68868d75effSDimitry Andric *p = x; 68968d75effSDimitry Andric } 69068d75effSDimitry Andric 69168d75effSDimitry Andric void __msan_set_death_callback(void (*callback)(void)) { 69268d75effSDimitry Andric SetUserDieCallback(callback); 69368d75effSDimitry Andric } 69468d75effSDimitry Andric 695e8d8bef9SDimitry Andric void __msan_start_switch_fiber(const void *bottom, uptr size) { 696e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 697e8d8bef9SDimitry Andric if (!t) { 698e8d8bef9SDimitry Andric VReport(1, "__msan_start_switch_fiber called from unknown thread\n"); 699e8d8bef9SDimitry Andric return; 700e8d8bef9SDimitry Andric } 701e8d8bef9SDimitry Andric t->StartSwitchFiber((uptr)bottom, size); 702e8d8bef9SDimitry Andric } 703e8d8bef9SDimitry Andric 704e8d8bef9SDimitry Andric void __msan_finish_switch_fiber(const void **bottom_old, uptr *size_old) { 705e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 706e8d8bef9SDimitry Andric if (!t) { 707e8d8bef9SDimitry Andric VReport(1, "__msan_finish_switch_fiber called from unknown thread\n"); 708e8d8bef9SDimitry Andric return; 709e8d8bef9SDimitry Andric } 710e8d8bef9SDimitry Andric t->FinishSwitchFiber((uptr *)bottom_old, (uptr *)size_old); 711e8d8bef9SDimitry Andric 712e8d8bef9SDimitry Andric internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 713e8d8bef9SDimitry Andric internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 714e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 715e8d8bef9SDimitry Andric 716e8d8bef9SDimitry Andric if (__msan_get_track_origins()) { 717e8d8bef9SDimitry Andric internal_memset(__msan_param_origin_tls, 0, 718e8d8bef9SDimitry Andric sizeof(__msan_param_origin_tls)); 719e8d8bef9SDimitry Andric internal_memset(&__msan_retval_origin_tls, 0, 720e8d8bef9SDimitry Andric sizeof(__msan_retval_origin_tls)); 721e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_origin_tls, 0, 722e8d8bef9SDimitry Andric sizeof(__msan_va_arg_origin_tls)); 723e8d8bef9SDimitry Andric } 724e8d8bef9SDimitry Andric } 725e8d8bef9SDimitry Andric 726e8d8bef9SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char *, __msan_default_options, void) { 727e8d8bef9SDimitry Andric return ""; 728e8d8bef9SDimitry Andric } 72968d75effSDimitry Andric 73068d75effSDimitry Andric extern "C" { 73168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 73268d75effSDimitry Andric void __sanitizer_print_stack_trace() { 73368d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 73468d75effSDimitry Andric stack.Print(); 73568d75effSDimitry Andric } 73668d75effSDimitry Andric } // extern "C" 737