dd_interceptors.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. //===-- dd_interceptors.cpp -----------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include <pthread.h>
  9. #include "dd_rtl.h"
  10. #include "interception/interception.h"
  11. #include "sanitizer_common/sanitizer_allocator_internal.h"
  12. #include "sanitizer_common/sanitizer_procmaps.h"
  13. using namespace __dsan;
  14. __attribute__((tls_model("initial-exec")))
  15. static __thread Thread *thr;
  16. __attribute__((tls_model("initial-exec")))
  17. static __thread volatile int initing;
  18. static bool inited;
  19. static uptr g_data_start;
  20. static uptr g_data_end;
  21. static bool InitThread() {
  22. if (initing)
  23. return false;
  24. if (thr != 0)
  25. return true;
  26. initing = true;
  27. if (!inited) {
  28. inited = true;
  29. Initialize();
  30. }
  31. thr = (Thread*)InternalAlloc(sizeof(*thr));
  32. internal_memset(thr, 0, sizeof(*thr));
  33. ThreadInit(thr);
  34. initing = false;
  35. return true;
  36. }
  37. INTERCEPTOR(int, pthread_mutex_destroy, pthread_mutex_t *m) {
  38. InitThread();
  39. MutexDestroy(thr, (uptr)m);
  40. return REAL(pthread_mutex_destroy)(m);
  41. }
  42. INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *m) {
  43. InitThread();
  44. MutexBeforeLock(thr, (uptr)m, true);
  45. int res = REAL(pthread_mutex_lock)(m);
  46. MutexAfterLock(thr, (uptr)m, true, false);
  47. return res;
  48. }
  49. INTERCEPTOR(int, pthread_mutex_trylock, pthread_mutex_t *m) {
  50. InitThread();
  51. int res = REAL(pthread_mutex_trylock)(m);
  52. if (res == 0)
  53. MutexAfterLock(thr, (uptr)m, true, true);
  54. return res;
  55. }
  56. INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *m) {
  57. InitThread();
  58. MutexBeforeUnlock(thr, (uptr)m, true);
  59. return REAL(pthread_mutex_unlock)(m);
  60. }
  61. INTERCEPTOR(int, pthread_spin_destroy, pthread_spinlock_t *m) {
  62. InitThread();
  63. int res = REAL(pthread_spin_destroy)(m);
  64. MutexDestroy(thr, (uptr)m);
  65. return res;
  66. }
  67. INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *m) {
  68. InitThread();
  69. MutexBeforeLock(thr, (uptr)m, true);
  70. int res = REAL(pthread_spin_lock)(m);
  71. MutexAfterLock(thr, (uptr)m, true, false);
  72. return res;
  73. }
  74. INTERCEPTOR(int, pthread_spin_trylock, pthread_spinlock_t *m) {
  75. InitThread();
  76. int res = REAL(pthread_spin_trylock)(m);
  77. if (res == 0)
  78. MutexAfterLock(thr, (uptr)m, true, true);
  79. return res;
  80. }
  81. INTERCEPTOR(int, pthread_spin_unlock, pthread_spinlock_t *m) {
  82. InitThread();
  83. MutexBeforeUnlock(thr, (uptr)m, true);
  84. return REAL(pthread_spin_unlock)(m);
  85. }
  86. INTERCEPTOR(int, pthread_rwlock_destroy, pthread_rwlock_t *m) {
  87. InitThread();
  88. MutexDestroy(thr, (uptr)m);
  89. return REAL(pthread_rwlock_destroy)(m);
  90. }
  91. INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *m) {
  92. InitThread();
  93. MutexBeforeLock(thr, (uptr)m, false);
  94. int res = REAL(pthread_rwlock_rdlock)(m);
  95. MutexAfterLock(thr, (uptr)m, false, false);
  96. return res;
  97. }
  98. INTERCEPTOR(int, pthread_rwlock_tryrdlock, pthread_rwlock_t *m) {
  99. InitThread();
  100. int res = REAL(pthread_rwlock_tryrdlock)(m);
  101. if (res == 0)
  102. MutexAfterLock(thr, (uptr)m, false, true);
  103. return res;
  104. }
  105. INTERCEPTOR(int, pthread_rwlock_timedrdlock, pthread_rwlock_t *m,
  106. const timespec *abstime) {
  107. InitThread();
  108. int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
  109. if (res == 0)
  110. MutexAfterLock(thr, (uptr)m, false, true);
  111. return res;
  112. }
  113. INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *m) {
  114. InitThread();
  115. MutexBeforeLock(thr, (uptr)m, true);
  116. int res = REAL(pthread_rwlock_wrlock)(m);
  117. MutexAfterLock(thr, (uptr)m, true, false);
  118. return res;
  119. }
  120. INTERCEPTOR(int, pthread_rwlock_trywrlock, pthread_rwlock_t *m) {
  121. InitThread();
  122. int res = REAL(pthread_rwlock_trywrlock)(m);
  123. if (res == 0)
  124. MutexAfterLock(thr, (uptr)m, true, true);
  125. return res;
  126. }
  127. INTERCEPTOR(int, pthread_rwlock_timedwrlock, pthread_rwlock_t *m,
  128. const timespec *abstime) {
  129. InitThread();
  130. int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
  131. if (res == 0)
  132. MutexAfterLock(thr, (uptr)m, true, true);
  133. return res;
  134. }
  135. INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *m) {
  136. InitThread();
  137. MutexBeforeUnlock(thr, (uptr)m, true); // note: not necessary write unlock
  138. return REAL(pthread_rwlock_unlock)(m);
  139. }
  140. static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {
  141. atomic_uintptr_t *p = (atomic_uintptr_t*)c;
  142. uptr cond = atomic_load(p, memory_order_acquire);
  143. if (!force && cond != 0)
  144. return (pthread_cond_t*)cond;
  145. void *newcond = InternalAlloc(sizeof(pthread_cond_t));
  146. internal_memset(newcond, 0, sizeof(pthread_cond_t));
  147. if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
  148. memory_order_acq_rel))
  149. return (pthread_cond_t*)newcond;
  150. InternalFree(newcond);
  151. return (pthread_cond_t*)cond;
  152. }
  153. INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *c,
  154. const pthread_condattr_t *a) {
  155. InitThread();
  156. pthread_cond_t *cond = init_cond(c, true);
  157. return REAL(pthread_cond_init)(cond, a);
  158. }
  159. INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *c, pthread_mutex_t *m) {
  160. InitThread();
  161. pthread_cond_t *cond = init_cond(c);
  162. MutexBeforeUnlock(thr, (uptr)m, true);
  163. MutexBeforeLock(thr, (uptr)m, true);
  164. int res = REAL(pthread_cond_wait)(cond, m);
  165. MutexAfterLock(thr, (uptr)m, true, false);
  166. return res;
  167. }
  168. INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *c, pthread_mutex_t *m,
  169. const timespec *abstime) {
  170. InitThread();
  171. pthread_cond_t *cond = init_cond(c);
  172. MutexBeforeUnlock(thr, (uptr)m, true);
  173. MutexBeforeLock(thr, (uptr)m, true);
  174. int res = REAL(pthread_cond_timedwait)(cond, m, abstime);
  175. MutexAfterLock(thr, (uptr)m, true, false);
  176. return res;
  177. }
  178. INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *c) {
  179. InitThread();
  180. pthread_cond_t *cond = init_cond(c);
  181. return REAL(pthread_cond_signal)(cond);
  182. }
  183. INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *c) {
  184. InitThread();
  185. pthread_cond_t *cond = init_cond(c);
  186. return REAL(pthread_cond_broadcast)(cond);
  187. }
  188. INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *c) {
  189. InitThread();
  190. pthread_cond_t *cond = init_cond(c);
  191. int res = REAL(pthread_cond_destroy)(cond);
  192. InternalFree(cond);
  193. atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
  194. return res;
  195. }
  196. // for symbolizer
  197. INTERCEPTOR(char*, realpath, const char *path, char *resolved_path) {
  198. InitThread();
  199. return REAL(realpath)(path, resolved_path);
  200. }
  201. INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
  202. InitThread();
  203. return REAL(read)(fd, ptr, count);
  204. }
  205. INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  206. InitThread();
  207. return REAL(pread)(fd, ptr, count, offset);
  208. }
  209. extern "C" {
  210. void __dsan_before_mutex_lock(uptr m, int writelock) {
  211. if (!InitThread())
  212. return;
  213. MutexBeforeLock(thr, m, writelock);
  214. }
  215. void __dsan_after_mutex_lock(uptr m, int writelock, int trylock) {
  216. if (!InitThread())
  217. return;
  218. MutexAfterLock(thr, m, writelock, trylock);
  219. }
  220. void __dsan_before_mutex_unlock(uptr m, int writelock) {
  221. if (!InitThread())
  222. return;
  223. MutexBeforeUnlock(thr, m, writelock);
  224. }
  225. void __dsan_mutex_destroy(uptr m) {
  226. if (!InitThread())
  227. return;
  228. // if (m >= g_data_start && m < g_data_end)
  229. // return;
  230. MutexDestroy(thr, m);
  231. }
  232. } // extern "C"
  233. namespace __dsan {
  234. static void InitDataSeg() {
  235. MemoryMappingLayout proc_maps(true);
  236. char name[128];
  237. MemoryMappedSegment segment(name, ARRAY_SIZE(name));
  238. bool prev_is_data = false;
  239. while (proc_maps.Next(&segment)) {
  240. bool is_data = segment.offset != 0 && segment.filename[0] != 0;
  241. // BSS may get merged with [heap] in /proc/self/maps. This is not very
  242. // reliable.
  243. bool is_bss = segment.offset == 0 &&
  244. (segment.filename[0] == 0 ||
  245. internal_strcmp(segment.filename, "[heap]") == 0) &&
  246. prev_is_data;
  247. if (g_data_start == 0 && is_data) g_data_start = segment.start;
  248. if (is_bss) g_data_end = segment.end;
  249. prev_is_data = is_data;
  250. }
  251. VPrintf(1, "guessed data_start=0x%zx data_end=0x%zx\n", g_data_start,
  252. g_data_end);
  253. CHECK_LT(g_data_start, g_data_end);
  254. CHECK_GE((uptr)&g_data_start, g_data_start);
  255. CHECK_LT((uptr)&g_data_start, g_data_end);
  256. }
  257. void InitializeInterceptors() {
  258. INTERCEPT_FUNCTION(pthread_mutex_destroy);
  259. INTERCEPT_FUNCTION(pthread_mutex_lock);
  260. INTERCEPT_FUNCTION(pthread_mutex_trylock);
  261. INTERCEPT_FUNCTION(pthread_mutex_unlock);
  262. INTERCEPT_FUNCTION(pthread_spin_destroy);
  263. INTERCEPT_FUNCTION(pthread_spin_lock);
  264. INTERCEPT_FUNCTION(pthread_spin_trylock);
  265. INTERCEPT_FUNCTION(pthread_spin_unlock);
  266. INTERCEPT_FUNCTION(pthread_rwlock_destroy);
  267. INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
  268. INTERCEPT_FUNCTION(pthread_rwlock_tryrdlock);
  269. INTERCEPT_FUNCTION(pthread_rwlock_timedrdlock);
  270. INTERCEPT_FUNCTION(pthread_rwlock_wrlock);
  271. INTERCEPT_FUNCTION(pthread_rwlock_trywrlock);
  272. INTERCEPT_FUNCTION(pthread_rwlock_timedwrlock);
  273. INTERCEPT_FUNCTION(pthread_rwlock_unlock);
  274. INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
  275. INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
  276. INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
  277. INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
  278. INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
  279. INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
  280. // for symbolizer
  281. INTERCEPT_FUNCTION(realpath);
  282. INTERCEPT_FUNCTION(read);
  283. INTERCEPT_FUNCTION(pread);
  284. InitDataSeg();
  285. }
  286. } // namespace __dsan