asan_mac.cc revision 8a34d384255f9bf4c2a9b03a4df81b9af57124d8
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" 208a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#include "asan_procmaps.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread_registry.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 251e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko#include <crt_externs.h> // for _NSGetEnviron 268a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#include <mach-o/dyld.h> 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 28ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany#include <sys/resource.h> 299107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany#include <sys/ucontext.h> 30c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 31a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany#include <fcntl.h> 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 33d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany#include <libkern/OSAtomic.h> 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 373281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkovoid *island_allocator_pos = NULL; 383281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_async_f_f real_dispatch_async_f; 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_sync_f_f real_dispatch_sync_f; 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_after_f_f real_dispatch_after_f; 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_barrier_async_f_f real_dispatch_barrier_async_f; 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern dispatch_group_async_f_f real_dispatch_group_async_f; 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np; 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 469107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryanyvoid GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { 479107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany ucontext_t *ucontext = (ucontext_t*)context; 489107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# if __WORDSIZE == 64 499107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__rip; 509107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__rbp; 519107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__rsp; 529107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# else 539107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *pc = ucontext->uc_mcontext->__ss.__eip; 549107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *bp = ucontext->uc_mcontext->__ss.__ebp; 559107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany *sp = ucontext->uc_mcontext->__ss.__esp; 569107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany# endif // __WORDSIZE 579107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany} 589107c26bd88fc9cf44a2cd7d6967eb830ac63be3Kostya Serebryany 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// No-op. Mac does not support static linkage anyway. 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return NULL; 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanybool AsanInterceptsSignal(int signum) { 654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return (signum == SIGSEGV || signum == SIGBUS) && FLAG_handle_segv; 664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 68a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mmap(addr, length, prot, flags, fd, offset); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 730ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanWrite(int fd, const void *buf, size_t count) { 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return write(fd, buf, count); 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 77de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 78de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 79de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 80de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 81de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 83de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 85de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 86de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 87de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 88a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 89a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 90a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 91a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 92a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 93a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 94a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 95a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size) { 96a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 97a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 98a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED, 99a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 100a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 101a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 102a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMprotect(uintptr_t fixed_addr, size_t size) { 103a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 104a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_NONE, 105a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 106a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 107a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 108a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 109de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid AsanUnmapOrDie(void *addr, size_t size) { 110de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (!addr || !size) return; 111de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany int res = munmap(addr, size); 112de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res != 0) { 113de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany Report("Failed to unmap\n"); 1140ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany AsanDie(); 115de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 116de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 117de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 118de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanOpenReadonly(const char* filename) { 119de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return open(filename, O_RDONLY); 120de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 121de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1221e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenkoconst char *AsanGetEnv(const char *name) { 1231e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko char ***env_ptr = _NSGetEnviron(); 1241e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko CHECK(env_ptr); 1251e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko char **environ = *env_ptr; 1261e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko CHECK(environ); 1271e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t name_len = internal_strlen(name); 1281e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko while (*environ != NULL) { 1291e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko size_t len = internal_strlen(*environ); 1301e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (len > name_len) { 1311e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko const char *p = *environ; 1321e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko if (!internal_memcmp(p, name, name_len) && 1331e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko p[name_len] == '=') { // Match. 1344dd8ba8238b1b698953628affe6e5b2edf3b3e3fAlexey Samsonov return *environ + name_len + 1; // String starting after =. 1351e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1361e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1371e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko environ++; 1381e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko } 1391e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko return NULL; 1401e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko} 1411e316d7f488a75312539629e9d937e156280eeb6Alexander Potapenko 1420ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryanysize_t AsanRead(int fd, void *buf, size_t count) { 143de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return read(fd, buf, count); 144de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 145de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 146de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 147de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return close(fd); 148de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 149de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 1508a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander PotapenkoAsanProcMaps::AsanProcMaps() { 1518a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko Reset(); 1528a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 1538a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 1548a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander PotapenkoAsanProcMaps::~AsanProcMaps() { 1558a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 1568a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 1578a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenkovoid AsanProcMaps::Reset() { 1588a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // Count down from the top. 1598a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // TODO(glider): as per man 3 dyld, iterating over the headers with 1608a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // _dyld_image_count is thread-unsafe. 1618a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko current_image_ = _dyld_image_count(); 1628a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko current_load_cmd_ = -1; 1638a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 1648a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 1658a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko// Similar code is used in Google Perftools, 1668a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko// http://code.google.com/p/google-perftools. 1678a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenkotemplate<uint32_t kMagic, uint32_t kLCSegment, 1688a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko typename MachHeader, typename SegmentCommand> 1698a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenkostatic bool NextExtMachHelper(const mach_header* hdr, 1708a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko int current_image, int current_load_cmd, 1718a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko uintptr_t *start, uintptr_t *end, 1728a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko uintptr_t *offset, 1738a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko char filename[], size_t filename_size) { 1748a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (hdr->magic != kMagic) 1758a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return false; 1768a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko const char* lc = (const char *)hdr + sizeof(MachHeader); 1778a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // TODO(csilvers): make this not-quadradic (increment and hold state) 1788a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko for (int j = 0; j < current_load_cmd; j++) // advance to *our* load_cmd 1798a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko lc += ((const load_command *)lc)->cmdsize; 1808a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (((const load_command *)lc)->cmd == kLCSegment) { 1818a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image); 1828a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko const SegmentCommand* sc = (const SegmentCommand *)lc; 1838a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (start) *start = sc->vmaddr + dlloff; 1848a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (end) *end = sc->vmaddr + sc->vmsize + dlloff; 1858a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (offset) *offset = sc->fileoff; 1868a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (filename) { 1878a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko real_strncpy(filename, _dyld_get_image_name(current_image), 1888a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko filename_size); 1898a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 1908a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return true; 1918a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 1928a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return false; 1938a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 1948a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 1958a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenkobool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end, 1968a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko uintptr_t *offset, char filename[], 1978a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko size_t filename_size) { 1988a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // We return a separate entry for each segment in the DLL. (TODO(csilvers): 1998a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // can we do better?) A DLL ("image") has load-commands, some of which 2008a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // talk about segment boundaries. 2018a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // cf image_for_address from http://svn.digium.com/view/asterisk/team/oej/minivoicemail/dlfcn.c?revision=53912 2028a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko for (; current_image_ >= 0; current_image_--) { 2038a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko const mach_header* hdr = _dyld_get_image_header(current_image_); 2048a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (!hdr) continue; 2058a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (current_load_cmd_ < 0) // set up for this image 2068a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko current_load_cmd_ = hdr->ncmds; // again, go from the top down 2078a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 2088a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // We start with the next load command (we've already looked at this one). 2098a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) { 2108a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#ifdef MH_MAGIC_64 2118a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (NextExtMachHelper<MH_MAGIC_64, LC_SEGMENT_64, 2128a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko struct mach_header_64, struct segment_command_64>( 2138a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko hdr, current_image_, current_load_cmd_, 2148a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko start, end, offset, filename, filename_size)) { 2158a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return true; 2168a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 2178a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko#endif 2188a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko if (NextExtMachHelper<MH_MAGIC, LC_SEGMENT, 2198a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko struct mach_header, struct segment_command>( 2208a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko hdr, current_image_, current_load_cmd_, 2218a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko start, end, offset, filename, filename_size)) { 2228a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return true; 2238a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 2248a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 2258a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // If we get here, no more load_cmd's in this image talk about 2268a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // segments. Go on to the next image. 2278a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko } 2288a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko // We didn't find anything. 2298a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return false; 2308a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 2318a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 2328a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenkobool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 2338a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko char filename[], 2348a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko size_t filename_size) { 2358a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); 2368a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko} 2378a34d384255f9bf4c2a9b03a4df81b9af57124d8Alexander Potapenko 238c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 239c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = pthread_get_stacksize_np(pthread_self()); 240c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 241c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr; 242c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - stacksize; 243c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany int local; 244c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&local)); 245c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 246c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 247d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya SerebryanyAsanLock::AsanLock(LinkerInitialized) { 248d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany // We assume that OS_SPINLOCK_INIT is zero 249d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 250d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 251d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Lock() { 252d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 253d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(OS_SPINLOCK_INIT == 0); 254d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ != (uintptr_t)pthread_self()); 255d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany OSSpinLockLock((OSSpinLock*)&opaque_storage_); 256d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(!owner_); 257d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = (uintptr_t)pthread_self(); 258d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 259d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 260d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryanyvoid AsanLock::Unlock() { 261d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany CHECK(owner_ == (uintptr_t)pthread_self()); 262d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany owner_ = 0; 263d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 264d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany} 265d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 2663281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// The range of pages to be used by __asan_mach_override_ptr for escape 2673281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// islands. 2683281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// TODO(glider): instead of mapping a fixed range we must find a range of 2693281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko// unmapped pages in vmmap and take them. 2701346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko// These constants were chosen empirically and may not work if the shadow 2711346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko// memory layout changes. Unfortunately they do necessarily depend on 2721346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko// kHighMemBeg or kHighMemEnd. 2731346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko#if __WORDSIZE == 32 2741346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko#define kIslandEnd (0xffdf0000 - kPageSize) 2751346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko#define kIslandBeg (kIslandEnd - 256 * kPageSize) 2761346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko#else 2773281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define kIslandEnd (0x7fffffdf0000 - kPageSize) 2783281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko#define kIslandBeg (kIslandEnd - 256 * kPageSize) 2791346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko#endif 2803281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 2813281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkoextern "C" 2823281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkomach_error_t __asan_allocate_island(void **ptr, 2833281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko size_t unused_size, 2843281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko void *unused_hint) { 2853281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko if (!island_allocator_pos) { 2861346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko island_allocator_pos = 2871346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko asan_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg, 2881346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko PROT_READ | PROT_WRITE | PROT_EXEC, 2891346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko MAP_PRIVATE | MAP_ANON | MAP_FIXED, 2901346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko -1, 0); 2911346ced2eb8d10305e8d98496d9006cfbbad1548Alexander Potapenko if (island_allocator_pos != (void*)kIslandBeg) { 2923281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return KERN_NO_SPACE; 2933281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko } 2943281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko }; 2953281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko *ptr = island_allocator_pos; 2963281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko island_allocator_pos = (char*)island_allocator_pos + kPageSize; 2973281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return err_none; 2983281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko} 2993281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko 3003281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkoextern "C" 3013281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenkomach_error_t __asan_deallocate_island(void *ptr) { 3023281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko // Do nothing. 3033281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko // TODO(glider): allow to free and reuse the island memory. 3043281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko return err_none; 3053281209790b5e543c79acb2f5008d1df77fb76d9Alexander Potapenko} 306d55f5f8c413622db4bd28b5cca9bfeb4d61564e0Kostya Serebryany 3071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Support for the following functions from libdispatch on Mac OS: 3081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async_f() 3091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_async() 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync_f() 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() 3121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after_f() 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_after() 3141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async_f() 3151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_group_async() 3161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): libdispatch API contains other functions that we don't support 3171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// yet. 3181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// they can cause jobs to run on a thread different from the current one. 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): if so, we need a test for this (otherwise we should remove 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// them). 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following functions use dispatch_barrier_async_f() (which isn't a library 3251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// function but is exported) and are thus supported: 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler_f() 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_cancel_handler() 3281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler_f() 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// dispatch_source_set_event_handler() 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The reference manual for Grand Central Dispatch is available at 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The implementation details are at 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid asan_dispatch_call_block_and_release(void *block) { 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *context = (asan_block_context_t*)block; 3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("asan_dispatch_call_block_and_release(): " 3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "context: %p, pthread_self: %p\n", 3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany block, pthread_self()); 3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanThread *t = asanThreadRegistry().GetCurrent(); 346af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany if (!t) { 34755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov t = AsanThread::Create(context->parent_tid, NULL, NULL, &stack); 34855cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov asanThreadRegistry().RegisterThread(t); 34969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany t->Init(); 3501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asanThreadRegistry().SetCurrent(t); 3511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Call the original dispatcher for the block. 3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany context->func(context->block); 3541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(context, &stack); 3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 3581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 3601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Wrap |ctxt| and |func| into an asan_block_context_t. 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The caller retains control of the allocated context. 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyasan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanStackTrace *stack) { 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); 3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = ctxt; 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = func; 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_ctxt; 3721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): can we reduce code duplication by introducing a macro? 3751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_async_f)(dispatch_queue_t dq, 3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_async_f(): context: %p, pthread_self: %p\n", 3831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 3841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 3851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_async_f(dq, (void*)asan_ctxt, 3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 3911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_sync_f)(dispatch_queue_t dq, 3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 3931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 3951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_sync_f(): context: %p, pthread_self: %p\n", 3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_sync_f(dq, (void*)asan_ctxt, 4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 4061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(dispatch_after_f)(dispatch_time_t when, 4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_queue_t dq, 4081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, 4091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_function_t func) { 4101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 4131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_after_f: %p\n", asan_ctxt); 4141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 4151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_dispatch_after_f(when, dq, (void*)asan_ctxt, 4171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 4181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid WRAP(dispatch_barrier_async_f)(dispatch_queue_t dq, 4221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, dispatch_function_t func) { 4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 4251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 4261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_barrier_async_f(): context: %p, pthread_self: %p\n", 4271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 4281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 4291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_dispatch_barrier_async_f(dq, (void*)asan_ctxt, 4311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 4321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 4351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid WRAP(dispatch_group_async_f)(dispatch_group_t group, 4361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany dispatch_queue_t dq, 4371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *ctxt, dispatch_function_t func) { 4381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); 4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 4411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n", 4421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt, pthread_self()); 4431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_dispatch_group_async_f(group, dq, (void*)asan_ctxt, 4461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_dispatch_call_block_and_release); 4471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The following stuff has been extremely helpful while looking for the 4501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// unhandled functions that spawned jobs on Chromium shutdown. If the verbosity 4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// level is 2 or greater, we wrap pthread_workqueue_additem_np() in order to 4521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// find the points of worker thread creation (each of such threads may be used 4531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// to run several tasks, that's why this is not enough to support the whole 4541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// libdispatch API. 4551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 4561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *wrap_workitem_func(void *arg) { 4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("wrap_workitem_func: %p, pthread_self: %p\n", arg, pthread_self()); 4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *ctxt = (asan_block_context_t*)arg; 4611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany worker_t fn = (worker_t)(ctxt->func); 4621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *result = fn(ctxt->block); 4631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 4641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(arg, &stack); 4651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return result; 4661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 4691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyint WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq, 4701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *(*workitem_func)(void *), void * workitem_arg, 4711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp) { 4721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); 4731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_block_context_t *asan_ctxt = 4741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), &stack); 4751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->block = workitem_arg; 4761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->func = (dispatch_function_t)workitem_func; 4771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 4781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 2) { 4791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("pthread_workqueue_additem_np: %p\n", asan_ctxt); 4801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany PRINT_CURRENT_STACK(); 4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return real_pthread_workqueue_additem_np(workq, wrap_workitem_func, asan_ctxt, 4831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany itemhandlep, gencountp); 4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 485d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 486d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 487