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 5968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6068d75effSDimitry Andric ALIGNED(16) THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; 6168d75effSDimitry Andric 6268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6368d75effSDimitry Andric ALIGNED(16) 6468d75effSDimitry Andric THREADLOCAL u32 __msan_va_arg_origin_tls[kMsanParamTlsSize / sizeof(u32)]; 6568d75effSDimitry Andric 6668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 6768d75effSDimitry Andric THREADLOCAL u64 __msan_va_arg_overflow_size_tls; 6868d75effSDimitry Andric 6968d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 7068d75effSDimitry Andric THREADLOCAL u32 __msan_origin_tls; 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 8281ad6265SDimitry Andric static THREADLOCAL int is_in_symbolizer_or_unwinder; 8381ad6265SDimitry Andric static void EnterSymbolizerOrUnwider() { ++is_in_symbolizer_or_unwinder; } 8481ad6265SDimitry Andric static void ExitSymbolizerOrUnwider() { --is_in_symbolizer_or_unwinder; } 8581ad6265SDimitry Andric bool IsInSymbolizerOrUnwider() { return is_in_symbolizer_or_unwinder; } 8681ad6265SDimitry Andric 8781ad6265SDimitry Andric struct UnwinderScope { 8881ad6265SDimitry Andric UnwinderScope() { EnterSymbolizerOrUnwider(); } 8981ad6265SDimitry Andric ~UnwinderScope() { ExitSymbolizerOrUnwider(); } 9081ad6265SDimitry Andric }; 9168d75effSDimitry Andric 9268d75effSDimitry Andric static Flags msan_flags; 9368d75effSDimitry Andric 9481ad6265SDimitry Andric Flags *flags() { return &msan_flags; } 9568d75effSDimitry Andric 9668d75effSDimitry Andric int msan_inited = 0; 9768d75effSDimitry Andric bool msan_init_is_running; 9868d75effSDimitry Andric 9968d75effSDimitry Andric int msan_report_count = 0; 10068d75effSDimitry Andric 10168d75effSDimitry Andric // Array of stack origins. 10268d75effSDimitry Andric // FIXME: make it resizable. 10368d75effSDimitry Andric static const uptr kNumStackOriginDescrs = 1024 * 1024; 10468d75effSDimitry Andric static const char *StackOriginDescr[kNumStackOriginDescrs]; 10568d75effSDimitry Andric static uptr StackOriginPC[kNumStackOriginDescrs]; 10668d75effSDimitry Andric static atomic_uint32_t NumStackOriginDescrs; 10768d75effSDimitry Andric 10868d75effSDimitry Andric void Flags::SetDefaults() { 10968d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 11068d75effSDimitry Andric #include "msan_flags.inc" 11168d75effSDimitry Andric #undef MSAN_FLAG 11268d75effSDimitry Andric } 11368d75effSDimitry Andric 11468d75effSDimitry Andric // keep_going is an old name for halt_on_error, 11568d75effSDimitry Andric // and it has inverse meaning. 116e8d8bef9SDimitry Andric class FlagHandlerKeepGoing final : public FlagHandlerBase { 11768d75effSDimitry Andric bool *halt_on_error_; 11868d75effSDimitry Andric 11968d75effSDimitry Andric public: 12068d75effSDimitry Andric explicit FlagHandlerKeepGoing(bool *halt_on_error) 12168d75effSDimitry Andric : halt_on_error_(halt_on_error) {} 12268d75effSDimitry Andric bool Parse(const char *value) final { 12368d75effSDimitry Andric bool tmp; 12468d75effSDimitry Andric FlagHandler<bool> h(&tmp); 12568d75effSDimitry Andric if (!h.Parse(value)) return false; 12668d75effSDimitry Andric *halt_on_error_ = !tmp; 12768d75effSDimitry Andric return true; 12868d75effSDimitry Andric } 129480093f4SDimitry Andric bool Format(char *buffer, uptr size) final { 130480093f4SDimitry Andric const char *keep_going_str = (*halt_on_error_) ? "false" : "true"; 131480093f4SDimitry Andric return FormatString(buffer, size, keep_going_str); 132480093f4SDimitry Andric } 13368d75effSDimitry Andric }; 13468d75effSDimitry Andric 13568d75effSDimitry Andric static void RegisterMsanFlags(FlagParser *parser, Flags *f) { 13668d75effSDimitry Andric #define MSAN_FLAG(Type, Name, DefaultValue, Description) \ 13768d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 13868d75effSDimitry Andric #include "msan_flags.inc" 13968d75effSDimitry Andric #undef MSAN_FLAG 14068d75effSDimitry Andric 141*5f757f3fSDimitry Andric FlagHandlerKeepGoing *fh_keep_going = new (GetGlobalLowLevelAllocator()) 142*5f757f3fSDimitry Andric FlagHandlerKeepGoing(&f->halt_on_error); 14368d75effSDimitry Andric parser->RegisterHandler("keep_going", fh_keep_going, 14468d75effSDimitry Andric "deprecated, use halt_on_error"); 14568d75effSDimitry Andric } 14668d75effSDimitry Andric 14768d75effSDimitry Andric static void InitializeFlags() { 14868d75effSDimitry Andric SetCommonFlagsDefaults(); 14968d75effSDimitry Andric { 15068d75effSDimitry Andric CommonFlags cf; 15168d75effSDimitry Andric cf.CopyFrom(*common_flags()); 15268d75effSDimitry Andric cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); 15368d75effSDimitry Andric cf.malloc_context_size = 20; 15468d75effSDimitry Andric cf.handle_ioctl = true; 15568d75effSDimitry Andric // FIXME: test and enable. 15668d75effSDimitry Andric cf.check_printf = false; 15768d75effSDimitry Andric cf.intercept_tls_get_addr = true; 15868d75effSDimitry Andric OverrideCommonFlags(cf); 15968d75effSDimitry Andric } 16068d75effSDimitry Andric 16168d75effSDimitry Andric Flags *f = flags(); 16268d75effSDimitry Andric f->SetDefaults(); 16368d75effSDimitry Andric 16468d75effSDimitry Andric FlagParser parser; 16568d75effSDimitry Andric RegisterMsanFlags(&parser, f); 16668d75effSDimitry Andric RegisterCommonFlags(&parser); 16768d75effSDimitry Andric 16868d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 16968d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 17068d75effSDimitry Andric uf->SetDefaults(); 17168d75effSDimitry Andric 17268d75effSDimitry Andric FlagParser ubsan_parser; 17368d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 17468d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 17568d75effSDimitry Andric #endif 17668d75effSDimitry Andric 17768d75effSDimitry Andric // Override from user-specified string. 17868d75effSDimitry Andric parser.ParseString(__msan_default_options()); 17968d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 180e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 18168d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 18268d75effSDimitry Andric #endif 18368d75effSDimitry Andric 18468d75effSDimitry Andric parser.ParseStringFromEnv("MSAN_OPTIONS"); 18568d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 18668d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 18768d75effSDimitry Andric #endif 18868d75effSDimitry Andric 18968d75effSDimitry Andric InitializeCommonFlags(); 19068d75effSDimitry Andric 19168d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 19268d75effSDimitry Andric 19368d75effSDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 19468d75effSDimitry Andric 19568d75effSDimitry Andric // Check if deprecated exit_code MSan flag is set. 19668d75effSDimitry Andric if (f->exit_code != -1) { 19768d75effSDimitry Andric if (Verbosity()) 19868d75effSDimitry Andric Printf("MSAN_OPTIONS=exit_code is deprecated! " 19968d75effSDimitry Andric "Please use MSAN_OPTIONS=exitcode instead.\n"); 20068d75effSDimitry Andric CommonFlags cf; 20168d75effSDimitry Andric cf.CopyFrom(*common_flags()); 20268d75effSDimitry Andric cf.exitcode = f->exit_code; 20368d75effSDimitry Andric OverrideCommonFlags(cf); 20468d75effSDimitry Andric } 20568d75effSDimitry Andric 20668d75effSDimitry Andric // Check flag values: 20768d75effSDimitry Andric if (f->origin_history_size < 0 || 20868d75effSDimitry Andric f->origin_history_size > Origin::kMaxDepth) { 20968d75effSDimitry Andric Printf( 21068d75effSDimitry Andric "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " 21168d75effSDimitry Andric "range.\n", 21268d75effSDimitry Andric f->origin_history_size, Origin::kMaxDepth); 21368d75effSDimitry Andric Die(); 21468d75effSDimitry Andric } 21568d75effSDimitry Andric // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in 21668d75effSDimitry Andric // StackDepotHandle::inc_use_count_unsafe. 21768d75effSDimitry Andric if (f->origin_history_per_stack_limit < 0 || 21868d75effSDimitry Andric f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { 21968d75effSDimitry Andric Printf( 22068d75effSDimitry Andric "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " 22168d75effSDimitry Andric "%d] range.\n", 22268d75effSDimitry Andric f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); 22368d75effSDimitry Andric Die(); 22468d75effSDimitry Andric } 22568d75effSDimitry Andric if (f->store_context_size < 1) f->store_context_size = 1; 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 302bdd1243dSDimitry Andric // Current implementation separates the 'id_ptr' from the 'descr' and makes 303bdd1243dSDimitry Andric // 'descr' constant. 304bdd1243dSDimitry Andric // Previous implementation 'descr' is created at compile time and contains 305bdd1243dSDimitry Andric // '----' in the beginning. When we see descr for the first time we replace 306bdd1243dSDimitry Andric // '----' with a uniq id and set the origin to (id | (31-th bit)). 307bdd1243dSDimitry Andric static inline void SetAllocaOrigin(void *a, uptr size, u32 *id_ptr, char *descr, 308bdd1243dSDimitry Andric uptr pc) { 309bdd1243dSDimitry Andric static const u32 dash = '-'; 310bdd1243dSDimitry Andric static const u32 first_timer = 311bdd1243dSDimitry Andric dash + (dash << 8) + (dash << 16) + (dash << 24); 312bdd1243dSDimitry Andric u32 id = *id_ptr; 313bdd1243dSDimitry Andric if (id == 0 || id == first_timer) { 314bdd1243dSDimitry Andric u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); 315bdd1243dSDimitry Andric CHECK_LT(idx, kNumStackOriginDescrs); 316bdd1243dSDimitry Andric StackOriginDescr[idx] = descr; 317bdd1243dSDimitry Andric StackOriginPC[idx] = pc; 318bdd1243dSDimitry Andric id = Origin::CreateStackOrigin(idx).raw_id(); 319bdd1243dSDimitry Andric *id_ptr = id; 320bdd1243dSDimitry Andric } 321bdd1243dSDimitry Andric __msan_set_origin(a, size, id); 322bdd1243dSDimitry Andric } 323bdd1243dSDimitry Andric 32468d75effSDimitry Andric } // namespace __msan 32568d75effSDimitry Andric 32668d75effSDimitry Andric void __sanitizer::BufferedStackTrace::UnwindImpl( 32768d75effSDimitry Andric uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 32868d75effSDimitry Andric using namespace __msan; 32968d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 33068d75effSDimitry Andric if (!t || !StackTrace::WillUseFastUnwind(request_fast)) { 33168d75effSDimitry Andric // Block reports from our interceptors during _Unwind_Backtrace. 33281ad6265SDimitry Andric UnwinderScope sym_scope; 333fe6060f1SDimitry Andric return Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0, 334fe6060f1SDimitry Andric t ? t->stack_bottom() : 0, false); 33568d75effSDimitry Andric } 33668d75effSDimitry Andric if (StackTrace::WillUseFastUnwind(request_fast)) 33768d75effSDimitry Andric Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true); 33868d75effSDimitry Andric else 33968d75effSDimitry Andric Unwind(max_depth, pc, 0, context, 0, 0, false); 34068d75effSDimitry Andric } 34168d75effSDimitry Andric 34268d75effSDimitry Andric // Interface. 34368d75effSDimitry Andric 34468d75effSDimitry Andric using namespace __msan; 34568d75effSDimitry Andric 34668d75effSDimitry Andric #define MSAN_MAYBE_WARNING(type, size) \ 34768d75effSDimitry Andric void __msan_maybe_warning_##size(type s, u32 o) { \ 34806c3fb27SDimitry Andric GET_CALLER_PC_BP; \ 34968d75effSDimitry Andric if (UNLIKELY(s)) { \ 35068d75effSDimitry Andric PrintWarningWithOrigin(pc, bp, o); \ 35168d75effSDimitry Andric if (__msan::flags()->halt_on_error) { \ 35268d75effSDimitry Andric Printf("Exiting\n"); \ 35368d75effSDimitry Andric Die(); \ 35468d75effSDimitry Andric } \ 35568d75effSDimitry Andric } \ 35668d75effSDimitry Andric } 35768d75effSDimitry Andric 35868d75effSDimitry Andric MSAN_MAYBE_WARNING(u8, 1) 35968d75effSDimitry Andric MSAN_MAYBE_WARNING(u16, 2) 36068d75effSDimitry Andric MSAN_MAYBE_WARNING(u32, 4) 36168d75effSDimitry Andric MSAN_MAYBE_WARNING(u64, 8) 36268d75effSDimitry Andric 36368d75effSDimitry Andric #define MSAN_MAYBE_STORE_ORIGIN(type, size) \ 36468d75effSDimitry Andric void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \ 36568d75effSDimitry Andric if (UNLIKELY(s)) { \ 36668d75effSDimitry Andric if (__msan_get_track_origins() > 1) { \ 36706c3fb27SDimitry Andric GET_CALLER_PC_BP; \ 36868d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); \ 36968d75effSDimitry Andric o = ChainOrigin(o, &stack); \ 37068d75effSDimitry Andric } \ 37168d75effSDimitry Andric *(u32 *)MEM_TO_ORIGIN((uptr)p & ~3UL) = o; \ 37268d75effSDimitry Andric } \ 37368d75effSDimitry Andric } 37468d75effSDimitry Andric 37568d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u8, 1) 37668d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u16, 2) 37768d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u32, 4) 37868d75effSDimitry Andric MSAN_MAYBE_STORE_ORIGIN(u64, 8) 37968d75effSDimitry Andric 38068d75effSDimitry Andric void __msan_warning() { 38106c3fb27SDimitry Andric GET_CALLER_PC_BP; 382bdd1243dSDimitry Andric PrintWarningWithOrigin(pc, bp, 0); 38368d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 38468d75effSDimitry Andric if (__msan::flags()->print_stats) 38568d75effSDimitry Andric ReportStats(); 38668d75effSDimitry Andric Printf("Exiting\n"); 38768d75effSDimitry Andric Die(); 38868d75effSDimitry Andric } 38968d75effSDimitry Andric } 39068d75effSDimitry Andric 39168d75effSDimitry Andric void __msan_warning_noreturn() { 39206c3fb27SDimitry Andric GET_CALLER_PC_BP; 393bdd1243dSDimitry Andric PrintWarningWithOrigin(pc, bp, 0); 39468d75effSDimitry Andric if (__msan::flags()->print_stats) 39568d75effSDimitry Andric ReportStats(); 39668d75effSDimitry Andric Printf("Exiting\n"); 39768d75effSDimitry Andric Die(); 39868d75effSDimitry Andric } 39968d75effSDimitry Andric 4005ffd83dbSDimitry Andric void __msan_warning_with_origin(u32 origin) { 40106c3fb27SDimitry Andric GET_CALLER_PC_BP; 4025ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 4035ffd83dbSDimitry Andric if (__msan::flags()->halt_on_error) { 4045ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 4055ffd83dbSDimitry Andric ReportStats(); 4065ffd83dbSDimitry Andric Printf("Exiting\n"); 4075ffd83dbSDimitry Andric Die(); 4085ffd83dbSDimitry Andric } 4095ffd83dbSDimitry Andric } 4105ffd83dbSDimitry Andric 4115ffd83dbSDimitry Andric void __msan_warning_with_origin_noreturn(u32 origin) { 41206c3fb27SDimitry Andric GET_CALLER_PC_BP; 4135ffd83dbSDimitry Andric PrintWarningWithOrigin(pc, bp, origin); 4145ffd83dbSDimitry Andric if (__msan::flags()->print_stats) 4155ffd83dbSDimitry Andric ReportStats(); 4165ffd83dbSDimitry Andric Printf("Exiting\n"); 4175ffd83dbSDimitry Andric Die(); 4185ffd83dbSDimitry Andric } 4195ffd83dbSDimitry Andric 42068d75effSDimitry Andric static void OnStackUnwind(const SignalContext &sig, const void *, 42168d75effSDimitry Andric BufferedStackTrace *stack) { 42268d75effSDimitry Andric stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 42368d75effSDimitry Andric common_flags()->fast_unwind_on_fatal); 42468d75effSDimitry Andric } 42568d75effSDimitry Andric 42668d75effSDimitry Andric static void MsanOnDeadlySignal(int signo, void *siginfo, void *context) { 42768d75effSDimitry Andric HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr); 42868d75effSDimitry Andric } 42968d75effSDimitry Andric 430fe6060f1SDimitry Andric static void CheckUnwind() { 431fe6060f1SDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 432fe6060f1SDimitry Andric stack.Print(); 43368d75effSDimitry Andric } 43468d75effSDimitry Andric 43568d75effSDimitry Andric void __msan_init() { 43668d75effSDimitry Andric CHECK(!msan_init_is_running); 43768d75effSDimitry Andric if (msan_inited) return; 43868d75effSDimitry Andric msan_init_is_running = 1; 43968d75effSDimitry Andric SanitizerToolName = "MemorySanitizer"; 44068d75effSDimitry Andric 44168d75effSDimitry Andric AvoidCVE_2016_2143(); 44268d75effSDimitry Andric 44368d75effSDimitry Andric CacheBinaryName(); 44468d75effSDimitry Andric InitializeFlags(); 44568d75effSDimitry Andric 44668d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 447fe6060f1SDimitry Andric SetCheckUnwindCallback(CheckUnwind); 44868d75effSDimitry Andric 44968d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 45068d75effSDimitry Andric 45168d75effSDimitry Andric InitializeInterceptors(); 452*5f757f3fSDimitry Andric InstallAtForkHandler(); 45368d75effSDimitry Andric CheckASLR(); 45468d75effSDimitry Andric InitTlsSize(); 45568d75effSDimitry Andric InstallDeadlySignalHandlers(MsanOnDeadlySignal); 45668d75effSDimitry Andric InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 45768d75effSDimitry Andric 45868d75effSDimitry Andric DisableCoreDumperIfNecessary(); 45968d75effSDimitry Andric if (StackSizeIsUnlimited()) { 46068d75effSDimitry Andric VPrintf(1, "Unlimited stack, doing reexec\n"); 46168d75effSDimitry Andric // A reasonably large stack size. It is bigger than the usual 8Mb, because, 46268d75effSDimitry Andric // well, the program could have been run with unlimited stack for a reason. 46368d75effSDimitry Andric SetStackSizeLimitInBytes(32 * 1024 * 1024); 46468d75effSDimitry Andric ReExec(); 46568d75effSDimitry Andric } 46668d75effSDimitry Andric 46768d75effSDimitry Andric __msan_clear_on_return(); 46868d75effSDimitry Andric if (__msan_get_track_origins()) 46968d75effSDimitry Andric VPrintf(1, "msan_track_origins\n"); 47068d75effSDimitry Andric if (!InitShadow(__msan_get_track_origins())) { 47168d75effSDimitry Andric Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); 47268d75effSDimitry Andric Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 47368d75effSDimitry Andric Printf("FATAL: Disabling ASLR is known to cause this error.\n"); 47468d75effSDimitry Andric Printf("FATAL: If running under GDB, try " 47568d75effSDimitry Andric "'set disable-randomization off'.\n"); 47668d75effSDimitry Andric DumpProcessMap(); 47768d75effSDimitry Andric Die(); 47868d75effSDimitry Andric } 47968d75effSDimitry Andric 48081ad6265SDimitry Andric Symbolizer::GetOrInit()->AddHooks(EnterSymbolizerOrUnwider, 48181ad6265SDimitry Andric ExitSymbolizerOrUnwider); 48268d75effSDimitry Andric 48368d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 48468d75effSDimitry Andric 48568d75effSDimitry Andric MsanTSDInit(MsanTSDDtor); 48668d75effSDimitry Andric 48768d75effSDimitry Andric MsanAllocatorInit(); 48868d75effSDimitry Andric 48968d75effSDimitry Andric MsanThread *main_thread = MsanThread::Create(nullptr, nullptr); 49068d75effSDimitry Andric SetCurrentThread(main_thread); 491349cc55cSDimitry Andric main_thread->Init(); 49268d75effSDimitry Andric 49368d75effSDimitry Andric #if MSAN_CONTAINS_UBSAN 49468d75effSDimitry Andric __ubsan::InitAsPlugin(); 49568d75effSDimitry Andric #endif 49668d75effSDimitry Andric 49768d75effSDimitry Andric VPrintf(1, "MemorySanitizer init done\n"); 49868d75effSDimitry Andric 49968d75effSDimitry Andric msan_init_is_running = 0; 50068d75effSDimitry Andric msan_inited = 1; 50168d75effSDimitry Andric } 50268d75effSDimitry Andric 50368d75effSDimitry Andric void __msan_set_keep_going(int keep_going) { 50468d75effSDimitry Andric flags()->halt_on_error = !keep_going; 50568d75effSDimitry Andric } 50668d75effSDimitry Andric 50768d75effSDimitry Andric void __msan_set_expect_umr(int expect_umr) { 50868d75effSDimitry Andric if (expect_umr) { 50968d75effSDimitry Andric msan_expected_umr_found = 0; 51068d75effSDimitry Andric } else if (!msan_expected_umr_found) { 51106c3fb27SDimitry Andric GET_CALLER_PC_BP; 51268d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 51368d75effSDimitry Andric ReportExpectedUMRNotFound(&stack); 51468d75effSDimitry Andric Die(); 51568d75effSDimitry Andric } 51668d75effSDimitry Andric msan_expect_umr = expect_umr; 51768d75effSDimitry Andric } 51868d75effSDimitry Andric 51968d75effSDimitry Andric void __msan_print_shadow(const void *x, uptr size) { 52068d75effSDimitry Andric if (!MEM_IS_APP(x)) { 52168d75effSDimitry Andric Printf("Not a valid application address: %p\n", x); 52268d75effSDimitry Andric return; 52368d75effSDimitry Andric } 52468d75effSDimitry Andric 52568d75effSDimitry Andric DescribeMemoryRange(x, size); 52668d75effSDimitry Andric } 52768d75effSDimitry Andric 52868d75effSDimitry Andric void __msan_dump_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 unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); 535349cc55cSDimitry Andric Printf("%p[%p] ", (void *)s, x); 53668d75effSDimitry Andric for (uptr i = 0; i < size; i++) 53768d75effSDimitry Andric Printf("%x%x ", s[i] >> 4, s[i] & 0xf); 53868d75effSDimitry Andric Printf("\n"); 53968d75effSDimitry Andric } 54068d75effSDimitry Andric 54168d75effSDimitry Andric sptr __msan_test_shadow(const void *x, uptr size) { 54268d75effSDimitry Andric if (!MEM_IS_APP(x)) return -1; 54368d75effSDimitry Andric unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x); 544e8d8bef9SDimitry Andric if (__sanitizer::mem_is_zero((const char *)s, size)) 545e8d8bef9SDimitry Andric return -1; 546e8d8bef9SDimitry Andric // Slow path: loop through again to find the location. 54768d75effSDimitry Andric for (uptr i = 0; i < size; ++i) 54868d75effSDimitry Andric if (s[i]) 54968d75effSDimitry Andric return i; 55068d75effSDimitry Andric return -1; 55168d75effSDimitry Andric } 55268d75effSDimitry Andric 55368d75effSDimitry Andric void __msan_check_mem_is_initialized(const void *x, uptr size) { 55468d75effSDimitry Andric if (!__msan::flags()->report_umrs) return; 55568d75effSDimitry Andric sptr offset = __msan_test_shadow(x, size); 55668d75effSDimitry Andric if (offset < 0) 55768d75effSDimitry Andric return; 55868d75effSDimitry Andric 55906c3fb27SDimitry Andric GET_CALLER_PC_BP; 56068d75effSDimitry Andric ReportUMRInsideAddressRange(__func__, x, size, offset); 56168d75effSDimitry Andric __msan::PrintWarningWithOrigin(pc, bp, 56268d75effSDimitry Andric __msan_get_origin(((const char *)x) + offset)); 56368d75effSDimitry Andric if (__msan::flags()->halt_on_error) { 56468d75effSDimitry Andric Printf("Exiting\n"); 56568d75effSDimitry Andric Die(); 56668d75effSDimitry Andric } 56768d75effSDimitry Andric } 56868d75effSDimitry Andric 56968d75effSDimitry Andric int __msan_set_poison_in_malloc(int do_poison) { 57068d75effSDimitry Andric int old = flags()->poison_in_malloc; 57168d75effSDimitry Andric flags()->poison_in_malloc = do_poison; 57268d75effSDimitry Andric return old; 57368d75effSDimitry Andric } 57468d75effSDimitry Andric 57568d75effSDimitry Andric int __msan_has_dynamic_component() { return false; } 57668d75effSDimitry Andric 57768d75effSDimitry Andric NOINLINE 57868d75effSDimitry Andric void __msan_clear_on_return() { 57968d75effSDimitry Andric __msan_param_tls[0] = 0; 58068d75effSDimitry Andric } 58168d75effSDimitry Andric 58268d75effSDimitry Andric void __msan_partial_poison(const void* data, void* shadow, uptr size) { 58368d75effSDimitry Andric internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); 58468d75effSDimitry Andric } 58568d75effSDimitry Andric 58668d75effSDimitry Andric void __msan_load_unpoisoned(const void *src, uptr size, void *dst) { 58768d75effSDimitry Andric internal_memcpy(dst, src, size); 58868d75effSDimitry Andric __msan_unpoison(dst, size); 58968d75effSDimitry Andric } 59068d75effSDimitry Andric 59168d75effSDimitry Andric void __msan_set_origin(const void *a, uptr size, u32 origin) { 59268d75effSDimitry Andric if (__msan_get_track_origins()) SetOrigin(a, size, origin); 59368d75effSDimitry Andric } 59468d75effSDimitry Andric 59568d75effSDimitry Andric void __msan_set_alloca_origin(void *a, uptr size, char *descr) { 596bdd1243dSDimitry Andric SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4, 597bdd1243dSDimitry Andric GET_CALLER_PC()); 59868d75effSDimitry Andric } 59968d75effSDimitry Andric 60068d75effSDimitry Andric void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) { 601bdd1243dSDimitry Andric // Intentionally ignore pc and use return address. This function is here for 602bdd1243dSDimitry Andric // compatibility, in case program is linked with library instrumented by 603bdd1243dSDimitry Andric // older clang. 604bdd1243dSDimitry Andric SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4, 605bdd1243dSDimitry Andric GET_CALLER_PC()); 60668d75effSDimitry Andric } 607bdd1243dSDimitry Andric 608bdd1243dSDimitry Andric void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr, 609bdd1243dSDimitry Andric char *descr) { 610bdd1243dSDimitry Andric SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC()); 611bdd1243dSDimitry Andric } 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr) { 614bdd1243dSDimitry Andric SetAllocaOrigin(a, size, id_ptr, nullptr, GET_CALLER_PC()); 61568d75effSDimitry Andric } 61668d75effSDimitry Andric 61768d75effSDimitry Andric u32 __msan_chain_origin(u32 id) { 61806c3fb27SDimitry Andric GET_CALLER_PC_BP; 61968d75effSDimitry Andric GET_STORE_STACK_TRACE_PC_BP(pc, bp); 62068d75effSDimitry Andric return ChainOrigin(id, &stack); 62168d75effSDimitry Andric } 62268d75effSDimitry Andric 62368d75effSDimitry Andric u32 __msan_get_origin(const void *a) { 62468d75effSDimitry Andric if (!__msan_get_track_origins()) return 0; 62568d75effSDimitry Andric uptr x = (uptr)a; 62668d75effSDimitry Andric uptr aligned = x & ~3ULL; 62768d75effSDimitry Andric uptr origin_ptr = MEM_TO_ORIGIN(aligned); 62868d75effSDimitry Andric return *(u32*)origin_ptr; 62968d75effSDimitry Andric } 63068d75effSDimitry Andric 63168d75effSDimitry Andric int __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id) { 63268d75effSDimitry Andric Origin o = Origin::FromRawId(this_id); 63368d75effSDimitry Andric while (o.raw_id() != prev_id && o.isChainedOrigin()) 63468d75effSDimitry Andric o = o.getNextChainedOrigin(nullptr); 63568d75effSDimitry Andric return o.raw_id() == prev_id; 63668d75effSDimitry Andric } 63768d75effSDimitry Andric 63868d75effSDimitry Andric u32 __msan_get_umr_origin() { 63968d75effSDimitry Andric return __msan_origin_tls; 64068d75effSDimitry Andric } 64168d75effSDimitry Andric 64268d75effSDimitry Andric u16 __sanitizer_unaligned_load16(const uu16 *p) { 6435ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6445ffd83dbSDimitry Andric sizeof(uu16)); 64568d75effSDimitry Andric if (__msan_get_track_origins()) 64668d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 64768d75effSDimitry Andric return *p; 64868d75effSDimitry Andric } 64968d75effSDimitry Andric u32 __sanitizer_unaligned_load32(const uu32 *p) { 6505ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6515ffd83dbSDimitry Andric sizeof(uu32)); 65268d75effSDimitry Andric if (__msan_get_track_origins()) 65368d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 65468d75effSDimitry Andric return *p; 65568d75effSDimitry Andric } 65668d75effSDimitry Andric u64 __sanitizer_unaligned_load64(const uu64 *p) { 6575ffd83dbSDimitry Andric internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p), 6585ffd83dbSDimitry Andric sizeof(uu64)); 65968d75effSDimitry Andric if (__msan_get_track_origins()) 66068d75effSDimitry Andric __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 66168d75effSDimitry Andric return *p; 66268d75effSDimitry Andric } 66368d75effSDimitry Andric void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 6645ffd83dbSDimitry Andric static_assert(sizeof(uu16) == sizeof(u16), "incompatible types"); 6655ffd83dbSDimitry Andric u16 s; 6665ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu16)); 6675ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu16)); 66868d75effSDimitry Andric if (s && __msan_get_track_origins()) 66968d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 67068d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 67168d75effSDimitry Andric *p = x; 67268d75effSDimitry Andric } 67368d75effSDimitry Andric void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 6745ffd83dbSDimitry Andric static_assert(sizeof(uu32) == sizeof(u32), "incompatible types"); 6755ffd83dbSDimitry Andric u32 s; 6765ffd83dbSDimitry Andric internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu32)); 6775ffd83dbSDimitry Andric internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu32)); 67868d75effSDimitry Andric if (s && __msan_get_track_origins()) 67968d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 68068d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 68168d75effSDimitry Andric *p = x; 68268d75effSDimitry Andric } 68368d75effSDimitry Andric void __sanitizer_unaligned_store64(uu64 *p, u64 x) { 68468d75effSDimitry Andric u64 s = __msan_param_tls[1]; 68568d75effSDimitry Andric *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; 68668d75effSDimitry Andric if (s && __msan_get_track_origins()) 68768d75effSDimitry Andric if (uu32 o = __msan_param_origin_tls[2]) 68868d75effSDimitry Andric SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 68968d75effSDimitry Andric *p = x; 69068d75effSDimitry Andric } 69168d75effSDimitry Andric 69268d75effSDimitry Andric void __msan_set_death_callback(void (*callback)(void)) { 69368d75effSDimitry Andric SetUserDieCallback(callback); 69468d75effSDimitry Andric } 69568d75effSDimitry Andric 696e8d8bef9SDimitry Andric void __msan_start_switch_fiber(const void *bottom, uptr size) { 697e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 698e8d8bef9SDimitry Andric if (!t) { 699e8d8bef9SDimitry Andric VReport(1, "__msan_start_switch_fiber called from unknown thread\n"); 700e8d8bef9SDimitry Andric return; 701e8d8bef9SDimitry Andric } 702e8d8bef9SDimitry Andric t->StartSwitchFiber((uptr)bottom, size); 703e8d8bef9SDimitry Andric } 704e8d8bef9SDimitry Andric 705e8d8bef9SDimitry Andric void __msan_finish_switch_fiber(const void **bottom_old, uptr *size_old) { 706e8d8bef9SDimitry Andric MsanThread *t = GetCurrentThread(); 707e8d8bef9SDimitry Andric if (!t) { 708e8d8bef9SDimitry Andric VReport(1, "__msan_finish_switch_fiber called from unknown thread\n"); 709e8d8bef9SDimitry Andric return; 710e8d8bef9SDimitry Andric } 711e8d8bef9SDimitry Andric t->FinishSwitchFiber((uptr *)bottom_old, (uptr *)size_old); 712e8d8bef9SDimitry Andric 713e8d8bef9SDimitry Andric internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 714e8d8bef9SDimitry Andric internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 715e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 716e8d8bef9SDimitry Andric 717e8d8bef9SDimitry Andric if (__msan_get_track_origins()) { 718e8d8bef9SDimitry Andric internal_memset(__msan_param_origin_tls, 0, 719e8d8bef9SDimitry Andric sizeof(__msan_param_origin_tls)); 720e8d8bef9SDimitry Andric internal_memset(&__msan_retval_origin_tls, 0, 721e8d8bef9SDimitry Andric sizeof(__msan_retval_origin_tls)); 722e8d8bef9SDimitry Andric internal_memset(__msan_va_arg_origin_tls, 0, 723e8d8bef9SDimitry Andric sizeof(__msan_va_arg_origin_tls)); 724e8d8bef9SDimitry Andric } 725e8d8bef9SDimitry Andric } 726e8d8bef9SDimitry Andric 727e8d8bef9SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char *, __msan_default_options, void) { 728e8d8bef9SDimitry Andric return ""; 729e8d8bef9SDimitry Andric } 73068d75effSDimitry Andric 73168d75effSDimitry Andric extern "C" { 73268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 73368d75effSDimitry Andric void __sanitizer_print_stack_trace() { 73468d75effSDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 73568d75effSDimitry Andric stack.Print(); 73668d75effSDimitry Andric } 73768d75effSDimitry Andric } // extern "C" 738