msan.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1//===-- msan.cc -----------------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of MemorySanitizer. 11// 12// MemorySanitizer runtime. 13//===----------------------------------------------------------------------===// 14 15#include "msan.h" 16#include "msan_chained_origin_depot.h" 17#include "msan_origin.h" 18#include "msan_thread.h" 19#include "sanitizer_common/sanitizer_atomic.h" 20#include "sanitizer_common/sanitizer_common.h" 21#include "sanitizer_common/sanitizer_flags.h" 22#include "sanitizer_common/sanitizer_libc.h" 23#include "sanitizer_common/sanitizer_procmaps.h" 24#include "sanitizer_common/sanitizer_stacktrace.h" 25#include "sanitizer_common/sanitizer_symbolizer.h" 26#include "sanitizer_common/sanitizer_stackdepot.h" 27 28 29// ACHTUNG! No system header includes in this file. 30 31using namespace __sanitizer; 32 33// Globals. 34static THREADLOCAL int msan_expect_umr = 0; 35static THREADLOCAL int msan_expected_umr_found = 0; 36 37static bool msan_running_under_dr; 38 39// Function argument shadow. Each argument starts at the next available 8-byte 40// aligned address. 41SANITIZER_INTERFACE_ATTRIBUTE 42THREADLOCAL u64 __msan_param_tls[kMsanParamTlsSizeInWords]; 43 44// Function argument origin. Each argument starts at the same offset as the 45// corresponding shadow in (__msan_param_tls). Slightly weird, but changing this 46// would break compatibility with older prebuilt binaries. 47SANITIZER_INTERFACE_ATTRIBUTE 48THREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSizeInWords]; 49 50SANITIZER_INTERFACE_ATTRIBUTE 51THREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSizeInWords]; 52 53SANITIZER_INTERFACE_ATTRIBUTE 54THREADLOCAL u32 __msan_retval_origin_tls; 55 56SANITIZER_INTERFACE_ATTRIBUTE 57THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSizeInWords]; 58 59SANITIZER_INTERFACE_ATTRIBUTE 60THREADLOCAL u64 __msan_va_arg_overflow_size_tls; 61 62SANITIZER_INTERFACE_ATTRIBUTE 63THREADLOCAL u32 __msan_origin_tls; 64 65static THREADLOCAL int is_in_symbolizer; 66static THREADLOCAL int is_in_loader; 67 68extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins; 69 70int __msan_get_track_origins() { 71 return &__msan_track_origins ? __msan_track_origins : 0; 72} 73 74extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going; 75 76namespace __msan { 77 78void EnterSymbolizer() { ++is_in_symbolizer; } 79void ExitSymbolizer() { --is_in_symbolizer; } 80bool IsInSymbolizer() { return is_in_symbolizer; } 81 82void EnterLoader() { ++is_in_loader; } 83void ExitLoader() { --is_in_loader; } 84 85extern "C" { 86SANITIZER_INTERFACE_ATTRIBUTE 87bool __msan_is_in_loader() { return is_in_loader; } 88} 89 90static Flags msan_flags; 91 92Flags *flags() { 93 return &msan_flags; 94} 95 96int msan_inited = 0; 97bool msan_init_is_running; 98 99int msan_report_count = 0; 100 101void (*death_callback)(void); 102 103// Array of stack origins. 104// FIXME: make it resizable. 105static const uptr kNumStackOriginDescrs = 1024 * 1024; 106static const char *StackOriginDescr[kNumStackOriginDescrs]; 107static uptr StackOriginPC[kNumStackOriginDescrs]; 108static atomic_uint32_t NumStackOriginDescrs; 109 110static void ParseFlagsFromString(Flags *f, const char *str) { 111 CommonFlags *cf = common_flags(); 112 ParseCommonFlagsFromString(cf, str); 113 ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes", ""); 114 ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes", ""); 115 ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc", ""); 116 ParseFlag(str, &f->poison_in_free, "poison_in_free", ""); 117 ParseFlag(str, &f->exit_code, "exit_code", ""); 118 if (f->exit_code < 0 || f->exit_code > 127) { 119 Printf("Exit code not in [0, 128) range: %d\n", f->exit_code); 120 Die(); 121 } 122 ParseFlag(str, &f->origin_history_size, "origin_history_size", ""); 123 if (f->origin_history_size < 0 || 124 f->origin_history_size > Origin::kMaxDepth) { 125 Printf( 126 "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " 127 "range.\n", 128 f->origin_history_size, Origin::kMaxDepth); 129 Die(); 130 } 131 ParseFlag(str, &f->origin_history_per_stack_limit, 132 "origin_history_per_stack_limit", ""); 133 // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in 134 // StackDepotHandle::inc_use_count_unsafe. 135 if (f->origin_history_per_stack_limit < 0 || 136 f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { 137 Printf( 138 "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " 139 "%d] range.\n", 140 f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); 141 Die(); 142 } 143 144 ParseFlag(str, &f->report_umrs, "report_umrs", ""); 145 ParseFlag(str, &f->wrap_signals, "wrap_signals", ""); 146 ParseFlag(str, &f->print_stats, "print_stats", ""); 147 148 // keep_going is an old name for halt_on_error, 149 // and it has inverse meaning. 150 f->halt_on_error = !f->halt_on_error; 151 ParseFlag(str, &f->halt_on_error, "keep_going", ""); 152 f->halt_on_error = !f->halt_on_error; 153 ParseFlag(str, &f->halt_on_error, "halt_on_error", ""); 154} 155 156static void InitializeFlags(Flags *f, const char *options) { 157 CommonFlags *cf = common_flags(); 158 SetCommonFlagsDefaults(cf); 159 cf->external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); 160 cf->malloc_context_size = 20; 161 cf->handle_ioctl = true; 162 // FIXME: test and enable. 163 cf->check_printf = false; 164 165 internal_memset(f, 0, sizeof(*f)); 166 f->poison_heap_with_zeroes = false; 167 f->poison_stack_with_zeroes = false; 168 f->poison_in_malloc = true; 169 f->poison_in_free = true; 170 f->exit_code = 77; 171 f->origin_history_size = Origin::kMaxDepth; 172 f->origin_history_per_stack_limit = 20000; 173 f->report_umrs = true; 174 f->wrap_signals = true; 175 f->print_stats = false; 176 f->halt_on_error = !&__msan_keep_going; 177 178 // Override from user-specified string. 179 if (__msan_default_options) 180 ParseFlagsFromString(f, __msan_default_options()); 181 ParseFlagsFromString(f, options); 182} 183 184void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, 185 bool request_fast_unwind) { 186 MsanThread *t = GetCurrentThread(); 187 if (!t || !StackTrace::WillUseFastUnwind(request_fast_unwind)) { 188 // Block reports from our interceptors during _Unwind_Backtrace. 189 SymbolizerScope sym_scope; 190 return stack->Unwind(max_s, pc, bp, 0, 0, 0, request_fast_unwind); 191 } 192 stack->Unwind(max_s, pc, bp, 0, t->stack_top(), t->stack_bottom(), 193 request_fast_unwind); 194} 195 196void PrintWarning(uptr pc, uptr bp) { 197 PrintWarningWithOrigin(pc, bp, __msan_origin_tls); 198} 199 200bool OriginIsValid(u32 origin) { 201 return origin != 0 && origin != (u32)-1; 202} 203 204void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) { 205 if (msan_expect_umr) { 206 // Printf("Expected UMR\n"); 207 __msan_origin_tls = origin; 208 msan_expected_umr_found = 1; 209 return; 210 } 211 212 ++msan_report_count; 213 214 GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 215 216 u32 report_origin = 217 (__msan_get_track_origins() && OriginIsValid(origin)) ? origin : 0; 218 ReportUMR(&stack, report_origin); 219 220 if (__msan_get_track_origins() && !OriginIsValid(origin)) { 221 Printf( 222 " ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin " 223 "tracking.\n This could still be a bug in your code, too!\n", 224 origin); 225 } 226} 227 228void UnpoisonParam(uptr n) { 229 internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls)); 230} 231 232// Backup MSan runtime TLS state. 233// Implementation must be async-signal-safe. 234// Instances of this class may live on the signal handler stack, and data size 235// may be an issue. 236void ScopedThreadLocalStateBackup::Backup() { 237 va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls; 238} 239 240void ScopedThreadLocalStateBackup::Restore() { 241 // A lame implementation that only keeps essential state and resets the rest. 242 __msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls; 243 244 internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls)); 245 internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls)); 246 internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls)); 247 248 if (__msan_get_track_origins()) { 249 internal_memset(&__msan_retval_origin_tls, 0, 250 sizeof(__msan_retval_origin_tls)); 251 internal_memset(__msan_param_origin_tls, 0, 252 sizeof(__msan_param_origin_tls)); 253 } 254} 255 256void UnpoisonThreadLocalState() { 257} 258 259const char *GetStackOriginDescr(u32 id, uptr *pc) { 260 CHECK_LT(id, kNumStackOriginDescrs); 261 if (pc) *pc = StackOriginPC[id]; 262 return StackOriginDescr[id]; 263} 264 265u32 ChainOrigin(u32 id, StackTrace *stack) { 266 MsanThread *t = GetCurrentThread(); 267 if (t && t->InSignalHandler()) 268 return id; 269 270 Origin o(id); 271 int depth = o.depth(); 272 // 0 means unlimited depth. 273 if (flags()->origin_history_size > 0 && depth > 0) { 274 if (depth >= flags()->origin_history_size) { 275 return id; 276 } else { 277 ++depth; 278 } 279 } 280 281 StackDepotHandle h = StackDepotPut_WithHandle(stack->trace, stack->size); 282 if (!h.valid()) return id; 283 int use_count = h.use_count(); 284 if (use_count > flags()->origin_history_per_stack_limit) 285 return id; 286 287 u32 chained_id; 288 bool inserted = ChainedOriginDepotPut(h.id(), o.id(), &chained_id); 289 290 if (inserted) h.inc_use_count_unsafe(); 291 292 return Origin(chained_id, depth).raw_id(); 293} 294 295} // namespace __msan 296 297// Interface. 298 299using namespace __msan; 300 301#define MSAN_MAYBE_WARNING(type, size) \ 302 void __msan_maybe_warning_##size(type s, u32 o) { \ 303 GET_CALLER_PC_BP_SP; \ 304 (void) sp; \ 305 if (UNLIKELY(s)) { \ 306 PrintWarningWithOrigin(pc, bp, o); \ 307 if (__msan::flags()->halt_on_error) { \ 308 Printf("Exiting\n"); \ 309 Die(); \ 310 } \ 311 } \ 312 } 313 314MSAN_MAYBE_WARNING(u8, 1) 315MSAN_MAYBE_WARNING(u16, 2) 316MSAN_MAYBE_WARNING(u32, 4) 317MSAN_MAYBE_WARNING(u64, 8) 318 319#define MSAN_MAYBE_STORE_ORIGIN(type, size) \ 320 void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \ 321 if (UNLIKELY(s)) *(u32 *)MEM_TO_ORIGIN((uptr)p &~3UL) = o; \ 322 } 323 324MSAN_MAYBE_STORE_ORIGIN(u8, 1) 325MSAN_MAYBE_STORE_ORIGIN(u16, 2) 326MSAN_MAYBE_STORE_ORIGIN(u32, 4) 327MSAN_MAYBE_STORE_ORIGIN(u64, 8) 328 329void __msan_warning() { 330 GET_CALLER_PC_BP_SP; 331 (void)sp; 332 PrintWarning(pc, bp); 333 if (__msan::flags()->halt_on_error) { 334 if (__msan::flags()->print_stats) 335 ReportStats(); 336 Printf("Exiting\n"); 337 Die(); 338 } 339} 340 341void __msan_warning_noreturn() { 342 GET_CALLER_PC_BP_SP; 343 (void)sp; 344 PrintWarning(pc, bp); 345 if (__msan::flags()->print_stats) 346 ReportStats(); 347 Printf("Exiting\n"); 348 Die(); 349} 350 351void __msan_init() { 352 CHECK(!msan_init_is_running); 353 if (msan_inited) return; 354 msan_init_is_running = 1; 355 SanitizerToolName = "MemorySanitizer"; 356 357 SetDieCallback(MsanDie); 358 InitTlsSize(); 359 360 const char *msan_options = GetEnv("MSAN_OPTIONS"); 361 InitializeFlags(&msan_flags, msan_options); 362 if (common_flags()->help) PrintFlagDescriptions(); 363 __sanitizer_set_report_path(common_flags()->log_path); 364 365 InitializeInterceptors(); 366 InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 367 368 if (MSAN_REPLACE_OPERATORS_NEW_AND_DELETE) 369 ReplaceOperatorsNewAndDelete(); 370 if (StackSizeIsUnlimited()) { 371 VPrintf(1, "Unlimited stack, doing reexec\n"); 372 // A reasonably large stack size. It is bigger than the usual 8Mb, because, 373 // well, the program could have been run with unlimited stack for a reason. 374 SetStackSizeLimitInBytes(32 * 1024 * 1024); 375 ReExec(); 376 } 377 378 VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>"); 379 380 __msan_clear_on_return(); 381 if (__msan_get_track_origins()) 382 VPrintf(1, "msan_track_origins\n"); 383 if (!InitShadow(/* prot1 */ !msan_running_under_dr, /* prot2 */ true, 384 /* map_shadow */ true, __msan_get_track_origins())) { 385 Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); 386 Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 387 Printf("FATAL: Disabling ASLR is known to cause this error.\n"); 388 Printf("FATAL: If running under GDB, try " 389 "'set disable-randomization off'.\n"); 390 DumpProcessMap(); 391 Die(); 392 } 393 394 Symbolizer::Init(common_flags()->external_symbolizer_path); 395 Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); 396 397 MsanTSDInit(MsanTSDDtor); 398 399 MsanThread *main_thread = MsanThread::Create(0, 0); 400 SetCurrentThread(main_thread); 401 main_thread->ThreadStart(); 402 403 VPrintf(1, "MemorySanitizer init done\n"); 404 405 msan_init_is_running = 0; 406 msan_inited = 1; 407} 408 409void __msan_set_exit_code(int exit_code) { 410 flags()->exit_code = exit_code; 411} 412 413void __msan_set_keep_going(int keep_going) { 414 flags()->halt_on_error = !keep_going; 415} 416 417void __msan_set_expect_umr(int expect_umr) { 418 if (expect_umr) { 419 msan_expected_umr_found = 0; 420 } else if (!msan_expected_umr_found) { 421 GET_CALLER_PC_BP_SP; 422 (void)sp; 423 GET_FATAL_STACK_TRACE_PC_BP(pc, bp); 424 ReportExpectedUMRNotFound(&stack); 425 Die(); 426 } 427 msan_expect_umr = expect_umr; 428} 429 430void __msan_print_shadow(const void *x, uptr size) { 431 if (!MEM_IS_APP(x)) { 432 Printf("Not a valid application address: %p\n", x); 433 return; 434 } 435 436 DescribeMemoryRange(x, size); 437} 438 439void __msan_dump_shadow(const void *x, uptr size) { 440 if (!MEM_IS_APP(x)) { 441 Printf("Not a valid application address: %p\n", x); 442 return; 443 } 444 445 unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); 446 for (uptr i = 0; i < size; i++) { 447 Printf("%x%x ", s[i] >> 4, s[i] & 0xf); 448 } 449 Printf("\n"); 450} 451 452sptr __msan_test_shadow(const void *x, uptr size) { 453 if (!MEM_IS_APP(x)) return -1; 454 unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x); 455 for (uptr i = 0; i < size; ++i) 456 if (s[i]) 457 return i; 458 return -1; 459} 460 461void __msan_check_mem_is_initialized(const void *x, uptr size) { 462 if (!__msan::flags()->report_umrs) return; 463 sptr offset = __msan_test_shadow(x, size); 464 if (offset < 0) 465 return; 466 467 GET_CALLER_PC_BP_SP; 468 (void)sp; 469 ReportUMRInsideAddressRange(__func__, x, size, offset); 470 __msan::PrintWarningWithOrigin(pc, bp, 471 __msan_get_origin(((char *)x) + offset)); 472 if (__msan::flags()->halt_on_error) { 473 Printf("Exiting\n"); 474 Die(); 475 } 476} 477 478int __msan_set_poison_in_malloc(int do_poison) { 479 int old = flags()->poison_in_malloc; 480 flags()->poison_in_malloc = do_poison; 481 return old; 482} 483 484int __msan_has_dynamic_component() { 485 return msan_running_under_dr; 486} 487 488NOINLINE 489void __msan_clear_on_return() { 490 __msan_param_tls[0] = 0; 491} 492 493static void* get_tls_base() { 494 u64 p; 495 asm("mov %%fs:0, %0" 496 : "=r"(p) ::); 497 return (void*)p; 498} 499 500int __msan_get_retval_tls_offset() { 501 // volatile here is needed to avoid UB, because the compiler thinks that we 502 // are doing address arithmetics on unrelated pointers, and takes some 503 // shortcuts 504 volatile sptr retval_tls_p = (sptr)&__msan_retval_tls; 505 volatile sptr tls_base_p = (sptr)get_tls_base(); 506 return retval_tls_p - tls_base_p; 507} 508 509int __msan_get_param_tls_offset() { 510 // volatile here is needed to avoid UB, because the compiler thinks that we 511 // are doing address arithmetics on unrelated pointers, and takes some 512 // shortcuts 513 volatile sptr param_tls_p = (sptr)&__msan_param_tls; 514 volatile sptr tls_base_p = (sptr)get_tls_base(); 515 return param_tls_p - tls_base_p; 516} 517 518void __msan_partial_poison(const void* data, void* shadow, uptr size) { 519 internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size); 520} 521 522void __msan_load_unpoisoned(void *src, uptr size, void *dst) { 523 internal_memcpy(dst, src, size); 524 __msan_unpoison(dst, size); 525} 526 527void __msan_set_origin(const void *a, uptr size, u32 origin) { 528 // Origin mapping is 4 bytes per 4 bytes of application memory. 529 // Here we extend the range such that its left and right bounds are both 530 // 4 byte aligned. 531 if (!__msan_get_track_origins()) return; 532 uptr x = MEM_TO_ORIGIN((uptr)a); 533 uptr beg = x & ~3UL; // align down. 534 uptr end = (x + size + 3) & ~3UL; // align up. 535 u64 origin64 = ((u64)origin << 32) | origin; 536 // This is like memset, but the value is 32-bit. We unroll by 2 to write 537 // 64 bits at once. May want to unroll further to get 128-bit stores. 538 if (beg & 7ULL) { 539 *(u32*)beg = origin; 540 beg += 4; 541 } 542 for (uptr addr = beg; addr < (end & ~7UL); addr += 8) 543 *(u64*)addr = origin64; 544 if (end & 7ULL) 545 *(u32*)(end - 4) = origin; 546} 547 548// 'descr' is created at compile time and contains '----' in the beginning. 549// When we see descr for the first time we replace '----' with a uniq id 550// and set the origin to (id | (31-th bit)). 551void __msan_set_alloca_origin(void *a, uptr size, const char *descr) { 552 __msan_set_alloca_origin4(a, size, descr, 0); 553} 554 555void __msan_set_alloca_origin4(void *a, uptr size, const char *descr, uptr pc) { 556 static const u32 dash = '-'; 557 static const u32 first_timer = 558 dash + (dash << 8) + (dash << 16) + (dash << 24); 559 u32 *id_ptr = (u32*)descr; 560 bool print = false; // internal_strstr(descr + 4, "AllocaTOTest") != 0; 561 u32 id = *id_ptr; 562 if (id == first_timer) { 563 u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); 564 CHECK_LT(idx, kNumStackOriginDescrs); 565 StackOriginDescr[idx] = descr + 4; 566 StackOriginPC[idx] = pc; 567 ChainedOriginDepotPut(idx, Origin::kStackRoot, &id); 568 *id_ptr = id; 569 if (print) 570 Printf("First time: idx=%d id=%d %s %p \n", idx, id, descr + 4, pc); 571 } 572 if (print) 573 Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id); 574 __msan_set_origin(a, size, id); 575} 576 577u32 __msan_chain_origin(u32 id) { 578 GET_CALLER_PC_BP_SP; 579 (void)sp; 580 GET_STORE_STACK_TRACE_PC_BP(pc, bp); 581 return ChainOrigin(id, &stack); 582} 583 584u32 __msan_get_origin(const void *a) { 585 if (!__msan_get_track_origins()) return 0; 586 uptr x = (uptr)a; 587 uptr aligned = x & ~3ULL; 588 uptr origin_ptr = MEM_TO_ORIGIN(aligned); 589 return *(u32*)origin_ptr; 590} 591 592u32 __msan_get_umr_origin() { 593 return __msan_origin_tls; 594} 595 596u16 __sanitizer_unaligned_load16(const uu16 *p) { 597 __msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); 598 if (__msan_get_track_origins()) 599 __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 600 return *p; 601} 602u32 __sanitizer_unaligned_load32(const uu32 *p) { 603 __msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); 604 if (__msan_get_track_origins()) 605 __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 606 return *p; 607} 608u64 __sanitizer_unaligned_load64(const uu64 *p) { 609 __msan_retval_tls[0] = *(uu64 *)MEM_TO_SHADOW((uptr)p); 610 if (__msan_get_track_origins()) 611 __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); 612 return *p; 613} 614void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 615 u16 s = __msan_param_tls[1]; 616 *(uu16 *)MEM_TO_SHADOW((uptr)p) = s; 617 if (s && __msan_get_track_origins()) 618 if (uu32 o = __msan_param_origin_tls[2]) 619 SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 620 *p = x; 621} 622void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 623 u32 s = __msan_param_tls[1]; 624 *(uu32 *)MEM_TO_SHADOW((uptr)p) = s; 625 if (s && __msan_get_track_origins()) 626 if (uu32 o = __msan_param_origin_tls[2]) 627 SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 628 *p = x; 629} 630void __sanitizer_unaligned_store64(uu64 *p, u64 x) { 631 u64 s = __msan_param_tls[1]; 632 *(uu64 *)MEM_TO_SHADOW((uptr)p) = s; 633 if (s && __msan_get_track_origins()) 634 if (uu32 o = __msan_param_origin_tls[2]) 635 SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o); 636 *p = x; 637} 638 639void __msan_set_death_callback(void (*callback)(void)) { 640 death_callback = callback; 641} 642 643void *__msan_wrap_indirect_call(void *target) { 644 return IndirectExternCall(target); 645} 646 647void __msan_dr_is_initialized() { 648 msan_running_under_dr = true; 649} 650 651void __msan_set_indirect_call_wrapper(uptr wrapper) { 652 SetIndirectCallWrapper(wrapper); 653} 654 655#if !SANITIZER_SUPPORTS_WEAK_HOOKS 656extern "C" { 657SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 658const char* __msan_default_options() { return ""; } 659} // extern "C" 660#endif 661 662extern "C" { 663SANITIZER_INTERFACE_ATTRIBUTE 664void __sanitizer_print_stack_trace() { 665 GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 666 stack.Print(); 667} 668} // extern "C" 669