Home | History | Annotate | Download | only in rtl
      1 //===-- tsan_platform_posix.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 ThreadSanitizer (TSan), a race detector.
     11 //
     12 // POSIX-specific code.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "sanitizer_common/sanitizer_platform.h"
     16 #if SANITIZER_POSIX
     17 
     18 #include "sanitizer_common/sanitizer_common.h"
     19 #include "sanitizer_common/sanitizer_libc.h"
     20 #include "sanitizer_common/sanitizer_procmaps.h"
     21 #include "tsan_platform.h"
     22 #include "tsan_rtl.h"
     23 
     24 namespace __tsan {
     25 
     26 #ifndef SANITIZER_GO
     27 void InitializeShadowMemory() {
     28   // Map memory shadow.
     29   uptr shadow =
     30       (uptr)MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(),
     31                                "shadow");
     32   if (shadow != ShadowBeg()) {
     33     Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
     34     Printf("FATAL: Make sure to compile with -fPIE and "
     35                "to link with -pie (%p, %p).\n", shadow, ShadowBeg());
     36     Die();
     37   }
     38   // This memory range is used for thread stacks and large user mmaps.
     39   // Frequently a thread uses only a small part of stack and similarly
     40   // a program uses a small part of large mmap. On some programs
     41   // we see 20% memory usage reduction without huge pages for this range.
     42   // FIXME: don't use constants here.
     43 #if defined(__x86_64__)
     44   const uptr kMadviseRangeBeg  = 0x7f0000000000ull;
     45   const uptr kMadviseRangeSize = 0x010000000000ull;
     46 #elif defined(__mips64)
     47   const uptr kMadviseRangeBeg  = 0xff00000000ull;
     48   const uptr kMadviseRangeSize = 0x0100000000ull;
     49 #elif defined(__aarch64__)
     50   uptr kMadviseRangeBeg = 0;
     51   uptr kMadviseRangeSize = 0;
     52   if (vmaSize == 39) {
     53     kMadviseRangeBeg  = 0x7d00000000ull;
     54     kMadviseRangeSize = 0x0300000000ull;
     55   } else if (vmaSize == 42) {
     56     kMadviseRangeBeg  = 0x3f000000000ull;
     57     kMadviseRangeSize = 0x01000000000ull;
     58   } else {
     59     DCHECK(0);
     60   }
     61 #elif defined(__powerpc64__)
     62   uptr kMadviseRangeBeg = 0;
     63   uptr kMadviseRangeSize = 0;
     64   if (vmaSize == 44) {
     65     kMadviseRangeBeg  = 0x0f60000000ull;
     66     kMadviseRangeSize = 0x0010000000ull;
     67   } else if (vmaSize == 46) {
     68     kMadviseRangeBeg  = 0x3f0000000000ull;
     69     kMadviseRangeSize = 0x010000000000ull;
     70   } else {
     71     DCHECK(0);
     72   }
     73 #endif
     74   NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg),
     75                       kMadviseRangeSize * kShadowMultiplier);
     76   // Meta shadow is compressing and we don't flush it,
     77   // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory.
     78   // On one program it reduces memory consumption from 5GB to 2.5GB.
     79   NoHugePagesInRegion(MetaShadowBeg(), MetaShadowEnd() - MetaShadowBeg());
     80   if (common_flags()->use_madv_dontdump)
     81     DontDumpShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg());
     82   DPrintf("memory shadow: %zx-%zx (%zuGB)\n",
     83       ShadowBeg(), ShadowEnd(),
     84       (ShadowEnd() - ShadowBeg()) >> 30);
     85 
     86   // Map meta shadow.
     87   uptr meta_size = MetaShadowEnd() - MetaShadowBeg();
     88   uptr meta =
     89       (uptr)MmapFixedNoReserve(MetaShadowBeg(), meta_size, "meta shadow");
     90   if (meta != MetaShadowBeg()) {
     91     Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
     92     Printf("FATAL: Make sure to compile with -fPIE and "
     93                "to link with -pie (%p, %p).\n", meta, MetaShadowBeg());
     94     Die();
     95   }
     96   if (common_flags()->use_madv_dontdump)
     97     DontDumpShadowMemory(meta, meta_size);
     98   DPrintf("meta shadow: %zx-%zx (%zuGB)\n",
     99       meta, meta + meta_size, meta_size >> 30);
    100 
    101   InitializeShadowMemoryPlatform();
    102 }
    103 
    104 static void ProtectRange(uptr beg, uptr end) {
    105   CHECK_LE(beg, end);
    106   if (beg == end)
    107     return;
    108   if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) {
    109     Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
    110     Printf("FATAL: Make sure you are not using unlimited stack\n");
    111     Die();
    112   }
    113 }
    114 
    115 void CheckAndProtect() {
    116   // Ensure that the binary is indeed compiled with -pie.
    117   MemoryMappingLayout proc_maps(true);
    118   uptr p, end, prot;
    119   while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) {
    120     if (IsAppMem(p))
    121       continue;
    122     if (p >= HeapMemEnd() &&
    123         p < HeapEnd())
    124       continue;
    125     if (prot == 0)  // Zero page or mprotected.
    126       continue;
    127     if (p >= VdsoBeg())  // vdso
    128       break;
    129     Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end);
    130     Die();
    131   }
    132 
    133   ProtectRange(LoAppMemEnd(), ShadowBeg());
    134   ProtectRange(ShadowEnd(), MetaShadowBeg());
    135 #ifdef TSAN_MID_APP_RANGE
    136   ProtectRange(MetaShadowEnd(), MidAppMemBeg());
    137   ProtectRange(MidAppMemEnd(), TraceMemBeg());
    138 #else
    139   ProtectRange(MetaShadowEnd(), TraceMemBeg());
    140 #endif
    141   // Memory for traces is mapped lazily in MapThreadTrace.
    142   // Protect the whole range for now, so that user does not map something here.
    143   ProtectRange(TraceMemBeg(), TraceMemEnd());
    144   ProtectRange(TraceMemEnd(), HeapMemBeg());
    145   ProtectRange(HeapEnd(), HiAppMemBeg());
    146 }
    147 #endif
    148 
    149 }  // namespace __tsan
    150 
    151 #endif  // SANITIZER_POSIX
    152