1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_mac.cc --------------------------------------------------===// 2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// 3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// The LLVM Compiler Infrastructure 4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// 5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source 6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details. 7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// 8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===// 9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// 102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is shared between various sanitizers' runtime libraries and 112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// implements OSX-specific functions. 12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===// 13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 1424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h" 1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC 16799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_mac.h" 1724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov 182bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so 192bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko// the clients will most certainly use 64-bit ones as well. 202bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#ifndef _DARWIN_USE_64_BIT_INODE 212bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#define _DARWIN_USE_64_BIT_INODE 1 222bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#endif 232bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#include <stdio.h> 24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 25e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common.h" 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h" 2794b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h" 28ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h" 297847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_placement_new.h" 30cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include "sanitizer_platform_limits_posix.h" 316895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h" 32ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 33799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if !SANITIZER_IOS 343dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov#include <crt_externs.h> // for _NSGetEnviron 35799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else 36799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarextern char **environ; 37799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 38799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if defined(__has_include) && __has_include(<os/trace.h>) 40799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define SANITIZER_OS_TRACE 1 41799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <os/trace.h> 42799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else 43799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#define SANITIZER_OS_TRACE 0 44799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 45799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 46799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if !SANITIZER_IOS 47799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron 48799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else 49799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarextern "C" { 50799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar extern char ***_NSGetArgv(void); 51799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 52799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 53799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 54799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <asl.h> 55799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <dlfcn.h> // for dladdr() 56cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include <errno.h> 57e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <fcntl.h> 58cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include <libkern/OSAtomic.h> 597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <mach-o/dyld.h> 60cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include <mach/mach.h> 61799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <mach/vm_statistics.h> 62e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 630969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <signal.h> 657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <stdlib.h> 66ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 67e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 68c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/sysctl.h> 70c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/types.h> 71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include <sys/wait.h> 72a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov#include <unistd.h> 73799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <util.h> 74ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 75c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// from <crt_externs.h>, but we don't have that file on iOS 76c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" { 77c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar extern char ***_NSGetArgv(void); 78c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar extern char ***_NSGetEnviron(void); 79c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 80c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 81ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 82ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 839578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc" 849578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne 85c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// Direct syscalls, don't call libmalloc hooks. 86c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes, 87c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar off_t off); 88c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" int __munmap(void *, size_t); 89c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 90e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ---------------------- sanitizer_libc.h 9165246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourneuptr internal_mmap(void *addr, size_t length, int prot, int flags, 9265246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourne int fd, u64 offset) { 93799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL); 94c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return (uptr)__mmap(addr, length, prot, flags, fd, offset); 95ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 96ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 9765246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourneuptr internal_munmap(void *addr, uptr length) { 98c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return __munmap(addr, length); 991f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 1001f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 101259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarint internal_mprotect(void *addr, uptr length, int prot) { 102259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return mprotect(addr, length, prot); 103259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 104259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 1059578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) { 106a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return close(fd); 107a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 108a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1099578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) { 110ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags); 111ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 112ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 1139578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) { 114ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags, mode); 115ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 116ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 117a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 118a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return read(fd, buf, count); 119a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 120a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 121a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 122a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return write(fd, buf, count); 123a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 124a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 1259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) { 1267c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return stat(path, (struct stat *)buf); 1274c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1284c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1299578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) { 1307c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return lstat(path, (struct stat *)buf); 1314c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1324c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1339578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) { 1347c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return fstat(fd, (struct stat *)buf); 1354c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 1364c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 1378e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 138668accc51f93df21fb0273d2ff10f7c86e757813Alexey Samsonov struct stat st; 1394c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 1408e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return -1; 1418e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 1428e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1438e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 1449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) { 1458e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return dup2(oldfd, newfd); 1468e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1478e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 148d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 149d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov return readlink(path, buf, bufsize); 150d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 151d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 15286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr internal_unlink(const char *path) { 15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return unlink(path); 15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 15586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 1569578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() { 1570969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return sched_yield(); 1580969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1590969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 160f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 161f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov _exit(exitcode); 162f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 163f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 164c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarunsigned int internal_sleep(unsigned int seconds) { 165c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return sleep(seconds); 166c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 167c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 1680b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourneuptr internal_getpid() { 1690b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne return getpid(); 1700b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne} 1710b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne 1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction(int signum, const void *act, void *oldact) { 1732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return sigaction(signum, 1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (struct sigaction *)act, (struct sigaction *)oldact); 1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 177cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarvoid internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); } 178cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar 179cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainaruptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 180cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar __sanitizer_sigset_t *oldset) { 181cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar return sigprocmask(how, set, oldset); 182cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar} 183cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar 184799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Doesn't call pthread_atfork() handlers. 185799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarextern "C" pid_t __fork(void); 186799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_fork() { 188799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return __fork(); 189799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 190799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 191799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarint internal_forkpty(int *amaster) { 192799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar int master, slave; 193799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; 194799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar int pid = __fork(); 195799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (pid == -1) { 196799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar close(master); 197799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar close(slave); 198799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return -1; 199799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 200799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (pid == 0) { 201799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar close(master); 202c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (login_tty(slave) != 0) { 203c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // We already forked, there's not much we can do. Let's quit. 204c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Report("login_tty failed (errno %d)\n", errno); 205c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar internal__exit(1); 206c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 207799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 208799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *amaster = master; 209799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar close(slave); 210799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 211799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return pid; 2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_rename(const char *oldpath, const char *newpath) { 2152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return rename(oldpath, newpath); 2162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr internal_ftruncate(fd_t fd, uptr size) { 2192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return ftruncate(fd, size); 2202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 2212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 222c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaruptr internal_execve(const char *filename, char *const argv[], 223c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar char *const envp[]) { 224c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return execve(filename, argv, envp); 225c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 226c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 227c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaruptr internal_waitpid(int pid, int *status, int options) { 228c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return waitpid(pid, status, options); 229c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 230c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 231e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 23293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 23393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 23493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (stat(filename, &st)) 23593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 23693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 23793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 23893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 23993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 240e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 241c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // FIXME: This can potentially get truncated on 32-bit, where uptr is 4 bytes. 242c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uint64_t tid; 243c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar pthread_threadid_np(nullptr, &tid); 244c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return tid; 245e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 246e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 247ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 248e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 249e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 250e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 251e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = pthread_get_stacksize_np(pthread_self()); 2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // pthread_get_stacksize_np() returns an incorrect stack size for the main 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // thread on Mavericks. See 254799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // https://github.com/google/sanitizers/issues/261 2556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization && 2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines stacksize == (1 << 19)) { 2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines struct rlimit rl; 2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Most often rl.rlim_cur will be the desired 8M. 2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (rl.rlim_cur < kMaxThreadStackSize) { 2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines stacksize = rl.rlim_cur; 2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines stacksize = kMaxThreadStackSize; 2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 266e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 267e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr; 268ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov *stack_bottom = *stack_top - stacksize; 269e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 270e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 271799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarchar **GetEnviron() { 272799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if !SANITIZER_IOS 2733dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char ***env_ptr = _NSGetEnviron(); 274b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko if (!env_ptr) { 275b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is " 276b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko "called after libSystem_initializer().\n"); 277b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko CHECK(env_ptr); 278b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko } 2793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char **environ = *env_ptr; 280799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 2813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov CHECK(environ); 282799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return environ; 283799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 284799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 285799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarconst char *GetEnv(const char *name) { 286799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char **env = GetEnviron(); 2873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr name_len = internal_strlen(name); 288799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar while (*env != 0) { 289799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr len = internal_strlen(*env); 2903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (len > name_len) { 291799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const char *p = *env; 2923dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!internal_memcmp(p, name, name_len) && 2933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p[name_len] == '=') { // Match. 294799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return *env + name_len + 1; // String starting after =. 2953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 297799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar env++; 2983dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 2993dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 3003dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 301e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 3027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainaruptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 3037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_LE(kMaxPathLength, buf_len); 3047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 3057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // On OS X the executable path is saved to the stack by dyld. Reading it 3067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // from there is much faster than calling dladdr, especially for large 3077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // binaries with symbols. 3087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar InternalScopedString exe_path(kMaxPathLength); 3097c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar uint32_t size = exe_path.size(); 3107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (_NSGetExecutablePath(exe_path.data(), &size) == 0 && 3117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar realpath(exe_path.data(), buf) != 0) { 3127c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return internal_strlen(buf); 3137c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 3147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return 0; 3157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 3167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 317799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainaruptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) { 318799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return ReadBinaryName(buf, buf_len); 319799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 320799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 321d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() { 322d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov UNIMPLEMENTED(); 323d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 324d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 3254df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() { 3264df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne return sysconf(_SC_PAGESIZE); 3274df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne} 3284df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne 32993af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 33093af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 33193af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 33293af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 333f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 334f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 335f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany CHECK_EQ(OS_SPINLOCK_INIT, 0); 336f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany CHECK_NE(owner_, (uptr)pthread_self()); 337f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockLock((OSSpinLock*)&opaque_storage_); 338f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(!owner_); 339f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = (uptr)pthread_self(); 340f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 341f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 342f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 343f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(owner_ == (uptr)pthread_self()); 344f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = 0; 345f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 346f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 347f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 348ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 349ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_EQ((uptr)pthread_self(), owner_); 350ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 351ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 352d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukovu64 NanoTime() { 353d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov return 0; 354d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov} 355d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov 356b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() { 357b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov return 0; 358b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 359b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 360b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() { 361b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 362b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 36324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 36424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev uptr *tls_addr, uptr *tls_size) { 3654a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#ifndef SANITIZER_GO 36624323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev uptr stack_top, stack_bottom; 36724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 36824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_addr = stack_bottom; 36924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *stk_size = stack_top - stack_bottom; 37024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_addr = 0; 37124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev *tls_size = 0; 3724a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#else 3734a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov *stk_addr = 0; 3744a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov *stk_size = 0; 3754a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov *tls_addr = 0; 3764a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov *tls_size = 0; 3774a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#endif 37824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev} 37924323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev 380c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid ListOfModules::init() { 381c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar clear(); 3827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov MemoryMappingLayout memory_mapping(false); 383c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar memory_mapping.DumpListOfModules(&modules_); 3842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 3852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 386c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool IsHandledDeadlySignal(int signum) { 387c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) 388c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // Handling fatal signals on watchOS and tvOS devices is disallowed. 389c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return false; 3902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv; 3912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 3922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesMacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; 3942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesMacosVersion GetMacosVersionInternal() { 3962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int mib[2] = { CTL_KERN, KERN_OSRELEASE }; 3972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char version[100]; 3982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); 3992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; 4002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Get the version length. 4012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1); 4022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_LT(len, maxlen); 4032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1); 4042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines switch (version[0]) { 4052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '9': return MACOS_VERSION_LEOPARD; 4062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '1': { 4072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines switch (version[1]) { 4082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '0': return MACOS_VERSION_SNOW_LEOPARD; 4092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '1': return MACOS_VERSION_LION; 4102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '2': return MACOS_VERSION_MOUNTAIN_LION; 4112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines case '3': return MACOS_VERSION_MAVERICKS; 4126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines case '4': return MACOS_VERSION_YOSEMITE; 41386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines default: 41486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (IsDigit(version[1])) 41586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return MACOS_VERSION_UNKNOWN_NEWER; 41686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines else 41786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return MACOS_VERSION_UNKNOWN; 4182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 4197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 4202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines default: return MACOS_VERSION_UNKNOWN; 4212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 4222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 4232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 4242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesMacosVersion GetMacosVersion() { 4252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_uint32_t *cache = 4262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines reinterpret_cast<atomic_uint32_t*>(&cached_macos_version); 4272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MacosVersion result = 4282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire)); 4292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (result == MACOS_VERSION_UNINITIALIZED) { 4302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines result = GetMacosVersionInternal(); 4312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_store(cache, result, memory_order_release); 4327847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 4332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return result; 4347847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 4357847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 43686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr GetRSS() { 437cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar struct task_basic_info info; 438cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar unsigned count = TASK_BASIC_INFO_COUNT; 439cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar kern_return_t result = 440cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count); 441cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar if (UNLIKELY(result != KERN_SUCCESS)) { 442cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar Report("Cannot get task info. Error: %d\n", result); 443cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar Die(); 444cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar } 445cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar return info.resident_size; 44686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 44786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 448799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *internal_start_thread(void(*func)(void *arg), void *arg) { 449799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Start the thread with signals blocked, otherwise it can steal user signals. 450799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar __sanitizer_sigset_t set, old; 451799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_sigfillset(&set); 452799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_sigprocmask(SIG_SETMASK, &set, &old); 453799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar pthread_t th; 454799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar pthread_create(&th, 0, (void*(*)(void *arg))func, arg); 455799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_sigprocmask(SIG_SETMASK, &old, 0); 456799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return th; 457799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 458799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 459799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); } 460799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 461c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef SANITIZER_GO 462799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic BlockingMutex syslog_lock(LINKER_INITIALIZED); 463c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif 464799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 465799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid WriteOneLineToSyslog(const char *s) { 466c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef SANITIZER_GO 467799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar syslog_lock.CheckLocked(); 468799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); 469c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif 470c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 471c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 472c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid LogMessageOnPrintf(const char *str) { 473c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // Log all printf output to CrashLog. 474c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (common_flags()->abort_on_error) 475c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar CRAppendCrashLogMessage(str); 476799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 477799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 478799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid LogFullErrorReport(const char *buffer) { 479c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef SANITIZER_GO 480799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Log with os_trace. This will make it into the crash log. 481799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_OS_TRACE 482799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { 483799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // os_trace requires the message (format parameter) to be a string literal. 484799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (internal_strncmp(SanitizerToolName, "AddressSanitizer", 485799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar sizeof("AddressSanitizer") - 1) == 0) 486799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar os_trace("Address Sanitizer reported a failure."); 487799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", 488799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar sizeof("UndefinedBehaviorSanitizer") - 1) == 0) 489799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar os_trace("Undefined Behavior Sanitizer reported a failure."); 490799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", 491799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar sizeof("ThreadSanitizer") - 1) == 0) 492799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar os_trace("Thread Sanitizer reported a failure."); 493799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar else 494799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar os_trace("Sanitizer tool reported a failure."); 495799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 496799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (common_flags()->log_to_syslog) 497799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar os_trace("Consult syslog for more information."); 498799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 499799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 500799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 501799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Log to syslog. 502799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // The logging on OS X may call pthread_create so we need the threading 503799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // environment to be fully initialized. Also, this should never be called when 504799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // holding the thread registry lock since that may result in a deadlock. If 505799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // the reporting thread holds the thread registry mutex, and asl_log waits 506799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // for GCD to dispatch a new thread, the process will deadlock, because the 507799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // pthread_create wrapper needs to acquire the lock as well. 508799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar BlockingMutexLock l(&syslog_lock); 509799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (common_flags()->log_to_syslog) 510799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar WriteToSyslog(buffer); 511799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 512c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // The report is added to CrashLog as part of logging all of Printf output. 513c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif 514c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 515c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 516c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarSignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) { 517c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#if defined(__x86_64__) || defined(__i386__) 518c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar ucontext_t *ucontext = static_cast<ucontext_t*>(context); 519c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ; 520c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#else 521c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return UNKNOWN; 522c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif 523799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 52486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 5257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarvoid GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 5267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ucontext_t *ucontext = (ucontext_t*)context; 527799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# if defined(__aarch64__) 528799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *pc = ucontext->uc_mcontext->__ss.__pc; 529799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 530799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *bp = ucontext->uc_mcontext->__ss.__fp; 531799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# else 532799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *bp = ucontext->uc_mcontext->__ss.__lr; 533799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# endif 534799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *sp = ucontext->uc_mcontext->__ss.__sp; 535799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# elif defined(__x86_64__) 5367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext->__ss.__rip; 5377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext->__ss.__rbp; 5387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext->__ss.__rsp; 539799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# elif defined(__arm__) 540799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *pc = ucontext->uc_mcontext->__ss.__pc; 541799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *bp = ucontext->uc_mcontext->__ss.__r[7]; 542799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *sp = ucontext->uc_mcontext->__ss.__sp; 543799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# elif defined(__i386__) 5447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *pc = ucontext->uc_mcontext->__ss.__eip; 5457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *bp = ucontext->uc_mcontext->__ss.__ebp; 5467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *sp = ucontext->uc_mcontext->__ss.__esp; 547799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# else 548799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# error "Unknown architecture" 549799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar# endif 550799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 551799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 552c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#ifndef SANITIZER_GO 553799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 554799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarLowLevelAllocator allocator_for_env; 555799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 556799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Change the value of the env var |name|, leaking the original value. 557799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// If |name_value| is NULL, the variable is deleted from the environment, 558799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// otherwise the corresponding "NAME=value" string is replaced with 559799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// |name_value|. 560799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid LeakyResetEnv(const char *name, const char *name_value) { 561799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char **env = GetEnviron(); 562799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr name_len = internal_strlen(name); 563799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar while (*env != 0) { 564799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr len = internal_strlen(*env); 565799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (len > name_len) { 566799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const char *p = *env; 567799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { 568799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Match. 569799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (name_value) { 570799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Replace the old value with the new one. 571799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *env = const_cast<char*>(name_value); 572799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 573799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Shift the subsequent pointers back. 574799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char **del = env; 575799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar do { 576799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar del[0] = del[1]; 577799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } while (*del++); 578799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 579799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 580799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 581799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar env++; 582799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 583799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 584799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 585c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga NainarSANITIZER_WEAK_CXX_DEFAULT_IMPL 586c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool ReexecDisabled() { 587c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return false; 588799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 589799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 590c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarextern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber; 591799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic const double kMinDyldVersionWithAutoInterposition = 360.0; 592799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 593799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarbool DyldNeedsEnvVariable() { 594c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users 595c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // still may want use them on older systems. On older Darwin platforms, dyld 596c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // doesn't export dyldVersionNumber symbol and we simply return true. 597c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (!&dyldVersionNumber) return true; 598799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if 599799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via 600799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // GetMacosVersion() doesn't work for the simulator. Let's instead check 601799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // `dyldVersionNumber`, which is exported by dyld, against a known version 602799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // number from the first OS release where this appeared. 603799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; 604799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 605799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 606799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid MaybeReexec() { 607c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (ReexecDisabled()) return; 608799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 609799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Make sure the dynamic runtime library is preloaded so that the 610799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec 611799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // ourselves. 612799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Dl_info info; 613c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info)); 614799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *dyld_insert_libraries = 615799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const_cast<char*>(GetEnv(kDyldInsertLibraries)); 616799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr old_env_len = dyld_insert_libraries ? 617799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strlen(dyld_insert_libraries) : 0; 618799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr fname_len = internal_strlen(info.dli_fname); 619799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const char *dylib_name = StripModuleName(info.dli_fname); 620799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr dylib_name_len = internal_strlen(dylib_name); 621799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 622799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar bool lib_is_in_env = dyld_insert_libraries && 623799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strstr(dyld_insert_libraries, dylib_name); 624799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (DyldNeedsEnvVariable() && !lib_is_in_env) { 625799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime 626799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // library. 627799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar InternalScopedString program_name(1024); 628799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uint32_t buf_size = program_name.size(); 629799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar _NSGetExecutablePath(program_name.data(), &buf_size); 630799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *new_env = const_cast<char*>(info.dli_fname); 631799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (dyld_insert_libraries) { 632799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Append the runtime dylib name to the existing value of 633799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // DYLD_INSERT_LIBRARIES. 634799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); 635799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strncpy(new_env, dyld_insert_libraries, old_env_len); 636799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env[old_env_len] = ':'; 637799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Copy fname_len and add a trailing zero. 638799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strncpy(new_env + old_env_len + 1, info.dli_fname, 639799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar fname_len + 1); 640799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Ok to use setenv() since the wrappers don't depend on the value of 641799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // asan_inited. 642799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); 643799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 644799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. 645799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); 646799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 647799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar VReport(1, "exec()-ing the program with\n"); 648799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); 649799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar VReport(1, "to enable wrappers.\n"); 650799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar execv(program_name.data(), *_NSGetArgv()); 651799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 652799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // We get here only if execv() failed. 653799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " 654799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "which is required for the sanitizer to work. We tried to set the " 655799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "environment variable and re-execute itself, but execv() failed, " 656799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "possibly because of sandbox restrictions. Make sure to launch the " 657799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); 658c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar RAW_CHECK("execv failed" && 0); 659c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 660c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 661c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // Verify that interceptors really work. We'll use dlsym to locate 662c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // "pthread_create", if interceptors are working, it should really point to 663c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // "wrap_pthread_create" within our own dylib. 664c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Dl_info info_pthread_create; 665c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create"); 666c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create)); 667c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) { 668c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Report( 669c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar "ERROR: Interceptors are not working. This may be because %s is " 670c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar "loaded too late (e.g. via dlopen). Please launch the executable " 671c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar "with:\n%s=%s\n", 672c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar SanitizerToolName, kDyldInsertLibraries, info.dli_fname); 673c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar RAW_CHECK("interceptors not installed" && 0); 674799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 675799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 676799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (!lib_is_in_env) 677799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return; 678799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 679799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove 680799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // the dylib from the environment variable, because interceptors are installed 681799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // and we don't want our children to inherit the variable. 682799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 683799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr env_name_len = internal_strlen(kDyldInsertLibraries); 684799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Allocate memory to hold the previous env var name, its value, the '=' 685799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // sign and the '\0' char. 686799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *new_env = (char*)allocator_for_env.Allocate( 687799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar old_env_len + 2 + env_name_len); 688c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar RAW_CHECK(new_env); 689799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); 690799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); 691799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env[env_name_len] = '='; 692799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *new_env_pos = new_env + env_name_len + 1; 693799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 694799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Iterate over colon-separated pieces of |dyld_insert_libraries|. 695799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *piece_start = dyld_insert_libraries; 696799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *piece_end = NULL; 697799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *old_env_end = dyld_insert_libraries + old_env_len; 698799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar do { 699799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (piece_start[0] == ':') piece_start++; 700799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar piece_end = internal_strchr(piece_start, ':'); 701799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; 702799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; 703799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr piece_len = piece_end - piece_start; 704799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 705799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *filename_start = 706799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (char *)internal_memrchr(piece_start, '/', piece_len); 707799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr filename_len = piece_len; 708799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (filename_start) { 709799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar filename_start += 1; 710799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar filename_len = piece_len - (filename_start - piece_start); 711799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 712799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar filename_start = piece_start; 713799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 714799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 715799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // If the current piece isn't the runtime library name, 716799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // append it to new_env. 717799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if ((dylib_name_len != filename_len) || 718799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { 719799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (new_env_pos != new_env + env_name_len + 1) { 720799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env_pos[0] = ':'; 721799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env_pos++; 722799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 723799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar internal_strncpy(new_env_pos, piece_start, piece_len); 724799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar new_env_pos += piece_len; 725799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 726799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Move on to the next piece. 727799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar piece_start = piece_end; 728799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } while (piece_start < old_env_end); 729799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 730799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Can't use setenv() here, because it requires the allocator to be 731799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // initialized. 732799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in 733799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // a separate function called after InitializeAllocator(). 734799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; 735799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar LeakyResetEnv(kDyldInsertLibraries, new_env); 7367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 737c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif // SANITIZER_GO 738c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 739c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarchar **GetArgv() { 740c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return *_NSGetArgv(); 741c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} 7427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 743ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 744ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 74546f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif // SANITIZER_MAC 746