178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===-- msan.cc -----------------------------------------------------------===//
278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//
378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//                     The LLVM Compiler Infrastructure
478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//
578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// This file is distributed under the University of Illinois Open Source
678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// License. See LICENSE.TXT for details.
778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//
878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===----------------------------------------------------------------------===//
978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//
1078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// This file is a part of MemorySanitizer.
1178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//
1278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// MemorySanitizer runtime.
1378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===----------------------------------------------------------------------===//
1478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
1578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "msan.h"
1678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_atomic.h"
1778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_common.h"
1878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_flags.h"
1978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_libc.h"
2078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_procmaps.h"
2178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_stacktrace.h"
2278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_symbolizer.h"
2378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
2478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "interception/interception.h"
2578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
2678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// ACHTUNG! No system header includes in this file.
2778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
2878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovusing namespace __sanitizer;
2978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// Globals.
3178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic THREADLOCAL int msan_expect_umr = 0;
3278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic THREADLOCAL int msan_expected_umr_found = 0;
3378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic int msan_running_under_dr = 0;
3578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
3778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u64 __msan_param_tls[kMsanParamTlsSizeInWords];
3878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
4078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSizeInWords];
4178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
4278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
4378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSizeInWords];
4478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
4578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
4678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u32 __msan_retval_origin_tls;
4778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
4878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
4978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSizeInWords];
5078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
5178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
5278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u64 __msan_va_arg_overflow_size_tls;
5378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
5478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovSANITIZER_INTERFACE_ATTRIBUTE
5578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovTHREADLOCAL u32 __msan_origin_tls;
5678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
5778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic THREADLOCAL struct {
5878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr stack_top, stack_bottom;
5978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov} __msan_stack_bounds;
6078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
6170c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanystatic THREADLOCAL bool is_in_symbolizer;
620f92deb81207c80481ff0257fbaba640fe669633Reid Klecknerstatic THREADLOCAL bool is_in_loader;
6370c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany
64a879f10ee6aa04f6169d056ef2a9c39502fff290Evgeniy Stepanovextern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins;
65b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov
6678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint __msan_get_track_origins() {
67b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  return &__msan_track_origins ? __msan_track_origins : 0;
6878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
6978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
70bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanovextern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going;
71bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov
7278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovnamespace __msan {
7378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
7478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic bool IsRunningUnderDr() {
7578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  bool result = false;
769ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander Potapenko  MemoryMappingLayout proc_maps(/*cache_enabled*/true);
7778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  const sptr kBufSize = 4095;
7878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
7978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  while (proc_maps.Next(/* start */0, /* end */0, /* file_offset */0,
8045717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                        filename, kBufSize, /* protection */0)) {
8178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (internal_strstr(filename, "libdynamorio") != 0) {
8278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      result = true;
8378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      break;
8478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    }
8578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
8678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  UnmapOrDie(filename, kBufSize);
8778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return result;
8878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
8978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
9070c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanyvoid EnterSymbolizer() { is_in_symbolizer = true; }
9170c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanyvoid ExitSymbolizer()  { is_in_symbolizer = false; }
9270c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanybool IsInSymbolizer() { return is_in_symbolizer; }
9370c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany
940f92deb81207c80481ff0257fbaba640fe669633Reid Klecknervoid EnterLoader() { is_in_loader = true; }
950f92deb81207c80481ff0257fbaba640fe669633Reid Klecknervoid ExitLoader()  { is_in_loader = false; }
960f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner
970f92deb81207c80481ff0257fbaba640fe669633Reid Klecknerextern "C" {
980f92deb81207c80481ff0257fbaba640fe669633Reid KlecknerSANITIZER_INTERFACE_ATTRIBUTE
990f92deb81207c80481ff0257fbaba640fe669633Reid Klecknerbool __msan_is_in_loader() { return is_in_loader; }
1000f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner}
1010f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner
10278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic Flags msan_flags;
10378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
10478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovFlags *flags() {
10578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return &msan_flags;
10678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
10778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
10878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint msan_inited = 0;
10978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovbool msan_init_is_running;
11078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
11199bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanovint msan_report_count = 0;
11299bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov
11378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// Array of stack origins.
11478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// FIXME: make it resizable.
11578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kNumStackOriginDescrs = 1024 * 1024;
11678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const char *StackOriginDescr[kNumStackOriginDescrs];
11778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic atomic_uint32_t NumStackOriginDescrs;
11878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
11978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic void ParseFlagsFromString(Flags *f, const char *str) {
1200b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  ParseCommonFlagsFromString(str);
12178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes");
12278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes");
12378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc");
12478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->exit_code, "exit_code");
12578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (f->exit_code < 0 || f->exit_code > 127) {
12678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("Exit code not in [0, 128) range: %d\n", f->exit_code);
12778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    f->exit_code = 1;
12878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Die();
12978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
13078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->report_umrs, "report_umrs");
13178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlag(str, &f->verbosity, "verbosity");
132a213ab66e1c743ec7a52af4a49ec6c126cc245aeEvgeniy Stepanov  ParseFlag(str, &f->wrap_signals, "wrap_signals");
133bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov  ParseFlag(str, &f->keep_going, "keep_going");
13478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
13578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
13678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic void InitializeFlags(Flags *f, const char *options) {
1370b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  CommonFlags *cf = common_flags();
1380b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  cf->external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH");
1390b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  cf->strip_path_prefix = "";
1400b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  cf->fast_unwind_on_fatal = false;
1410b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  cf->fast_unwind_on_malloc = true;
1420b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  cf->malloc_context_size = 20;
143745dd0d296e7bef712df4b5c7f86c72534953738Evgeniy Stepanov  cf->handle_ioctl = true;
144b6246066a271e3b01732d1b4381ef745152747d2Evgeniy Stepanov  cf->log_path = 0;
14578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
1460b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  internal_memset(f, 0, sizeof(*f));
14778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->poison_heap_with_zeroes = false;
14878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->poison_stack_with_zeroes = false;
14978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->poison_in_malloc = true;
15078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->exit_code = 77;
15178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->report_umrs = true;
15278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  f->verbosity = 0;
153a213ab66e1c743ec7a52af4a49ec6c126cc245aeEvgeniy Stepanov  f->wrap_signals = true;
154bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov  f->keep_going = !!&__msan_keep_going;
15578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
15670c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany  // Override from user-specified string.
15770c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany  if (__msan_default_options)
15870c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany    ParseFlagsFromString(f, __msan_default_options());
15978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  ParseFlagsFromString(f, options);
16078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
16178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
16278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic void GetCurrentStackBounds(uptr *stack_top, uptr *stack_bottom) {
16378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (__msan_stack_bounds.stack_top == 0) {
16478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // Break recursion (GetStackTrace -> GetThreadStackTopAndBottom ->
16578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // realloc -> GetStackTrace).
16678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    __msan_stack_bounds.stack_top = __msan_stack_bounds.stack_bottom = 1;
16778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    GetThreadStackTopAndBottom(/* at_initialization */false,
16878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov                               &__msan_stack_bounds.stack_top,
16978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov                               &__msan_stack_bounds.stack_bottom);
17078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
17178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  *stack_top = __msan_stack_bounds.stack_top;
17278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  *stack_bottom = __msan_stack_bounds.stack_bottom;
17378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
17478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
175efbc43528892b0a30039f68633e0b4ed3bbd2daeEvgeniy Stepanovvoid GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
176efbc43528892b0a30039f68633e0b4ed3bbd2daeEvgeniy Stepanov                   bool fast) {
17793c26022f362c9e0a6acbe3bf3c7c395e19e0835Reid Kleckner  if (!fast) {
17893c26022f362c9e0a6acbe3bf3c7c395e19e0835Reid Kleckner    // Block reports from our interceptors during _Unwind_Backtrace.
17993c26022f362c9e0a6acbe3bf3c7c395e19e0835Reid Kleckner    SymbolizerScope sym_scope;
180efbc43528892b0a30039f68633e0b4ed3bbd2daeEvgeniy Stepanov    return stack->SlowUnwindStack(pc, max_s);
18193c26022f362c9e0a6acbe3bf3c7c395e19e0835Reid Kleckner  }
182efbc43528892b0a30039f68633e0b4ed3bbd2daeEvgeniy Stepanov
18378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr stack_top, stack_bottom;
18478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  GetCurrentStackBounds(&stack_top, &stack_bottom);
18578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  stack->size = 0;
18678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  stack->trace[0] = pc;
18778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  stack->max_size = max_s;
18878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  stack->FastUnwindStack(pc, bp, stack_top, stack_bottom);
18978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
19078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
19178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid PrintWarning(uptr pc, uptr bp) {
19278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  PrintWarningWithOrigin(pc, bp, __msan_origin_tls);
19378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
19478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
195db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanovbool OriginIsValid(u32 origin) {
196db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov  return origin != 0 && origin != (u32)-1;
197db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov}
198db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov
19978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) {
20078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (msan_expect_umr) {
20178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // Printf("Expected UMR\n");
20278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    __msan_origin_tls = origin;
20378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    msan_expected_umr_found = 1;
20478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    return;
20578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
20678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
20799bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov  ++msan_report_count;
20899bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov
209db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov  StackTrace stack;
2100b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  GetStackTrace(&stack, kStackTraceMax, pc, bp,
2110b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev                common_flags()->fast_unwind_on_fatal);
212db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov
213db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov  u32 report_origin =
214b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov    (__msan_get_track_origins() && OriginIsValid(origin)) ? origin : 0;
215db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov  ReportUMR(&stack, report_origin);
216db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov
217b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (__msan_get_track_origins() && !OriginIsValid(origin)) {
218db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov    Printf("  ORIGIN: invalid (%x). Might be a bug in MemorySanitizer, "
219db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov           "please report to MemorySanitizer developers.\n",
220db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov           origin);
22178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
22278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
22378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
224c2918bf11fc65b1f9551eee03719e9bdf02eedd5Alexey Samsonovvoid UnpoisonParam(uptr n) {
225c2918bf11fc65b1f9551eee03719e9bdf02eedd5Alexey Samsonov  internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls));
226c2918bf11fc65b1f9551eee03719e9bdf02eedd5Alexey Samsonov}
227c2918bf11fc65b1f9551eee03719e9bdf02eedd5Alexey Samsonov
22878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}  // namespace __msan
22978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
23078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// Interface.
23178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
23278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovusing namespace __msan;
23378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
23478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_warning() {
23578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  GET_CALLER_PC_BP_SP;
23678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  (void)sp;
23778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  PrintWarning(pc, bp);
238bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov  if (!__msan::flags()->keep_going) {
239bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov    Printf("Exiting\n");
240bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov    Die();
241bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov  }
24278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
24378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
24478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_warning_noreturn() {
24578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  GET_CALLER_PC_BP_SP;
24678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  (void)sp;
24778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  PrintWarning(pc, bp);
24878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  Printf("Exiting\n");
24978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  Die();
25078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
25178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
25278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_init() {
25378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (msan_inited) return;
25478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  msan_init_is_running = 1;
255859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany  SanitizerToolName = "MemorySanitizer";
25678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
25799bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov  InstallAtExitHandler();
25878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  SetDieCallback(MsanDie);
25910fd3227546d17c7411241a45ebc143b2031c78dEvgeniy Stepanov  InitTlsSize();
26078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  InitializeInterceptors();
26178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
262a897400cec0284763da5a6db4670fa0a64bbfcd9Evgeniy Stepanov  if (MSAN_REPLACE_OPERATORS_NEW_AND_DELETE)
263a897400cec0284763da5a6db4670fa0a64bbfcd9Evgeniy Stepanov    ReplaceOperatorsNewAndDelete();
264f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  const char *msan_options = GetEnv("MSAN_OPTIONS");
265f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov  InitializeFlags(&msan_flags, msan_options);
266b6246066a271e3b01732d1b4381ef745152747d2Evgeniy Stepanov  __sanitizer_set_report_path(common_flags()->log_path);
26778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (StackSizeIsUnlimited()) {
26878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (flags()->verbosity)
26978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      Printf("Unlimited stack, doing reexec\n");
27078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // A reasonably large stack size. It is bigger than the usual 8Mb, because,
27178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // well, the program could have been run with unlimited stack for a reason.
27278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    SetStackSizeLimitInBytes(32 * 1024 * 1024);
27378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    ReExec();
27478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
275f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov
27678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (flags()->verbosity)
27778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>");
278f35eae83757946decb312deab3f0fe155fe5d580Evgeniy Stepanov
27978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  msan_running_under_dr = IsRunningUnderDr();
28078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  __msan_clear_on_return();
281b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (__msan_get_track_origins() && flags()->verbosity > 0)
28278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("msan_track_origins\n");
283b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (!InitShadow(/* prot1 */ false, /* prot2 */ true, /* map_shadow */ true,
284b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov                  __msan_get_track_origins())) {
28578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    // FIXME: prot1 = false is only required when running under DR.
2864c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov    Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n");
28778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
2884c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov    Printf("FATAL: Disabling ASLR is known to cause this error.\n");
2894b48f4563ca25d8915155acc5837e195cf0e5c57Kostya Serebryany    Printf("FATAL: If running under GDB, try "
2904b48f4563ca25d8915155acc5837e195cf0e5c57Kostya Serebryany           "'set disable-randomization off'.\n");
29178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    DumpProcessMap();
29278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Die();
29378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
29478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
2950b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev  const char *external_symbolizer = common_flags()->external_symbolizer_path;
29678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (external_symbolizer && external_symbolizer[0]) {
29778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    CHECK(InitializeExternalSymbolizer(external_symbolizer));
29878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
29978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
30078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  GetThreadStackTopAndBottom(/* at_initialization */true,
30178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov                             &__msan_stack_bounds.stack_top,
30278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov                             &__msan_stack_bounds.stack_bottom);
30378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (flags()->verbosity)
30478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("MemorySanitizer init done\n");
30578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  msan_init_is_running = 0;
30678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  msan_inited = 1;
30778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
30878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
30978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_set_exit_code(int exit_code) {
31078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  flags()->exit_code = exit_code;
31178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
31278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
313bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanovvoid __msan_set_keep_going(int keep_going) {
314bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov  flags()->keep_going = keep_going;
315bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov}
316bb881c736eff073a84cc640d431ae1e58a5e07d4Evgeniy Stepanov
31778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_set_expect_umr(int expect_umr) {
31878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (expect_umr) {
31978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    msan_expected_umr_found = 0;
32078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  } else if (!msan_expected_umr_found) {
32178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    GET_CALLER_PC_BP_SP;
32278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    (void)sp;
323db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov    StackTrace stack;
32458b52b5efb7641b27c1728be0946889f335d83e1Evgeniy Stepanov    GetStackTrace(&stack, kStackTraceMax, pc, bp,
3250b4bf4d72be10ba114c9b1f73aca45acd0e44ddcSergey Matveev                  common_flags()->fast_unwind_on_fatal);
326db010dae23962ab6089ad1e97af176b7215cb35cEvgeniy Stepanov    ReportExpectedUMRNotFound(&stack);
32778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Die();
32878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
32978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  msan_expect_umr = expect_umr;
33078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
33178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
33278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_print_shadow(const void *x, uptr size) {
33378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x);
33478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  u32 *o = (u32*)MEM_TO_ORIGIN(x);
33578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  for (uptr i = 0; i < size; i++) {
33678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("%x%x ", s[i] >> 4, s[i] & 0xf);
33778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
33878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  Printf("\n");
339b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (__msan_get_track_origins()) {
34078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    for (uptr i = 0; i < size / 4; i++) {
34178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      Printf(" o: %x ", o[i]);
34278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    }
34378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("\n");
34478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
34578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
34678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
34778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_print_param_shadow() {
34878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  for (int i = 0; i < 16; i++) {
34978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("#%d:%zx ", i, __msan_param_tls[i]);
35078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
35178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  Printf("\n");
35278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
35378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
35478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovsptr __msan_test_shadow(const void *x, uptr size) {
35578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  unsigned char *s = (unsigned char*)MEM_TO_SHADOW((uptr)x);
35678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  for (uptr i = 0; i < size; ++i)
35778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (s[i])
35878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      return i;
35978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return -1;
36078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
36178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
36278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint __msan_set_poison_in_malloc(int do_poison) {
36378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  int old = flags()->poison_in_malloc;
36478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  flags()->poison_in_malloc = do_poison;
36578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return old;
36678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
36778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
36878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint  __msan_has_dynamic_component() {
36978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return msan_running_under_dr;
37078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
37178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
37278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy StepanovNOINLINE
37378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_clear_on_return() {
37478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  __msan_param_tls[0] = 0;
37578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
37678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
37778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic void* get_tls_base() {
37878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  u64 p;
37978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  asm("mov %%fs:0, %0"
38078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      : "=r"(p) ::);
38178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return (void*)p;
38278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
38378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
38478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint __msan_get_retval_tls_offset() {
38578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // volatile here is needed to avoid UB, because the compiler thinks that we
38678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // are doing address arithmetics on unrelated pointers, and takes some
38778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // shortcuts
38878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  volatile sptr retval_tls_p = (sptr)&__msan_retval_tls;
38978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  volatile sptr tls_base_p = (sptr)get_tls_base();
39078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return retval_tls_p - tls_base_p;
39178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
39278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
39378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovint __msan_get_param_tls_offset() {
39478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // volatile here is needed to avoid UB, because the compiler thinks that we
39578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // are doing address arithmetics on unrelated pointers, and takes some
39678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // shortcuts
39778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  volatile sptr param_tls_p = (sptr)&__msan_param_tls;
39878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  volatile sptr tls_base_p = (sptr)get_tls_base();
39978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return param_tls_p - tls_base_p;
40078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
40178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
40211347bf5f008b5970f699241617381d95526d73dAlexey Samsonovvoid __msan_partial_poison(const void* data, void* shadow, uptr size) {
40378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size);
40478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
40578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
40678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_load_unpoisoned(void *src, uptr size, void *dst) {
40778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  internal_memcpy(dst, src, size);
40878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  __msan_unpoison(dst, size);
40978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
41078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
41111347bf5f008b5970f699241617381d95526d73dAlexey Samsonovvoid __msan_set_origin(const void *a, uptr size, u32 origin) {
41278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // Origin mapping is 4 bytes per 4 bytes of application memory.
41378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // Here we extend the range such that its left and right bounds are both
41478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // 4 byte aligned.
415b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (!__msan_get_track_origins()) return;
41678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr x = MEM_TO_ORIGIN((uptr)a);
41778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr beg = x & ~3UL;  // align down.
41878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr end = (x + size + 3) & ~3UL;  // align up.
41978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  u64 origin64 = ((u64)origin << 32) | origin;
42078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // This is like memset, but the value is 32-bit. We unroll by 2 two write
42178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  // 64-bits at once. May want to unroll further to get 128-bit stores.
42278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (beg & 7ULL) {
42378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    *(u32*)beg = origin;
42478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    beg += 4;
42578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
42678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  for (uptr addr = beg; addr < (end & ~7UL); addr += 8)
42778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    *(u64*)addr = origin64;
42878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (end & 7ULL)
42978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    *(u32*)(end - 4) = origin;
43078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
43178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
43278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 'descr' is created at compile time and contains '----' in the beginning.
43378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// When we see descr for the first time we replace '----' with a uniq id
43478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// and set the origin to (id | (31-th bit)).
43578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid __msan_set_alloca_origin(void *a, uptr size, const char *descr) {
43678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  static const u32 dash = '-';
43778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  static const u32 first_timer =
43878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      dash + (dash << 8) + (dash << 16) + (dash << 24);
43978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  u32 *id_ptr = (u32*)descr;
44078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  bool print = false;  // internal_strstr(descr + 4, "AllocaTOTest") != 0;
44178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  u32 id = *id_ptr;
44278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (id == first_timer) {
44378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    id = atomic_fetch_add(&NumStackOriginDescrs,
44478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov                          1, memory_order_relaxed);
44578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    *id_ptr = id;
44678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    CHECK_LT(id, kNumStackOriginDescrs);
44778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    StackOriginDescr[id] = descr + 4;
44878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (print)
44978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov      Printf("First time: id=%d %s \n", id, descr + 4);
45078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
45178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  id |= 1U << 31;
45278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (print)
45378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id);
45478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  __msan_set_origin(a, size, id);
45578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
45678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
45778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovconst char *__msan_get_origin_descr_if_stack(u32 id) {
45878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if ((id >> 31) == 0) return 0;
45978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  id &= (1U << 31) - 1;
46078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  CHECK_LT(id, kNumStackOriginDescrs);
46178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return StackOriginDescr[id];
46278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
46378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
46478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
46511347bf5f008b5970f699241617381d95526d73dAlexey Samsonovu32 __msan_get_origin(const void *a) {
466b36779d6e9c55e97b2258fe30e8e02c416b14ddaEvgeniy Stepanov  if (!__msan_get_track_origins()) return 0;
46778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr x = (uptr)a;
46878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr aligned = x & ~3ULL;
46978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  uptr origin_ptr = MEM_TO_ORIGIN(aligned);
47078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return *(u32*)origin_ptr;
47178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
47278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
47312c46937db2a5ab9237ce314c3f3a83636e8a575Evgeniy Stepanovu32 __msan_get_umr_origin() {
47478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return __msan_origin_tls;
47578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
47670c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany
4772e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovu16 __sanitizer_unaligned_load16(const uu16 *p) {
4782e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  __msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p);
4792e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  return *p;
480f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
4812e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovu32 __sanitizer_unaligned_load32(const uu32 *p) {
4822e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  __msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p);
4832e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  return *p;
484f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
4852e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovu64 __sanitizer_unaligned_load64(const uu64 *p) {
4862e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  __msan_retval_tls[0] = *(uu64 *)MEM_TO_SHADOW((uptr)p);
4872e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  return *p;
488f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
4892e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovvoid __sanitizer_unaligned_store16(uu16 *p, u16 x) {
4902e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *(uu16 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1];
4912e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *p = x;
492f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
4932e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovvoid __sanitizer_unaligned_store32(uu32 *p, u32 x) {
4942e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *(uu32 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1];
4952e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *p = x;
496f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
4972e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanovvoid __sanitizer_unaligned_store64(uu64 *p, u64 x) {
4982e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *(uu64 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1];
4992e9ffcbc2184f308881fc04ce0799c557b7e5b0fEvgeniy Stepanov  *p = x;
500f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov}
501f43f6026dc9374e657fb6300840b18ead6347b74Evgeniy Stepanov
50270c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany#if !SANITIZER_SUPPORTS_WEAK_HOOKS
50370c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanyextern "C" {
50470c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya SerebryanySANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
50570c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryanyconst char* __msan_default_options() { return ""; }
50670c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany}  // extern "C"
50770c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany#endif
50870c6e3fb6dfddb9c4d26ac133beb5f53b71e47d9Kostya Serebryany
509