asan_mac.cc revision 3281209790b5e543c79acb2f5008d1df77fb76d9
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 15d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __APPLE__ 161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mac.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread_registry.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 241e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko#include <crt_externs.h> // for _NSGetEnviron 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 26ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany#include <sys/resource.h> 279107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 28c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 29a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany#include <fcntl.h> 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 31d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include <libkern/OSAtomic.h> 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 353281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkovoid *island_allocator_pos = NULL; 363281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_async_f_f real_dispatch_async_f; 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_sync_f_f real_dispatch_sync_f; 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_after_f_f real_dispatch_after_f; 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_barrier_async_f_f real_dispatch_barrier_async_f; 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_group_async_f_f real_dispatch_group_async_f; 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np; 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 449107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryanyvoid GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { 459107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# if __WORDSIZE == 64 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__rip; 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__rbp; 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__rsp; 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# else 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__eip; 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__ebp; 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__esp; 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# endif // __WORDSIZE 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// No-op. Mac does not support static linkage anyway. 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return NULL; 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 624803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 634803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return (signum == SIGSEGV || signum == SIGBUS) && FLAG_handle_segv; 644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 66a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mmap(addr, length, prot, flags, fd, offset); 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 710ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanWrite(int fd, const void *buf, size_t count) { 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return write(fd, buf, count); 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 75de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 76de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 77de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 78de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 79de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 80de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 81de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 83de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 85de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 86a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 87a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 88a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 89a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 90a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 91a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 92a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 93a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size) { 94a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 95a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 96a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED, 97a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 98a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 99a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 100a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMprotect(uintptr_t fixed_addr, size_t size) { 101a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 102a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_NONE, 103a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 104a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 105a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 106a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 107de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid AsanUnmapOrDie(void *addr, size_t size) { 108de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (!addr || !size) return; 109de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany int res = munmap(addr, size); 110de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res != 0) { 111de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany Report("Failed to unmap\n"); 1120ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany AsanDie(); 113de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 114de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 115de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 116de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanOpenReadonly(const char* filename) { 117de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return open(filename, O_RDONLY); 118de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 119de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1201e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenkoconst char *AsanGetEnv(const char *name) { 1211e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko char ***env_ptr = _NSGetEnviron(); 1221e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko CHECK(env_ptr); 1231e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko char **environ = *env_ptr; 1241e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko CHECK(environ); 1251e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t name_len = internal_strlen(name); 1261e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko while (*environ != NULL) { 1271e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t len = internal_strlen(*environ); 1281e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (len > name_len) { 1291e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char *p = *environ; 1301e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (!internal_memcmp(p, name, name_len) && 1311e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko p[name_len] == '=') { // Match. 1321e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return *environ + name_len + 1; // String starting after =. 1331e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1341e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1351e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko environ++; 1361e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1371e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return NULL; 1381e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko} 1391e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko 1400ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanRead(int fd, void *buf, size_t count) { 141de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return read(fd, buf, count); 142de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 143de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 144de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 145de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return close(fd); 146de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 147de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 148c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 149c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = pthread_get_stacksize_np(pthread_self()); 150c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 151c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr; 152c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - stacksize; 153c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany int local; 154c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&local)); 155c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 156c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 157d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 158d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya SerebryanyAsanLock::AsanLock(LinkerInitialized) { 159d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // We assume that OS_SPINLOCK_INIT is zero 160d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 161d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 162d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Lock() { 163d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 164d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(OS_SPINLOCK_INIT == 0); 165d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ != (uintptr_t)pthread_self()); 166d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany OSSpinLockLock((OSSpinLock*)&opaque_storage_); 167d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(!owner_); 168d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = (uintptr_t)pthread_self(); 169d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 170d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 171d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Unlock() { 172d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ == (uintptr_t)pthread_self()); 173d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = 0; 174d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 175d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 176d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 1773281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// The range of pages to be used by __asan_mach_override_ptr for escape 1783281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// islands. 1793281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// TODO(glider): instead of mapping a fixed range we must find a range of 1803281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// unmapped pages in vmmap and take them. 1813281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define kIslandEnd (0x7fffffdf0000 - kPageSize) 1823281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define kIslandBeg (kIslandEnd - 256 * kPageSize) 1833281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 1843281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkoextern "C" 1853281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkomach_error_t __asan_allocate_island(void **ptr, 1863281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko size_t unused_size, 1873281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko void *unused_hint) { 1883281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko if (!island_allocator_pos) { 1893281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko if ((void*)-1 == asan_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg, 1903281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko PROT_READ | PROT_WRITE | PROT_EXEC, 1913281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko MAP_PRIVATE | MAP_ANON | MAP_FIXED, 1923281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko -1, 0)) { 1933281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return KERN_NO_SPACE; 1943281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko } 1953281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko island_allocator_pos = (void*)kIslandBeg; 1963281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko }; 1973281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko *ptr = island_allocator_pos; 1983281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko island_allocator_pos = (char*)island_allocator_pos + kPageSize; 1993281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return err_none; 2003281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko} 2013281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 2023281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkoextern "C" 2033281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkomach_error_t __asan_deallocate_island(void *ptr) { 2043281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko // Do nothing. 2053281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko // TODO(glider): allow to free and reuse the island memory. 2063281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return err_none; 2073281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko} 208d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Support for the following functions from libdispatch on Mac OS: 2101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async_f() 2111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async() 2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync_f() 2131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() 2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after_f() 2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after() 2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async_f() 2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async() 2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): libdispatch API contains other functions that we don't support 2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// yet. 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// they can cause jobs to run on a thread different from the current one. 2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): if so, we need a test for this (otherwise we should remove 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// them). 2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following functions use dispatch_barrier_async_f() (which isn't a library 2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// function but is exported) and are thus supported: 2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler_f() 2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler() 2301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler_f() 2311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler() 2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 2331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The reference manual for Grand Central Dispatch is available at 2341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html 2351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The implementation details are at 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c 2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid asan_dispatch_call_block_and_release(void *block) { 2401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *context = (asan_block_context_t*)block; 2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 2431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("asan_dispatch_call_block_and_release(): " 2441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "context: %p, pthread_self: %p\n", 2451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany block, pthread_self()); 2461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanThread *t = asanThreadRegistry().GetCurrent(); 248af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany if (!t) { 249af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany t = AsanThread::Create(context->parent_tid, NULL, NULL); 250a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack); 25169eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany t->Init(); 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asanThreadRegistry().SetCurrent(t); 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Call the original dispatcher for the block. 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany context->func(context->block); 2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(context, &stack); 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Wrap |ctxt| and |func| into an asan_block_context_t. 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The caller retains control of the allocated context. 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyasan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanStackTrace *stack) { 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); 2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = ctxt; 2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = func; 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_ctxt; 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): can we reduce code duplication by introducing a macro? 2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_async_f)(dispatch_queue_t dq, 2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 2831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_async_f(): context: %p, pthread_self: %p\n", 2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_async_f(dq, (void*)asan_ctxt, 2891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 2901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 2931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_sync_f)(dispatch_queue_t dq, 2941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 2971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 2981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 2991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_sync_f(): context: %p, pthread_self: %p\n", 3001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 3011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_sync_f(dq, (void*)asan_ctxt, 3041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 3051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_after_f)(dispatch_time_t when, 3091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_queue_t dq, 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 3121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 3141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_after_f: %p\n", asan_ctxt); 3161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_after_f(when, dq, (void*)asan_ctxt, 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid WRAP(dispatch_barrier_async_f)(dispatch_queue_t dq, 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, dispatch_function_t func) { 3251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_barrier_async_f(): context: %p, pthread_self: %p\n", 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_dispatch_barrier_async_f(dq, (void*)asan_ctxt, 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid WRAP(dispatch_group_async_f)(dispatch_group_t group, 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_queue_t dq, 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, dispatch_function_t func) { 3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n", 3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 3451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_dispatch_group_async_f(group, dq, (void*)asan_ctxt, 3481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 3491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following stuff has been extremely helpful while looking for the 3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// unhandled functions that spawned jobs on Chromium shutdown. If the verbosity 3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// level is 2 or greater, we wrap pthread_workqueue_additem_np() in order to 3541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// find the points of worker thread creation (each of such threads may be used 3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// to run several tasks, that's why this is not enough to support the whole 3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// libdispatch API. 3571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *wrap_workitem_func(void *arg) { 3591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("wrap_workitem_func: %p, pthread_self: %p\n", arg, pthread_self()); 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *ctxt = (asan_block_context_t*)arg; 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany worker_t fn = (worker_t)(ctxt->func); 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *result = fn(ctxt->block); 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(arg, &stack); 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return result; 3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq, 3721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *(*workitem_func)(void *), void * workitem_arg, 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp) { 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 3761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), &stack); 3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = workitem_arg; 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = (dispatch_function_t)workitem_func; 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("pthread_workqueue_additem_np: %p\n", asan_ctxt); 3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_pthread_workqueue_additem_np(workq, wrap_workitem_func, asan_ctxt, 3851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany itemhandlep, gencountp); 3861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 387d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 388d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 389