Home | History | Annotate | Download | only in rtl
      1 //===-- tsan_platform.h -----------------------------------------*- C++ -*-===//
      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 // Platform-specific code.
     13 //===----------------------------------------------------------------------===//
     14 
     15 /*
     16 C++ linux memory layout:
     17 0000 0000 0000 - 03c0 0000 0000: protected
     18 03c0 0000 0000 - 1000 0000 0000: shadow
     19 1000 0000 0000 - 3000 0000 0000: protected
     20 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
     21 4000 0000 0000 - 6000 0000 0000: protected
     22 6000 0000 0000 - 6200 0000 0000: traces
     23 6200 0000 0000 - 7d00 0000 0000: -
     24 7d00 0000 0000 - 7e00 0000 0000: heap
     25 7e00 0000 0000 - 7fff ffff ffff: modules and main thread stack
     26 
     27 C++ COMPAT linux memory layout:
     28 0000 0000 0000 - 0400 0000 0000: protected
     29 0400 0000 0000 - 1000 0000 0000: shadow
     30 1000 0000 0000 - 2900 0000 0000: protected
     31 2900 0000 0000 - 2c00 0000 0000: modules
     32 2c00 0000 0000 - 3000 0000 0000: -
     33 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
     34 4000 0000 0000 - 6000 0000 0000: -
     35 6000 0000 0000 - 6200 0000 0000: traces
     36 6200 0000 0000 - 7d00 0000 0000: -
     37 7d00 0000 0000 - 7e00 0000 0000: heap
     38 7e00 0000 0000 - 7f00 0000 0000: -
     39 7f00 0000 0000 - 7fff ffff ffff: main thread stack
     40 
     41 Go linux and darwin memory layout:
     42 0000 0000 0000 - 0000 1000 0000: executable
     43 0000 1000 0000 - 00f8 0000 0000: -
     44 00c0 0000 0000 - 00e0 0000 0000: heap
     45 00e0 0000 0000 - 1000 0000 0000: -
     46 1000 0000 0000 - 1380 0000 0000: shadow
     47 1460 0000 0000 - 2000 0000 0000: -
     48 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
     49 4000 0000 0000 - 6000 0000 0000: -
     50 6000 0000 0000 - 6200 0000 0000: traces
     51 6200 0000 0000 - 7fff ffff ffff: -
     52 
     53 Go windows memory layout:
     54 0000 0000 0000 - 0000 1000 0000: executable
     55 0000 1000 0000 - 00f8 0000 0000: -
     56 00c0 0000 0000 - 00e0 0000 0000: heap
     57 00e0 0000 0000 - 0100 0000 0000: -
     58 0100 0000 0000 - 0560 0000 0000: shadow
     59 0560 0000 0000 - 0760 0000 0000: traces
     60 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
     61 07d0 0000 0000 - 07ff ffff ffff: -
     62 */
     63 
     64 #ifndef TSAN_PLATFORM_H
     65 #define TSAN_PLATFORM_H
     66 
     67 #include "tsan_defs.h"
     68 #include "tsan_trace.h"
     69 
     70 #if defined(__LP64__) || defined(_WIN64)
     71 namespace __tsan {
     72 
     73 #if defined(TSAN_GO)
     74 static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
     75 static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL;
     76 # if SANITIZER_WINDOWS
     77 static const uptr kLinuxShadowMsk = 0x010000000000ULL;
     78 static const uptr kMetaShadow     = 0x076000000000ULL;
     79 static const uptr kMetaSize       = 0x007000000000ULL;
     80 # else  // if SANITIZER_WINDOWS
     81 static const uptr kLinuxShadowMsk = 0x200000000000ULL;
     82 static const uptr kMetaShadow     = 0x300000000000ULL;
     83 static const uptr kMetaSize       = 0x100000000000ULL;
     84 # endif  // if SANITIZER_WINDOWS
     85 #else  // defined(TSAN_GO)
     86 static const uptr kMetaShadow     = 0x300000000000ULL;
     87 static const uptr kMetaSize       = 0x100000000000ULL;
     88 // TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout,
     89 // when memory addresses are of the 0x2axxxxxxxxxx form.
     90 // The option is enabled with 'setarch x86_64 -L'.
     91 # if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
     92 static const uptr kLinuxAppMemBeg = 0x290000000000ULL;
     93 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
     94 static const uptr kAppMemGapBeg   = 0x2c0000000000ULL;
     95 static const uptr kAppMemGapEnd   = 0x7d0000000000ULL;
     96 # else
     97 static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL;
     98 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
     99 # endif
    100 #endif
    101 
    102 static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL;
    103 
    104 #if SANITIZER_WINDOWS
    105 const uptr kTraceMemBegin = 0x056000000000ULL;
    106 #else
    107 const uptr kTraceMemBegin = 0x600000000000ULL;
    108 #endif
    109 const uptr kTraceMemSize = 0x020000000000ULL;
    110 
    111 // This has to be a macro to allow constant initialization of constants below.
    112 #ifndef TSAN_GO
    113 #define MemToShadow(addr) \
    114     ((((uptr)addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt)
    115 #define MemToMeta(addr) \
    116     (u32*)(((((uptr)addr) & ~(kLinuxAppMemMsk | (kMetaShadowCell - 1))) \
    117     / kMetaShadowCell * kMetaShadowSize) | kMetaShadow)
    118 #else
    119 #define MemToShadow(addr) \
    120     (((((uptr)addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk)
    121 #define MemToMeta(addr) \
    122     (u32*)(((((uptr)addr) & ~(kMetaShadowCell - 1)) \
    123     / kMetaShadowCell * kMetaShadowSize) | kMetaShadow)
    124 #endif
    125 
    126 static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg);
    127 static const uptr kLinuxShadowEnd =
    128     MemToShadow(kLinuxAppMemEnd) | 0xff;
    129 
    130 static inline bool IsAppMem(uptr mem) {
    131 #if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
    132   return (mem >= kLinuxAppMemBeg && mem < kAppMemGapBeg) ||
    133          (mem >= kAppMemGapEnd   && mem <= kLinuxAppMemEnd);
    134 #elif defined(TSAN_GO)
    135   return mem <= kLinuxAppMemEnd;
    136 #else
    137   return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd;
    138 #endif
    139 }
    140 
    141 static inline bool IsShadowMem(uptr mem) {
    142   return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd;
    143 }
    144 
    145 static inline uptr ShadowToMem(uptr shadow) {
    146   CHECK(IsShadowMem(shadow));
    147 #ifdef TSAN_GO
    148   return (shadow & ~kLinuxShadowMsk) / kShadowCnt;
    149 #else
    150   return (shadow / kShadowCnt) | kLinuxAppMemMsk;
    151 #endif
    152 }
    153 
    154 // For COMPAT mapping returns an alternative address
    155 // that mapped to the same shadow address.
    156 // COMPAT mapping is not quite one-to-one.
    157 static inline uptr AlternativeAddress(uptr addr) {
    158 #if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
    159   return (addr & ~kLinuxAppMemMsk) | 0x280000000000ULL;
    160 #else
    161   return 0;
    162 #endif
    163 }
    164 
    165 void FlushShadowMemory();
    166 void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
    167 uptr GetRSS();
    168 
    169 const char *InitializePlatform();
    170 void FinalizePlatform();
    171 
    172 // The additional page is to catch shadow stack overflow as paging fault.
    173 // Windows wants 64K alignment for mmaps.
    174 const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
    175     + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
    176 
    177 uptr ALWAYS_INLINE GetThreadTrace(int tid) {
    178   uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize;
    179   DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
    180   return p;
    181 }
    182 
    183 uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
    184   uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize
    185       + kTraceSize * sizeof(Event);
    186   DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
    187   return p;
    188 }
    189 
    190 void *internal_start_thread(void(*func)(void*), void *arg);
    191 void internal_join_thread(void *th);
    192 
    193 // Says whether the addr relates to a global var.
    194 // Guesses with high probability, may yield both false positives and negatives.
    195 bool IsGlobalVar(uptr addr);
    196 int ExtractResolvFDs(void *state, int *fds, int nfd);
    197 int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
    198 
    199 int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
    200     void *abstime), void *c, void *m, void *abstime,
    201     void(*cleanup)(void *arg), void *arg);
    202 
    203 }  // namespace __tsan
    204 
    205 #else  // defined(__LP64__) || defined(_WIN64)
    206 # error "Only 64-bit is supported"
    207 #endif
    208 
    209 #endif  // TSAN_PLATFORM_H
    210