Home | History | Annotate | Download | only in msan
      1 //===-- msan_linux.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 // Linux-specific code.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "sanitizer_common/sanitizer_platform.h"
     16 #if SANITIZER_LINUX
     17 
     18 #include "msan.h"
     19 #include "msan_thread.h"
     20 
     21 #include <elf.h>
     22 #include <link.h>
     23 #include <pthread.h>
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <signal.h>
     27 #include <unistd.h>
     28 #include <unwind.h>
     29 #include <execinfo.h>
     30 #include <sys/time.h>
     31 #include <sys/resource.h>
     32 
     33 #include "sanitizer_common/sanitizer_common.h"
     34 #include "sanitizer_common/sanitizer_procmaps.h"
     35 
     36 namespace __msan {
     37 
     38 static const uptr kMemBeg     = 0x600000000000;
     39 static const uptr kMemEnd     = 0x7fffffffffff;
     40 static const uptr kShadowBeg  = MEM_TO_SHADOW(kMemBeg);
     41 static const uptr kShadowEnd  = MEM_TO_SHADOW(kMemEnd);
     42 static const uptr kBad1Beg    = 0;
     43 static const uptr kBad1End    = kShadowBeg - 1;
     44 static const uptr kBad2Beg    = kShadowEnd + 1;
     45 static const uptr kBad2End    = kMemBeg - 1;
     46 static const uptr kOriginsBeg = kBad2Beg;
     47 static const uptr kOriginsEnd = kBad2End;
     48 
     49 bool InitShadow(bool prot1, bool prot2, bool map_shadow, bool init_origins) {
     50   if ((uptr) & InitShadow < kMemBeg) {
     51     Printf("FATAL: Code below application range: %p < %p. Non-PIE build?\n",
     52            &InitShadow, (void *)kMemBeg);
     53     return false;
     54   }
     55 
     56   VPrintf(1, "__msan_init %p\n", &__msan_init);
     57   VPrintf(1, "Memory   : %p %p\n", kMemBeg, kMemEnd);
     58   VPrintf(1, "Bad2     : %p %p\n", kBad2Beg, kBad2End);
     59   VPrintf(1, "Origins  : %p %p\n", kOriginsBeg, kOriginsEnd);
     60   VPrintf(1, "Shadow   : %p %p\n", kShadowBeg, kShadowEnd);
     61   VPrintf(1, "Bad1     : %p %p\n", kBad1Beg, kBad1End);
     62 
     63   if (!MemoryRangeIsAvailable(kShadowBeg,
     64                               init_origins ? kOriginsEnd : kShadowEnd) ||
     65       (prot1 && !MemoryRangeIsAvailable(kBad1Beg, kBad1End)) ||
     66       (prot2 && !MemoryRangeIsAvailable(kBad2Beg, kBad2End))) {
     67     Printf("FATAL: Shadow memory range is not available.\n");
     68     return false;
     69   }
     70 
     71   if (prot1 && !Mprotect(kBad1Beg, kBad1End - kBad1Beg))
     72     return false;
     73   if (prot2 && !Mprotect(kBad2Beg, kBad2End - kBad2Beg))
     74     return false;
     75   if (map_shadow) {
     76     void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg);
     77     if (shadow != (void*)kShadowBeg) return false;
     78   }
     79   if (init_origins) {
     80     void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsEnd - kOriginsBeg);
     81     if (origins != (void*)kOriginsBeg) return false;
     82   }
     83   return true;
     84 }
     85 
     86 void MsanDie() {
     87   if (death_callback)
     88     death_callback();
     89   _exit(flags()->exit_code);
     90 }
     91 
     92 static void MsanAtExit(void) {
     93   if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
     94     ReportStats();
     95   if (msan_report_count > 0) {
     96     ReportAtExitStatistics();
     97     if (flags()->exit_code) _exit(flags()->exit_code);
     98   }
     99 }
    100 
    101 void InstallAtExitHandler() {
    102   atexit(MsanAtExit);
    103 }
    104 
    105 // ---------------------- TSD ---------------- {{{1
    106 
    107 static pthread_key_t tsd_key;
    108 static bool tsd_key_inited = false;
    109 void MsanTSDInit(void (*destructor)(void *tsd)) {
    110   CHECK(!tsd_key_inited);
    111   tsd_key_inited = true;
    112   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
    113 }
    114 
    115 void *MsanTSDGet() {
    116   CHECK(tsd_key_inited);
    117   return pthread_getspecific(tsd_key);
    118 }
    119 
    120 void MsanTSDSet(void *tsd) {
    121   CHECK(tsd_key_inited);
    122   pthread_setspecific(tsd_key, tsd);
    123 }
    124 
    125 void MsanTSDDtor(void *tsd) {
    126   MsanThread *t = (MsanThread*)tsd;
    127   if (t->destructor_iterations_ > 1) {
    128     t->destructor_iterations_--;
    129     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
    130     return;
    131   }
    132   MsanThread::TSDDtor(tsd);
    133 }
    134 
    135 }  // namespace __msan
    136 
    137 #endif  // __linux__
    138