11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_mac.cc -------------------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Mac-specific details.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h"
1630e110edf92303237d471f1cb8e3ad07954fb145Evgeniy Stepanov#if SANITIZER_MAC
171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1864ce2db7c838cd95315f7a4428e8a628eaa3e2fcAlexey Samsonov#include "asan_interceptors.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
20895b3872acb5bcccb1769ea69d37dd33c722f99dAlexander Potapenko#include "asan_mapping.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h"
2331f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko#include "sanitizer_common/sanitizer_atomic.h"
24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_mac.h"
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
27c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <dlfcn.h>
28799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <fcntl.h>
29799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <libkern/OSAtomic.h>
308a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#include <mach-o/dyld.h>
31c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <mach-o/getsect.h>
329b993e8cd0f8964782ee93524603d0c53adc2249Kostya Serebryany#include <mach-o/loader.h>
33799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <pthread.h>
34799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <stdlib.h>  // for free()
351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h>
36ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany#include <sys/resource.h>
3759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko#include <sys/sysctl.h>
389107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h>
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h>
401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
41c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// from <crt_externs.h>, but we don't have that file on iOS
42c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" {
43c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  extern char ***_NSGetArgv(void);
44c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  extern char ***_NSGetEnviron(void);
45c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
46c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid InitializePlatformInterceptors() {}
50c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid InitializePlatformExceptionHandlers() {}
5131f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko
5238dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonovbool PlatformHasDifferentMemcpyAndMemmove() {
5338dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  // On OS X 10.7 memcpy() and memmove() are both resolved
5438dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  // into memmove$VARIANT$sse42.
55799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  // See also https://github.com/google/sanitizers/issues/34.
5638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  // TODO(glider): need to check dynamically that memcpy() and memmove() are
5738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  // actually the same function.
5838dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov  return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
5938dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov}
6038dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov
611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// No-op. Mac does not support static linkage anyway.
621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() {
633f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  return 0;
641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// No-op. Mac does not support static linkage anyway.
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckDynamicRTPrereqs() {}
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// No-op. Mac does not support static linkage anyway.
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsanCheckIncompatibleRT() {}
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
72c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
73c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Find the Mach-O header for the image containing the needle
74c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  Dl_info info;
75c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  int err = dladdr(needle, &info);
76c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (err == 0) return;
77c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
78c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if __LP64__
79c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const struct mach_header_64 *mh = (struct mach_header_64 *)info.dli_fbase;
80c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else
81c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  const struct mach_header *mh = (struct mach_header *)info.dli_fbase;
82c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif
83c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
84c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Look up the __asan_globals section in that image and register its globals
85c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  unsigned long size = 0;
86c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  __asan_global *globals = (__asan_global *)getsectiondata(
87c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      mh,
88c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      "__DATA", "__asan_globals",
89c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      &size);
90c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
91c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (!globals) return;
92c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  if (size % sizeof(__asan_global) != 0) return;
93c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  op(globals, size / sizeof(__asan_global));
94c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
95c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
9657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovvoid ReadContextStack(void *context, uptr *stack, uptr *ssize) {
97f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov  UNIMPLEMENTED();
98f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov}
99f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Support for the following functions from libdispatch on Mac OS:
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_async_f()
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_async()
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_sync_f()
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_sync()
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_after_f()
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_after()
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_group_async_f()
1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_group_async()
1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): libdispatch API contains other functions that we don't support
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// yet.
1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// they can cause jobs to run on a thread different from the current one.
1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): if so, we need a test for this (otherwise we should remove
1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// them).
1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following functions use dispatch_barrier_async_f() (which isn't a library
1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// function but is exported) and are thus supported:
1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_source_set_cancel_handler_f()
1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_source_set_cancel_handler()
1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_source_set_event_handler_f()
1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   dispatch_source_set_event_handler()
1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The reference manual for Grand Central Dispatch is available at
1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The implementation details are at
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//   http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c
1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
129f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_group_t;
130f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_queue_t;
131af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkotypedef void* dispatch_source_t;
132ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryanytypedef u64 dispatch_time_t;
133f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void (*dispatch_function_t)(void *block);
1345cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef void* (*worker_t)(void *block);
1355cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov
1365cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov// A wrapper for the ObjC blocks used to support libdispatch.
1375cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef struct {
1385cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov  void *block;
1395cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov  dispatch_function_t func;
140e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany  u32 parent_tid;
1415cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov} asan_block_context_t;
1425cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov
143b157c67e17c3fc8805c8b7cb590668885680608fTimur IskhodzhanovALWAYS_INLINE
144c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid asan_register_worker_thread(int parent_tid, StackTrace *stack) {
145c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov  AsanThread *t = GetCurrentThread();
146af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  if (!t) {
14786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr,
14886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                           parent_tid, stack, /* detached */ true);
149af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko    t->Init();
150def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asanThreadRegistry().StartThread(t->tid(), 0, 0);
151c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov    SetCurrentThread(t);
152af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  }
153af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko}
154af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko
1552483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// For use by only those functions that allocated the context via
1562483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// alloc_asan_context().
1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C"
1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid asan_dispatch_call_block_and_release(void *block) {
159a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  asan_block_context_t *context = (asan_block_context_t*)block;
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(2,
1622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "asan_dispatch_call_block_and_release(): "
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "context: %p, pthread_self: %p\n",
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          block, pthread_self());
165af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  asan_register_worker_thread(context->parent_tid, &stack);
1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // Call the original dispatcher for the block.
1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  context->func(context->block);
168fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  asan_free(context, &stack, FROM_MALLOC);
1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
1741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Wrap |ctxt| and |func| into an asan_block_context_t.
1761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The caller retains control of the allocated context.
1771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C"
1781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyasan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
1796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                                         BufferedStackTrace *stack) {
1801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  asan_block_context_t *asan_ctxt =
1811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
1821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  asan_ctxt->block = ctxt;
1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  asan_ctxt->func = func;
184c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov  asan_ctxt->parent_tid = GetCurrentTidOrInvalid();
1851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_ctxt;
1861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
188b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// Define interceptor for dispatch_*_f function with the three most common
189b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// parameters: dispatch_queue_t, context, dispatch_function_t.
190b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f)                                \
191b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko  INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt,            \
192b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko                                  dispatch_function_t func) {                 \
193a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    GET_STACK_TRACE_THREAD;                                                   \
194b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko    asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \
19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (Verbosity() >= 2) {                                     \
196b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko      Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n",             \
197b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko             asan_ctxt, pthread_self());                                      \
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      PRINT_CURRENT_STACK();                                                  \
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }                                                                         \
2002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return REAL(dispatch_x_f)(dq, (void*)asan_ctxt,                           \
2012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                              asan_dispatch_call_block_and_release);          \
2020ffc227f91b068c78908f735a4846f92e339a337Kostya Serebryany  }
203b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko
204b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_async_f)
205b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_sync_f)
206b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f)
2071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
208f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
209f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov                                    dispatch_queue_t dq, void *ctxt,
210f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov                                    dispatch_function_t func) {
211a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (Verbosity() >= 2) {
2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    Report("dispatch_after_f: %p\n", asan_ctxt);
2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    PRINT_CURRENT_STACK();
2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
21709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt,
21809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov                                asan_dispatch_call_block_and_release);
2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
221af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
222af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                                          dispatch_queue_t dq, void *ctxt,
223af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                                          dispatch_function_t func) {
224a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_THREAD;
225af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
22686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (Verbosity() >= 2) {
227af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko    Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n",
228af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko           asan_ctxt, pthread_self());
229af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko    PRINT_CURRENT_STACK();
230af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  }
231af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt,
232af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                               asan_dispatch_call_block_and_release);
233af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko}
234af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko
23569563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if !defined(MISSING_BLOCKS_SUPPORT)
236af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkoextern "C" {
237af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_async(dispatch_queue_t dq, void(^work)(void));
238af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
239af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                          void(^work)(void));
240af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
241af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                    void(^work)(void));
242af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_cancel_handler(dispatch_source_t ds,
243af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko                                        void(^work)(void));
244af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
2452483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko}
2462483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko
247af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#define GET_ASAN_BLOCK(work) \
248af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  void (^asan_block)(void);  \
249c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov  int parent_tid = GetCurrentTidOrInvalid(); \
250af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  asan_block = ^(void) { \
251a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany    GET_STACK_TRACE_THREAD; \
252af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko    asan_register_worker_thread(parent_tid, &stack); \
253af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko    work(); \
2542483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko  }
2552483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko
2562483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_async,
257af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko            dispatch_queue_t dq, void(^work)(void)) {
2586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENABLE_FRAME_POINTER;
259af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  GET_ASAN_BLOCK(work);
260af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_async)(dq, asan_block);
261af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko}
262af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko
263af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async,
264af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko            dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) {
2656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENABLE_FRAME_POINTER;
266af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  GET_ASAN_BLOCK(work);
267af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_group_async)(dg, dq, asan_block);
2682483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko}
2692483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko
2702483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_after,
271af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko            dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) {
2726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENABLE_FRAME_POINTER;
273af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  GET_ASAN_BLOCK(work);
274af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_after)(when, queue, asan_block);
2752483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko}
2762483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko
277af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_cancel_handler,
278af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko            dispatch_source_t ds, void(^work)(void)) {
27986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!work) {
28086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    REAL(dispatch_source_set_cancel_handler)(ds, work);
28186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return;
28286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
2836a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENABLE_FRAME_POINTER;
284af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  GET_ASAN_BLOCK(work);
285af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_source_set_cancel_handler)(ds, asan_block);
2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
288af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_event_handler,
289af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko            dispatch_source_t ds, void(^work)(void)) {
2906a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENABLE_FRAME_POINTER;
291af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  GET_ASAN_BLOCK(work);
292af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko  REAL(dispatch_source_set_event_handler)(ds, asan_block);
293af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko}
294af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#endif
295af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko
296649a270f5341efe9c57f473dbb78706b0b2ed523Alexey Samsonov#endif  // SANITIZER_MAC
297