asan_mac.cc revision 31f78fda9c511f9ab4afc3494f54cb24450e28e6
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" 20d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko#include "asan_mac.h" 21895b3872acb5bcccb1769ea69d37dd33c722f99dAlexander Potapenko#include "asan_mapping.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 2431f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko#include "sanitizer_common/sanitizer_atomic.h" 25ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 27eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko#include <crt_externs.h> // for _NSGetArgv 28eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko#include <dlfcn.h> // for dladdr() 298a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#include <mach-o/dyld.h> 309b993e8cd0f8964782ee93524603d0c53adc2249Kostya Serebryany#include <mach-o/loader.h> 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 32ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany#include <sys/resource.h> 3359dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko#include <sys/sysctl.h> 349107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 35a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany#include <fcntl.h> 36e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko#include <pthread.h> 37e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko#include <stdlib.h> // for free() 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 39d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include <libkern/OSAtomic.h> 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 433f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 449107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 455af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany# if SANITIZER_WORDSIZE == 64 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__rip; 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__rbp; 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__rsp; 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# else 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__eip; 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__ebp; 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__esp; 535af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany# endif // SANITIZER_WORDSIZE 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 5631f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander PotapenkoMacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; 5731f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko 5831f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander PotapenkoMacosVersion GetMacosVersionInternal() { 5959dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko int mib[2] = { CTL_KERN, KERN_OSRELEASE }; 6059dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko char version[100]; 613f46cf42b0f8e0667a3bea88cf871ebd4dc0ecdfAlexey Samsonov uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); 62b0bb7fb31301ee9ac9cf41f21d3a19987dc30609Alexey Samsonov for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; 6359dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko // Get the version length. 64a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1); 65a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany CHECK_LT(len, maxlen); 66a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1); 6759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko switch (version[0]) { 6859dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '9': return MACOS_VERSION_LEOPARD; 6959dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '1': { 7059dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko switch (version[1]) { 7159dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '0': return MACOS_VERSION_SNOW_LEOPARD; 7259dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '1': return MACOS_VERSION_LION; 73679bf63dba568611bf1fe6397fd0c41d43ac041aAlexander Potapenko case '2': return MACOS_VERSION_MOUNTAIN_LION; 74ad2ae5464b3c0f947f72908671ba1e6d753855a5Alexander Potapenko case '3': return MACOS_VERSION_MAVERICKS; 7559dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko default: return MACOS_VERSION_UNKNOWN; 7659dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 7759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 7859dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko default: return MACOS_VERSION_UNKNOWN; 7959dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 8059dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko} 8159dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko 8231f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander PotapenkoMacosVersion GetMacosVersion() { 8331f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko atomic_uint32_t *cache = 8431f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko reinterpret_cast<atomic_uint32_t*>(&cached_macos_version); 8531f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko MacosVersion result = 8631f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire)); 8731f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko if (result == MACOS_VERSION_UNINITIALIZED) { 8831f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko result = GetMacosVersionInternal(); 8931f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko atomic_store(cache, result, memory_order_release); 9031f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko } 9131f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko return result; 9231f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko} 9331f78fda9c511f9ab4afc3494f54cb24450e28e6Alexander Potapenko 9438dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonovbool PlatformHasDifferentMemcpyAndMemmove() { 9538dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // On OS X 10.7 memcpy() and memmove() are both resolved 9638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // into memmove$VARIANT$sse42. 9738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34. 9838dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // TODO(glider): need to check dynamically that memcpy() and memmove() are 9938dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // actually the same function. 10038dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; 10138dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov} 10238dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov 103eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkoextern "C" 104eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkovoid __asan_init(); 105eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 106eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkostatic const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 107fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander PotapenkoLowLevelAllocator allocator_for_env; 108fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 109fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// Change the value of the env var |name|, leaking the original value. 110fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// If |name_value| is NULL, the variable is deleted from the environment, 111fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// otherwise the corresponding "NAME=value" string is replaced with 112fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// |name_value|. 113fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenkovoid LeakyResetEnv(const char *name, const char *name_value) { 114fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char ***env_ptr = _NSGetEnviron(); 115fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(env_ptr); 116fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char **environ = *env_ptr; 117fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(environ); 118fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr name_len = internal_strlen(name); 119fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko while (*environ != 0) { 120fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr len = internal_strlen(*environ); 121fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (len > name_len) { 122fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko const char *p = *environ; 123fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { 124fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Match. 125fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (name_value) { 126fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Replace the old value with the new one. 127fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko *environ = const_cast<char*>(name_value); 128fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 129fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Shift the subsequent pointers back. 130fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char **del = environ; 131fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko do { 132fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko del[0] = del[1]; 133366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany } while (*del++); 134fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 135fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 136fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 137fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko environ++; 138fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 139fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko} 140eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 141eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkovoid MaybeReexec() { 142eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (!flags()->allow_reexec) return; 14369563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // Make sure the dynamic ASan runtime library is preloaded so that the 14469563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec 14569563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // ourselves. 146eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Dl_info info; 1474ea14c2fa243684e1d7a017bd4f0d1e38801de0aAlexey Samsonov CHECK(dladdr((void*)((uptr)__asan_init), &info)); 148fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *dyld_insert_libraries = 149fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko const_cast<char*>(GetEnv(kDyldInsertLibraries)); 150180e988700858a838e00fe9406f170502c203b85Alexey Samsonov uptr old_env_len = dyld_insert_libraries ? 151fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strlen(dyld_insert_libraries) : 0; 152e6b91fdad54c4c9a711b5149d65ea6a6f368d9abAlexey Samsonov uptr fname_len = internal_strlen(info.dli_fname); 153eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (!dyld_insert_libraries || 154eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { 155eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime 156eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko // library. 157eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko char program_name[1024]; 158eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko uint32_t buf_size = sizeof(program_name); 159eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko _NSGetExecutablePath(program_name, &buf_size); 160fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env = const_cast<char*>(info.dli_fname); 161eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko if (dyld_insert_libraries) { 162eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Append the runtime dylib name to the existing value of 163eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // DYLD_INSERT_LIBRARIES. 164fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); 165eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko internal_strncpy(new_env, dyld_insert_libraries, old_env_len); 166eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko new_env[old_env_len] = ':'; 167eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Copy fname_len and add a trailing zero. 1688da17ea3bc3ba0a28844642921247a3b9a1a3bcdKostya Serebryany internal_strncpy(new_env + old_env_len + 1, info.dli_fname, 1698da17ea3bc3ba0a28844642921247a3b9a1a3bcdKostya Serebryany fname_len + 1); 170fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Ok to use setenv() since the wrappers don't depend on the value of 171fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // asan_inited. 172eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); 173eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko } else { 174eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. 175eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); 176eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko } 177eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (flags()->verbosity >= 1) { 178eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("exec()-ing the program with\n"); 179fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko Report("%s=%s\n", kDyldInsertLibraries, new_env); 180eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("to enable ASan wrappers.\n"); 181eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); 182eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko } 183eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko execv(program_name, *_NSGetArgv()); 184fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 185fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // DYLD_INSERT_LIBRARIES is set and contains the runtime library. 186fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (old_env_len == fname_len) { 187fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // It's just the runtime library name - fine to unset the variable. 188fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko LeakyResetEnv(kDyldInsertLibraries, NULL); 189fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 190180e988700858a838e00fe9406f170502c203b85Alexey Samsonov uptr env_name_len = internal_strlen(kDyldInsertLibraries); 191fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Allocate memory to hold the previous env var name, its value, the '=' 192fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // sign and the '\0' char. 193fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env = (char*)allocator_for_env.Allocate( 194fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko old_env_len + 2 + env_name_len); 195fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(new_env); 196fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); 197fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); 198fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env[env_name_len] = '='; 199fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env_pos = new_env + env_name_len + 1; 200fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 201fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Iterate over colon-separated pieces of |dyld_insert_libraries|. 202fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *piece_start = dyld_insert_libraries; 203fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *piece_end = NULL; 204fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *old_env_end = dyld_insert_libraries + old_env_len; 205fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko do { 206fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (piece_start[0] == ':') piece_start++; 207fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko piece_end = REAL(strchr)(piece_start, ':'); 208fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; 209180e988700858a838e00fe9406f170502c203b85Alexey Samsonov if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; 210fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr piece_len = piece_end - piece_start; 211fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 212366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // If the current piece isn't the runtime library name, 213366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // append it to new_env. 214fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if ((piece_len != fname_len) || 215fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko (internal_strncmp(piece_start, info.dli_fname, fname_len) != 0)) { 216fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (new_env_pos != new_env + env_name_len + 1) { 217fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos[0] = ':'; 218fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos++; 219fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 220fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strncpy(new_env_pos, piece_start, piece_len); 221fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 222366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // Move on to the next piece. 223fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos += piece_len; 224fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko piece_start = piece_end; 225fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } while (piece_start < old_env_end); 226fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 227fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Can't use setenv() here, because it requires the allocator to be 228fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // initialized. 229fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in 230fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // a separate function called after InitializeAllocator(). 231fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko LeakyResetEnv(kDyldInsertLibraries, new_env); 232fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 233eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko } 234eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko} 235eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// No-op. Mac does not support static linkage anyway. 2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 2383f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 242cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov return (signum == SIGSEGV || signum == SIGBUS) && flags()->handle_segv; 2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 24575b19ebf25af204cf209d108997272822241d6daAlexander Potapenkovoid AsanPlatformThreadInit() { 24675b19ebf25af204cf209d108997272822241d6daAlexander Potapenko} 24775b19ebf25af204cf209d108997272822241d6daAlexander Potapenko 24857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovvoid ReadContextStack(void *context, uptr *stack, uptr *ssize) { 249f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov UNIMPLEMENTED(); 250f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov} 251f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Support for the following functions from libdispatch on Mac OS: 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async_f() 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async() 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync_f() 2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after_f() 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after() 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async_f() 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async() 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): libdispatch API contains other functions that we don't support 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// yet. 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// they can cause jobs to run on a thread different from the current one. 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): if so, we need a test for this (otherwise we should remove 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// them). 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following functions use dispatch_barrier_async_f() (which isn't a library 2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// function but is exported) and are thus supported: 2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler_f() 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler() 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler_f() 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler() 2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The reference manual for Grand Central Dispatch is available at 2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The implementation details are at 2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c 2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 281f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_group_t; 282f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_queue_t; 283af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkotypedef void* dispatch_source_t; 284ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryanytypedef u64 dispatch_time_t; 285f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void (*dispatch_function_t)(void *block); 2865cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef void* (*worker_t)(void *block); 2875cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov 2885cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov// A wrapper for the ObjC blocks used to support libdispatch. 2895cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef struct { 2905cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov void *block; 2915cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov dispatch_function_t func; 292e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany u32 parent_tid; 2935cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov} asan_block_context_t; 2945cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov 295b157c67e17c3fc8805c8b7cb590668885680608fTimur IskhodzhanovALWAYS_INLINE 296c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid asan_register_worker_thread(int parent_tid, StackTrace *stack) { 297c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov AsanThread *t = GetCurrentThread(); 298af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko if (!t) { 299def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov t = AsanThread::Create(0, 0); 300def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CreateThreadContextArgs args = { t, stack }; 301def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().CreateThread(*(uptr*)t, true, parent_tid, &args); 302af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko t->Init(); 303def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().StartThread(t->tid(), 0, 0); 304c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov SetCurrentThread(t); 305af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko } 306af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 307af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 3082483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// For use by only those functions that allocated the context via 3092483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// alloc_asan_context(). 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid asan_dispatch_call_block_and_release(void *block) { 312a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *context = (asan_block_context_t*)block; 314cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 2) { 3151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("asan_dispatch_call_block_and_release(): " 3161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "context: %p, pthread_self: %p\n", 3171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany block, pthread_self()); 3181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 319af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_register_worker_thread(context->parent_tid, &stack); 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Call the original dispatcher for the block. 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany context->func(context->block); 322fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(context, &stack, FROM_MALLOC); 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 3281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Wrap |ctxt| and |func| into an asan_block_context_t. 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The caller retains control of the allocated context. 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyasan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, 333c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany StackTrace *stack) { 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = ctxt; 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = func; 338c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov asan_ctxt->parent_tid = GetCurrentTidOrInvalid(); 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_ctxt; 3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 342b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// Define interceptor for dispatch_*_f function with the three most common 343b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// parameters: dispatch_queue_t, context, dispatch_function_t. 344b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \ 345b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \ 346b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko dispatch_function_t func) { \ 347a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; \ 348b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \ 349b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko if (flags()->verbosity >= 2) { \ 350b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \ 351b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_ctxt, pthread_self()); \ 352b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko PRINT_CURRENT_STACK(); \ 353b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko } \ 354b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \ 355b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_dispatch_call_block_and_release); \ 3560ffc227f91b068c78908f735a4846f92e339a337Kostya Serebryany } 357b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko 358b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_async_f) 359b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_sync_f) 360b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f) 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 362f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, dispatch_after_f, dispatch_time_t when, 363f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov dispatch_queue_t dq, void *ctxt, 364f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov dispatch_function_t func) { 365a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 367cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 2) { 3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_after_f: %p\n", asan_ctxt); 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 37109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt, 37209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov asan_dispatch_call_block_and_release); 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 375af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, 376af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_queue_t dq, void *ctxt, 377af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_function_t func) { 378a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 379af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 380af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko if (flags()->verbosity >= 2) { 381af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n", 382af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_ctxt, pthread_self()); 383af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko PRINT_CURRENT_STACK(); 384af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko } 385af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt, 386af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_dispatch_call_block_and_release); 387af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 388af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 38969563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if !defined(MISSING_BLOCKS_SUPPORT) 390af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkoextern "C" { 391af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko// FIXME: consolidate these declarations with asan_intercepted_functions.h. 392af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_async(dispatch_queue_t dq, void(^work)(void)); 393af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq, 394af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 395af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_after(dispatch_time_t when, dispatch_queue_t queue, 396af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 397af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_cancel_handler(dispatch_source_t ds, 398af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 399af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void)); 4002483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 4012483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 402af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#define GET_ASAN_BLOCK(work) \ 403af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void (^asan_block)(void); \ 404c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov int parent_tid = GetCurrentTidOrInvalid(); \ 405af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_block = ^(void) { \ 406a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; \ 407af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_register_worker_thread(parent_tid, &stack); \ 408af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko work(); \ 4092483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko } 4102483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 4112483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_async, 412af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_queue_t dq, void(^work)(void)) { 413af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 414af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_async)(dq, asan_block); 415af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 416af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 417af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async, 418af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) { 419af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 420af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_group_async)(dg, dq, asan_block); 4212483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 4222483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 4232483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_after, 424af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) { 425af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 426af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_after)(when, queue, asan_block); 4272483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 4282483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 429af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_cancel_handler, 430af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_source_t ds, void(^work)(void)) { 431af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 432af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_source_set_cancel_handler)(ds, asan_block); 4331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 435af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_event_handler, 436af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_source_t ds, void(^work)(void)) { 437af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 438af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_source_set_event_handler)(ds, asan_block); 439af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 440af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#endif 441af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 442649a270f5341efe9c57f473dbb78706b0b2ed523Alexey Samsonov#endif // SANITIZER_MAC 443