asan_mac.cc revision b157c67e17c3fc8805c8b7cb590668885680608f
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" 24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 26eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko#include <crt_externs.h> // for _NSGetArgv 27eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko#include <dlfcn.h> // for dladdr() 288a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#include <mach-o/dyld.h> 299b993e8cd0f8964782ee93524603d0c53adc2249Kostya Serebryany#include <mach-o/loader.h> 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 31ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany#include <sys/resource.h> 3259dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko#include <sys/sysctl.h> 339107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 34a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany#include <fcntl.h> 35e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko#include <pthread.h> 36e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko#include <stdlib.h> // for free() 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 38d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include <libkern/OSAtomic.h> 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 423f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 439107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 445af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany# if SANITIZER_WORDSIZE == 64 459107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__rip; 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__rbp; 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__rsp; 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# else 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__eip; 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__ebp; 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__esp; 525af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany# endif // SANITIZER_WORDSIZE 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 55d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenkoint GetMacosVersion() { 5659dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko int mib[2] = { CTL_KERN, KERN_OSRELEASE }; 5759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko char version[100]; 583f46cf42b0f8e0667a3bea88cf871ebd4dc0ecdfAlexey Samsonov uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); 59b0bb7fb31301ee9ac9cf41f21d3a19987dc30609Alexey Samsonov for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; 6059dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko // Get the version length. 613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(sysctl(mib, 2, 0, &len, 0, 0) != -1); 6259dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko CHECK(len < maxlen); 633f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(sysctl(mib, 2, version, &len, 0, 0) != -1); 6459dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko switch (version[0]) { 6559dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '9': return MACOS_VERSION_LEOPARD; 6659dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '1': { 6759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko switch (version[1]) { 6859dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '0': return MACOS_VERSION_SNOW_LEOPARD; 6959dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko case '1': return MACOS_VERSION_LION; 70679bf63dba568611bf1fe6397fd0c41d43ac041aAlexander Potapenko case '2': return MACOS_VERSION_MOUNTAIN_LION; 7159dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko default: return MACOS_VERSION_UNKNOWN; 7259dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 7359dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 7459dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko default: return MACOS_VERSION_UNKNOWN; 7559dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko } 7659dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko} 7759dc578df0de177b44c8c78f69d73735e38e5c14Alexander Potapenko 7838dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonovbool PlatformHasDifferentMemcpyAndMemmove() { 7938dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // On OS X 10.7 memcpy() and memmove() are both resolved 8038dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // into memmove$VARIANT$sse42. 8138dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34. 8238dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // TODO(glider): need to check dynamically that memcpy() and memmove() are 8338dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov // actually the same function. 8438dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; 8538dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov} 8638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov 87eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkoextern "C" 88eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkovoid __asan_init(); 89eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 90eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkostatic const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 91fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander PotapenkoLowLevelAllocator allocator_for_env; 92fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 93fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// Change the value of the env var |name|, leaking the original value. 94fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// If |name_value| is NULL, the variable is deleted from the environment, 95fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// otherwise the corresponding "NAME=value" string is replaced with 96fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko// |name_value|. 97fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenkovoid LeakyResetEnv(const char *name, const char *name_value) { 98fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char ***env_ptr = _NSGetEnviron(); 99fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(env_ptr); 100fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char **environ = *env_ptr; 101fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(environ); 102fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr name_len = internal_strlen(name); 103fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko while (*environ != 0) { 104fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr len = internal_strlen(*environ); 105fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (len > name_len) { 106fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko const char *p = *environ; 107fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { 108fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Match. 109fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (name_value) { 110fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Replace the old value with the new one. 111fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko *environ = const_cast<char*>(name_value); 112fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 113fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Shift the subsequent pointers back. 114fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char **del = environ; 115fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko do { 116fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko del[0] = del[1]; 117366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany } while (*del++); 118fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 119fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 120fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 121fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko environ++; 122fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 123fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko} 124eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 125eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenkovoid MaybeReexec() { 126eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (!flags()->allow_reexec) return; 12769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // Make sure the dynamic ASan runtime library is preloaded so that the 12869563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec 12969563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko // ourselves. 130eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Dl_info info; 1314ea14c2fa243684e1d7a017bd4f0d1e38801de0aAlexey Samsonov CHECK(dladdr((void*)((uptr)__asan_init), &info)); 132fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *dyld_insert_libraries = 133fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko const_cast<char*>(GetEnv(kDyldInsertLibraries)); 134180e988700858a838e00fe9406f170502c203b85Alexey Samsonov uptr old_env_len = dyld_insert_libraries ? 135fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strlen(dyld_insert_libraries) : 0; 136e6b91fdad54c4c9a711b5149d65ea6a6f368d9abAlexey Samsonov uptr fname_len = internal_strlen(info.dli_fname); 137eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (!dyld_insert_libraries || 138eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { 139eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime 140eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko // library. 141eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko char program_name[1024]; 142eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko uint32_t buf_size = sizeof(program_name); 143eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko _NSGetExecutablePath(program_name, &buf_size); 144fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env = const_cast<char*>(info.dli_fname); 145eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko if (dyld_insert_libraries) { 146eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Append the runtime dylib name to the existing value of 147eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // DYLD_INSERT_LIBRARIES. 148fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); 149eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko internal_strncpy(new_env, dyld_insert_libraries, old_env_len); 150eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko new_env[old_env_len] = ':'; 151eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Copy fname_len and add a trailing zero. 1528da17ea3bc3ba0a28844642921247a3b9a1a3bcdKostya Serebryany internal_strncpy(new_env + old_env_len + 1, info.dli_fname, 1538da17ea3bc3ba0a28844642921247a3b9a1a3bcdKostya Serebryany fname_len + 1); 154fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Ok to use setenv() since the wrappers don't depend on the value of 155fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // asan_inited. 156eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); 157eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko } else { 158eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. 159eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); 160eb5f427c10c5d23e520def5f921cbbed831526beAlexander Potapenko } 161eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko if (flags()->verbosity >= 1) { 162eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("exec()-ing the program with\n"); 163fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko Report("%s=%s\n", kDyldInsertLibraries, new_env); 164eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("to enable ASan wrappers.\n"); 165eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); 166eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko } 167eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko execv(program_name, *_NSGetArgv()); 168fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 169fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // DYLD_INSERT_LIBRARIES is set and contains the runtime library. 170fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (old_env_len == fname_len) { 171fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // It's just the runtime library name - fine to unset the variable. 172fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko LeakyResetEnv(kDyldInsertLibraries, NULL); 173fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } else { 174180e988700858a838e00fe9406f170502c203b85Alexey Samsonov uptr env_name_len = internal_strlen(kDyldInsertLibraries); 175fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Allocate memory to hold the previous env var name, its value, the '=' 176fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // sign and the '\0' char. 177fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env = (char*)allocator_for_env.Allocate( 178fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko old_env_len + 2 + env_name_len); 179fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko CHECK(new_env); 180fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); 181fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); 182fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env[env_name_len] = '='; 183fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *new_env_pos = new_env + env_name_len + 1; 184fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 185fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Iterate over colon-separated pieces of |dyld_insert_libraries|. 186fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *piece_start = dyld_insert_libraries; 187fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *piece_end = NULL; 188fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko char *old_env_end = dyld_insert_libraries + old_env_len; 189fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko do { 190fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (piece_start[0] == ':') piece_start++; 191fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko piece_end = REAL(strchr)(piece_start, ':'); 192fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; 193180e988700858a838e00fe9406f170502c203b85Alexey Samsonov if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; 194fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko uptr piece_len = piece_end - piece_start; 195fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 196366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // If the current piece isn't the runtime library name, 197366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // append it to new_env. 198fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if ((piece_len != fname_len) || 199fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko (internal_strncmp(piece_start, info.dli_fname, fname_len) != 0)) { 200fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko if (new_env_pos != new_env + env_name_len + 1) { 201fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos[0] = ':'; 202fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos++; 203fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 204fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko internal_strncpy(new_env_pos, piece_start, piece_len); 205fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 206366984e3aa286f7b4fb45f5c9e703f2768c407edKostya Serebryany // Move on to the next piece. 207fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko new_env_pos += piece_len; 208fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko piece_start = piece_end; 209fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } while (piece_start < old_env_end); 210fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko 211fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // Can't use setenv() here, because it requires the allocator to be 212fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // initialized. 213fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in 214fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko // a separate function called after InitializeAllocator(). 215fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko LeakyResetEnv(kDyldInsertLibraries, new_env); 216fe984cc9d8aa86cf6d5aa802b223a588d6f14105Alexander Potapenko } 217eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko } 218eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko} 219eb8c46e419f4c6f01d1b1a0d1b96cc51a61ecbc3Alexander Potapenko 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// No-op. Mac does not support static linkage anyway. 2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 2223f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2254803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 226cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov return (signum == SIGSEGV || signum == SIGBUS) && flags()->handle_segv; 2274803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 22975b19ebf25af204cf209d108997272822241d6daAlexander Potapenkovoid AsanPlatformThreadInit() { 23075b19ebf25af204cf209d108997272822241d6daAlexander Potapenko} 23175b19ebf25af204cf209d108997272822241d6daAlexander Potapenko 232a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryanyvoid GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) { 23352c06849f842ae3893c7520b7a45ba21e95a4f30Kostya Serebryany (void)fast; 2342b939c3abc8b7713ef28000bd768ca6d77445f45Kostya Serebryany stack->size = 0; 2352b939c3abc8b7713ef28000bd768ca6d77445f45Kostya Serebryany stack->trace[0] = pc; 2369cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov if ((max_s) > 1) { 2372b939c3abc8b7713ef28000bd768ca6d77445f45Kostya Serebryany stack->max_size = max_s; 2382b939c3abc8b7713ef28000bd768ca6d77445f45Kostya Serebryany if (!asan_inited) return; 239c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov if (AsanThread *t = GetCurrentThread()) 2402b939c3abc8b7713ef28000bd768ca6d77445f45Kostya Serebryany stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom()); 2419cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov } 2429cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov} 2439cfa194cc62026fc7c6e82f7303eee8ad4d10cf4Evgeniy Stepanov 24457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovvoid ReadContextStack(void *context, uptr *stack, uptr *ssize) { 245f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov UNIMPLEMENTED(); 246f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov} 247f3950c6d6acf53fe60735f6d38715c1ea6df814bAlexey Samsonov 2481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Support for the following functions from libdispatch on Mac OS: 2491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async_f() 2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async() 2511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync_f() 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after_f() 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after() 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async_f() 2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async() 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): libdispatch API contains other functions that we don't support 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// yet. 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// they can cause jobs to run on a thread different from the current one. 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): if so, we need a test for this (otherwise we should remove 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// them). 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following functions use dispatch_barrier_async_f() (which isn't a library 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// function but is exported) and are thus supported: 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler_f() 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler() 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler_f() 2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler() 2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The reference manual for Grand Central Dispatch is available at 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The implementation details are at 2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 277f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_group_t; 278f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void* dispatch_queue_t; 279af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkotypedef void* dispatch_source_t; 280ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryanytypedef u64 dispatch_time_t; 281f7ceaad2919d2e26e9edea29232bc9dd8f145c42Alexey Samsonovtypedef void (*dispatch_function_t)(void *block); 2825cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef void* (*worker_t)(void *block); 2835cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov 2845cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov// A wrapper for the ObjC blocks used to support libdispatch. 2855cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonovtypedef struct { 2865cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov void *block; 2875cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov dispatch_function_t func; 288e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany u32 parent_tid; 2895cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov} asan_block_context_t; 2905cf832dc0a6566ae4bb8d48b1f41da623d2c2c1aAlexey Samsonov 291b157c67e17c3fc8805c8b7cb590668885680608fTimur IskhodzhanovALWAYS_INLINE 292c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid asan_register_worker_thread(int parent_tid, StackTrace *stack) { 293c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov AsanThread *t = GetCurrentThread(); 294af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko if (!t) { 295def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov t = AsanThread::Create(0, 0); 296def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CreateThreadContextArgs args = { t, stack }; 297def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().CreateThread(*(uptr*)t, true, parent_tid, &args); 298af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko t->Init(); 299def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().StartThread(t->tid(), 0, 0); 300c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov SetCurrentThread(t); 301af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko } 302af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 303af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 3042483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// For use by only those functions that allocated the context via 3052483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko// alloc_asan_context(). 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid asan_dispatch_call_block_and_release(void *block) { 308a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 3091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *context = (asan_block_context_t*)block; 310cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 2) { 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("asan_dispatch_call_block_and_release(): " 3121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "context: %p, pthread_self: %p\n", 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany block, pthread_self()); 3141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 315af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_register_worker_thread(context->parent_tid, &stack); 3161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Call the original dispatcher for the block. 3171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany context->func(context->block); 318fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany asan_free(context, &stack, FROM_MALLOC); 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Wrap |ctxt| and |func| into an asan_block_context_t. 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The caller retains control of the allocated context. 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyasan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, 329c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany StackTrace *stack) { 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = ctxt; 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = func; 334c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov asan_ctxt->parent_tid = GetCurrentTidOrInvalid(); 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_ctxt; 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 338b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// Define interceptor for dispatch_*_f function with the three most common 339b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko// parameters: dispatch_queue_t, context, dispatch_function_t. 340b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \ 341b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \ 342b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko dispatch_function_t func) { \ 343a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; \ 344b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \ 345b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko if (flags()->verbosity >= 2) { \ 346b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \ 347b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_ctxt, pthread_self()); \ 348b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko PRINT_CURRENT_STACK(); \ 349b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko } \ 350b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \ 351b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko asan_dispatch_call_block_and_release); \ 3520ffc227f91b068c78908f735a4846f92e339a337Kostya Serebryany } 353b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander Potapenko 354b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_async_f) 355b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_sync_f) 356b09dd34786713a150fed5c5ab1529f01de0e2bc0Alexander PotapenkoINTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f) 3571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 358f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, dispatch_after_f, dispatch_time_t when, 359f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov dispatch_queue_t dq, void *ctxt, 360f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov dispatch_function_t func) { 361a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 363cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 2) { 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_after_f: %p\n", asan_ctxt); 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 36709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt, 36809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov asan_dispatch_call_block_and_release); 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 371af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, 372af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_queue_t dq, void *ctxt, 373af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_function_t func) { 374a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 375af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 376af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko if (flags()->verbosity >= 2) { 377af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n", 378af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_ctxt, pthread_self()); 379af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko PRINT_CURRENT_STACK(); 380af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko } 381af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt, 382af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_dispatch_call_block_and_release); 383af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 384af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 38569563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if !defined(MISSING_BLOCKS_SUPPORT) 386af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkoextern "C" { 387af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko// FIXME: consolidate these declarations with asan_intercepted_functions.h. 388af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_async(dispatch_queue_t dq, void(^work)(void)); 389af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq, 390af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 391af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_after(dispatch_time_t when, dispatch_queue_t queue, 392af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 393af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_cancel_handler(dispatch_source_t ds, 394af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void(^work)(void)); 395af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenkovoid dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void)); 3962483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 3972483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 398af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#define GET_ASAN_BLOCK(work) \ 399af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko void (^asan_block)(void); \ 400c25e62b0cdbca855e7611583b0ff7013c31db21dAlexey Samsonov int parent_tid = GetCurrentTidOrInvalid(); \ 401af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_block = ^(void) { \ 402a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; \ 403af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko asan_register_worker_thread(parent_tid, &stack); \ 404af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko work(); \ 4052483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko } 4062483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 4072483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_async, 408af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_queue_t dq, void(^work)(void)) { 409af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 410af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_async)(dq, asan_block); 411af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 412af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 413af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_group_async, 414af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) { 415af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 416af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_group_async)(dg, dq, asan_block); 4172483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 4182483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 4192483ce3e635515d907c0cd8c97db315142fb28dbAlexander PotapenkoINTERCEPTOR(void, dispatch_after, 420af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) { 421af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 422af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_after)(when, queue, asan_block); 4232483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko} 4242483ce3e635515d907c0cd8c97db315142fb28dbAlexander Potapenko 425af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_cancel_handler, 426af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_source_t ds, void(^work)(void)) { 427af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 428af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_source_set_cancel_handler)(ds, asan_block); 4291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 431af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander PotapenkoINTERCEPTOR(void, dispatch_source_set_event_handler, 432af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko dispatch_source_t ds, void(^work)(void)) { 433af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko GET_ASAN_BLOCK(work); 434af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko REAL(dispatch_source_set_event_handler)(ds, asan_block); 435af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko} 436af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko#endif 437af198e421ea198c5f9fa8cd691aa9a209b3d96a0Alexander Potapenko 438d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 439