tsan_platform.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. //===-- tsan_platform.h -----------------------------------------*- C++ -*-===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is a part of ThreadSanitizer (TSan), a race detector.
  9. //
  10. // Platform-specific code.
  11. //===----------------------------------------------------------------------===//
  12. #ifndef TSAN_PLATFORM_H
  13. #define TSAN_PLATFORM_H
  14. #if !defined(__LP64__) && !defined(_WIN64)
  15. # error "Only 64-bit is supported"
  16. #endif
  17. #include "tsan_defs.h"
  18. #include "tsan_trace.h"
  19. namespace __tsan {
  20. #if !defined(TSAN_GO)
  21. /*
  22. C/C++ on linux and freebsd
  23. 0000 0000 1000 - 0100 0000 0000: main binary and/or MAP_32BIT mappings
  24. 0100 0000 0000 - 0200 0000 0000: -
  25. 0200 0000 0000 - 1000 0000 0000: shadow
  26. 1000 0000 0000 - 3000 0000 0000: -
  27. 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
  28. 4000 0000 0000 - 6000 0000 0000: -
  29. 6000 0000 0000 - 6200 0000 0000: traces
  30. 6200 0000 0000 - 7d00 0000 0000: -
  31. 7d00 0000 0000 - 7e00 0000 0000: heap
  32. 7e00 0000 0000 - 7e80 0000 0000: -
  33. 7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
  34. */
  35. const uptr kMetaShadowBeg = 0x300000000000ull;
  36. const uptr kMetaShadowEnd = 0x400000000000ull;
  37. const uptr kTraceMemBeg = 0x600000000000ull;
  38. const uptr kTraceMemEnd = 0x620000000000ull;
  39. const uptr kShadowBeg = 0x020000000000ull;
  40. const uptr kShadowEnd = 0x100000000000ull;
  41. const uptr kHeapMemBeg = 0x7d0000000000ull;
  42. const uptr kHeapMemEnd = 0x7e0000000000ull;
  43. const uptr kLoAppMemBeg = 0x000000001000ull;
  44. const uptr kLoAppMemEnd = 0x010000000000ull;
  45. const uptr kHiAppMemBeg = 0x7e8000000000ull;
  46. const uptr kHiAppMemEnd = 0x800000000000ull;
  47. const uptr kAppMemMsk = 0x7c0000000000ull;
  48. const uptr kAppMemXor = 0x020000000000ull;
  49. ALWAYS_INLINE
  50. bool IsAppMem(uptr mem) {
  51. return (mem >= kHeapMemBeg && mem < kHeapMemEnd) ||
  52. (mem >= kLoAppMemBeg && mem < kLoAppMemEnd) ||
  53. (mem >= kHiAppMemBeg && mem < kHiAppMemEnd);
  54. }
  55. ALWAYS_INLINE
  56. bool IsShadowMem(uptr mem) {
  57. return mem >= kShadowBeg && mem <= kShadowEnd;
  58. }
  59. ALWAYS_INLINE
  60. bool IsMetaMem(uptr mem) {
  61. return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
  62. }
  63. ALWAYS_INLINE
  64. uptr MemToShadow(uptr x) {
  65. DCHECK(IsAppMem(x));
  66. return (((x) & ~(kAppMemMsk | (kShadowCell - 1)))
  67. ^ kAppMemXor) * kShadowCnt;
  68. }
  69. ALWAYS_INLINE
  70. u32 *MemToMeta(uptr x) {
  71. DCHECK(IsAppMem(x));
  72. return (u32*)(((((x) & ~(kAppMemMsk | (kMetaShadowCell - 1)))
  73. ^ kAppMemXor) / kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
  74. }
  75. ALWAYS_INLINE
  76. uptr ShadowToMem(uptr s) {
  77. CHECK(IsShadowMem(s));
  78. if (s >= MemToShadow(kLoAppMemBeg) && s <= MemToShadow(kLoAppMemEnd - 1))
  79. return (s / kShadowCnt) ^ kAppMemXor;
  80. else
  81. return ((s / kShadowCnt) ^ kAppMemXor) | kAppMemMsk;
  82. }
  83. static USED uptr UserRegions[] = {
  84. kLoAppMemBeg, kLoAppMemEnd,
  85. kHiAppMemBeg, kHiAppMemEnd,
  86. kHeapMemBeg, kHeapMemEnd,
  87. };
  88. #elif defined(TSAN_GO) && !SANITIZER_WINDOWS
  89. /* Go on linux, darwin and freebsd
  90. 0000 0000 1000 - 0000 1000 0000: executable
  91. 0000 1000 0000 - 00c0 0000 0000: -
  92. 00c0 0000 0000 - 00e0 0000 0000: heap
  93. 00e0 0000 0000 - 2000 0000 0000: -
  94. 2000 0000 0000 - 2380 0000 0000: shadow
  95. 2380 0000 0000 - 3000 0000 0000: -
  96. 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
  97. 4000 0000 0000 - 6000 0000 0000: -
  98. 6000 0000 0000 - 6200 0000 0000: traces
  99. 6200 0000 0000 - 8000 0000 0000: -
  100. */
  101. const uptr kMetaShadowBeg = 0x300000000000ull;
  102. const uptr kMetaShadowEnd = 0x400000000000ull;
  103. const uptr kTraceMemBeg = 0x600000000000ull;
  104. const uptr kTraceMemEnd = 0x620000000000ull;
  105. const uptr kShadowBeg = 0x200000000000ull;
  106. const uptr kShadowEnd = 0x238000000000ull;
  107. const uptr kAppMemBeg = 0x000000001000ull;
  108. const uptr kAppMemEnd = 0x00e000000000ull;
  109. ALWAYS_INLINE
  110. bool IsAppMem(uptr mem) {
  111. return mem >= kAppMemBeg && mem < kAppMemEnd;
  112. }
  113. ALWAYS_INLINE
  114. bool IsShadowMem(uptr mem) {
  115. return mem >= kShadowBeg && mem <= kShadowEnd;
  116. }
  117. ALWAYS_INLINE
  118. bool IsMetaMem(uptr mem) {
  119. return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
  120. }
  121. ALWAYS_INLINE
  122. uptr MemToShadow(uptr x) {
  123. DCHECK(IsAppMem(x));
  124. return ((x & ~(kShadowCell - 1)) * kShadowCnt) | kShadowBeg;
  125. }
  126. ALWAYS_INLINE
  127. u32 *MemToMeta(uptr x) {
  128. DCHECK(IsAppMem(x));
  129. return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
  130. kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
  131. }
  132. ALWAYS_INLINE
  133. uptr ShadowToMem(uptr s) {
  134. CHECK(IsShadowMem(s));
  135. return (s & ~kShadowBeg) / kShadowCnt;
  136. }
  137. static USED uptr UserRegions[] = {
  138. kAppMemBeg, kAppMemEnd,
  139. };
  140. #elif defined(TSAN_GO) && SANITIZER_WINDOWS
  141. /* Go on windows
  142. 0000 0000 1000 - 0000 1000 0000: executable
  143. 0000 1000 0000 - 00f8 0000 0000: -
  144. 00c0 0000 0000 - 00e0 0000 0000: heap
  145. 00e0 0000 0000 - 0100 0000 0000: -
  146. 0100 0000 0000 - 0380 0000 0000: shadow
  147. 0380 0000 0000 - 0560 0000 0000: -
  148. 0560 0000 0000 - 0760 0000 0000: traces
  149. 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
  150. 07d0 0000 0000 - 8000 0000 0000: -
  151. */
  152. const uptr kMetaShadowBeg = 0x076000000000ull;
  153. const uptr kMetaShadowEnd = 0x07d000000000ull;
  154. const uptr kTraceMemBeg = 0x056000000000ull;
  155. const uptr kTraceMemEnd = 0x076000000000ull;
  156. const uptr kShadowBeg = 0x010000000000ull;
  157. const uptr kShadowEnd = 0x038000000000ull;
  158. const uptr kAppMemBeg = 0x000000001000ull;
  159. const uptr kAppMemEnd = 0x00e000000000ull;
  160. ALWAYS_INLINE
  161. bool IsAppMem(uptr mem) {
  162. return mem >= kAppMemBeg && mem < kAppMemEnd;
  163. }
  164. ALWAYS_INLINE
  165. bool IsShadowMem(uptr mem) {
  166. return mem >= kShadowBeg && mem <= kShadowEnd;
  167. }
  168. ALWAYS_INLINE
  169. bool IsMetaMem(uptr mem) {
  170. return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
  171. }
  172. ALWAYS_INLINE
  173. uptr MemToShadow(uptr x) {
  174. DCHECK(IsAppMem(x));
  175. return ((x & ~(kShadowCell - 1)) * kShadowCnt) | kShadowBeg;
  176. }
  177. ALWAYS_INLINE
  178. u32 *MemToMeta(uptr x) {
  179. DCHECK(IsAppMem(x));
  180. return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
  181. kMetaShadowCell * kMetaShadowSize) | kMetaShadowEnd);
  182. }
  183. ALWAYS_INLINE
  184. uptr ShadowToMem(uptr s) {
  185. CHECK(IsShadowMem(s));
  186. // FIXME(dvyukov): this is most likely wrong as the mapping is not bijection.
  187. return (x & ~kShadowBeg) / kShadowCnt;
  188. }
  189. static USED uptr UserRegions[] = {
  190. kAppMemBeg, kAppMemEnd,
  191. };
  192. #else
  193. # error "Unknown platform"
  194. #endif
  195. // The additional page is to catch shadow stack overflow as paging fault.
  196. // Windows wants 64K alignment for mmaps.
  197. const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
  198. + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
  199. uptr ALWAYS_INLINE GetThreadTrace(int tid) {
  200. uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize;
  201. DCHECK_LT(p, kTraceMemEnd);
  202. return p;
  203. }
  204. uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
  205. uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize
  206. + kTraceSize * sizeof(Event);
  207. DCHECK_LT(p, kTraceMemEnd);
  208. return p;
  209. }
  210. void InitializePlatform();
  211. void FlushShadowMemory();
  212. void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
  213. uptr GetRSS();
  214. void *internal_start_thread(void(*func)(void*), void *arg);
  215. void internal_join_thread(void *th);
  216. // Says whether the addr relates to a global var.
  217. // Guesses with high probability, may yield both false positives and negatives.
  218. bool IsGlobalVar(uptr addr);
  219. int ExtractResolvFDs(void *state, int *fds, int nfd);
  220. int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
  221. int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
  222. void *abstime), void *c, void *m, void *abstime,
  223. void(*cleanup)(void *arg), void *arg);
  224. } // namespace __tsan
  225. #endif // TSAN_PLATFORM_H