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