178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===-- msan_linux.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// Linux-specific code.
1378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===----------------------------------------------------------------------===//
1478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h"
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX
1778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
1878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "msan.h"
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "msan_thread.h"
2078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
210f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner#include <elf.h>
220f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner#include <link.h>
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <pthread.h>
2478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <stdio.h>
2578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <stdlib.h>
2678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <signal.h>
2778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <unistd.h>
2878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <unwind.h>
2978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <execinfo.h>
3078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <sys/time.h>
3178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <sys/resource.h>
3278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_common.h"
3478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_procmaps.h"
3578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovnamespace __msan {
3778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
3878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kMemBeg     = 0x600000000000;
3978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kMemEnd     = 0x7fffffffffff;
4078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kShadowBeg  = MEM_TO_SHADOW(kMemBeg);
4178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kShadowEnd  = MEM_TO_SHADOW(kMemEnd);
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic const uptr kBad1Beg    = 0;
4378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad1End    = kShadowBeg - 1;
4478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad2Beg    = kShadowEnd + 1;
4578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad2End    = kMemBeg - 1;
4678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kOriginsBeg = kBad2Beg;
4778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kOriginsEnd = kBad2End;
4878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
4978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovbool InitShadow(bool prot1, bool prot2, bool map_shadow, bool init_origins) {
5062355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov  if ((uptr) & InitShadow < kMemBeg) {
5162355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov    Printf("FATAL: Code below application range: %p < %p. Non-PIE build?\n",
5262355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov           &InitShadow, (void *)kMemBeg);
5362355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov    return false;
5462355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov  }
5562355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "__msan_init %p\n", &__msan_init);
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "Memory   : %p %p\n", kMemBeg, kMemEnd);
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "Bad2     : %p %p\n", kBad2Beg, kBad2End);
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "Origins  : %p %p\n", kOriginsBeg, kOriginsEnd);
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "Shadow   : %p %p\n", kShadowBeg, kShadowEnd);
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "Bad1     : %p %p\n", kBad1Beg, kBad1End);
6278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
634c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov  if (!MemoryRangeIsAvailable(kShadowBeg,
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                              init_origins ? kOriginsEnd : kShadowEnd) ||
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (prot1 && !MemoryRangeIsAvailable(kBad1Beg, kBad1End)) ||
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      (prot2 && !MemoryRangeIsAvailable(kBad2Beg, kBad2End))) {
674c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov    Printf("FATAL: Shadow memory range is not available.\n");
684c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov    return false;
694c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov  }
704c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov
7178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (prot1 && !Mprotect(kBad1Beg, kBad1End - kBad1Beg))
7278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    return false;
7378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (prot2 && !Mprotect(kBad2Beg, kBad2End - kBad2Beg))
7478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    return false;
7578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (map_shadow) {
7678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg);
7778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (shadow != (void*)kShadowBeg) return false;
7878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
7978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  if (init_origins) {
8078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsEnd - kOriginsBeg);
8178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov    if (origins != (void*)kOriginsBeg) return false;
8278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  }
8378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  return true;
8478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
8578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
8678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid MsanDie() {
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (death_callback)
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    death_callback();
8978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov  _exit(flags()->exit_code);
9078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov}
9199bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov
9299bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanovstatic void MsanAtExit(void) {
935d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
945d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    ReportStats();
9599bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov  if (msan_report_count > 0) {
9699bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov    ReportAtExitStatistics();
975d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    if (flags()->exit_code) _exit(flags()->exit_code);
9899bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov  }
9999bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov}
10099bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov
10199bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanovvoid InstallAtExitHandler() {
10299bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov  atexit(MsanAtExit);
10399bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov}
1040f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// ---------------------- TSD ---------------- {{{1
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic pthread_key_t tsd_key;
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic bool tsd_key_inited = false;
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDInit(void (*destructor)(void *tsd)) {
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(!tsd_key_inited);
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  tsd_key_inited = true;
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *MsanTSDGet() {
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(tsd_key_inited);
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return pthread_getspecific(tsd_key);
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDSet(void *tsd) {
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK(tsd_key_inited);
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_setspecific(tsd_key, tsd);
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDDtor(void *tsd) {
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  MsanThread *t = (MsanThread*)tsd;
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (t->destructor_iterations_ > 1) {
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    t->destructor_iterations_--;
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  MsanThread::TSDDtor(tsd);
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
135ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov}  // namespace __msan
13678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov
13778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#endif  // __linux__
138