1*490215a3Smrg //===-- sanitizer_mac.cc --------------------------------------------------===//
2*490215a3Smrg //
3*490215a3Smrg // This file is distributed under the University of Illinois Open Source
4*490215a3Smrg // License. See LICENSE.TXT for details.
5*490215a3Smrg //
6*490215a3Smrg //===----------------------------------------------------------------------===//
7*490215a3Smrg //
8*490215a3Smrg // This file is shared between various sanitizers' runtime libraries and
9*490215a3Smrg // implements OSX-specific functions.
10*490215a3Smrg //===----------------------------------------------------------------------===//
11*490215a3Smrg 
12*490215a3Smrg #include "sanitizer_platform.h"
13*490215a3Smrg #if SANITIZER_MAC
14*490215a3Smrg #include "sanitizer_mac.h"
15*490215a3Smrg 
16*490215a3Smrg // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
17*490215a3Smrg // the clients will most certainly use 64-bit ones as well.
18*490215a3Smrg #ifndef _DARWIN_USE_64_BIT_INODE
19*490215a3Smrg #define _DARWIN_USE_64_BIT_INODE 1
20*490215a3Smrg #endif
21*490215a3Smrg #include <stdio.h>
22*490215a3Smrg 
23*490215a3Smrg #include "sanitizer_common.h"
24*490215a3Smrg #include "sanitizer_file.h"
25*490215a3Smrg #include "sanitizer_flags.h"
26*490215a3Smrg #include "sanitizer_internal_defs.h"
27*490215a3Smrg #include "sanitizer_libc.h"
28*490215a3Smrg #include "sanitizer_placement_new.h"
29*490215a3Smrg #include "sanitizer_platform_limits_posix.h"
30*490215a3Smrg #include "sanitizer_procmaps.h"
31*490215a3Smrg 
32*490215a3Smrg #if !SANITIZER_IOS
33*490215a3Smrg #include <crt_externs.h>  // for _NSGetEnviron
34*490215a3Smrg #else
35*490215a3Smrg extern char **environ;
36*490215a3Smrg #endif
37*490215a3Smrg 
38*490215a3Smrg #if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
39*490215a3Smrg #define SANITIZER_OS_TRACE 1
40*490215a3Smrg #include <os/trace.h>
41*490215a3Smrg #else
42*490215a3Smrg #define SANITIZER_OS_TRACE 0
43*490215a3Smrg #endif
44*490215a3Smrg 
45*490215a3Smrg #if !SANITIZER_IOS
46*490215a3Smrg #include <crt_externs.h>  // for _NSGetArgv and _NSGetEnviron
47*490215a3Smrg #else
48*490215a3Smrg extern "C" {
49*490215a3Smrg   extern char ***_NSGetArgv(void);
50*490215a3Smrg }
51*490215a3Smrg #endif
52*490215a3Smrg 
53*490215a3Smrg #include <asl.h>
54*490215a3Smrg #include <dlfcn.h>  // for dladdr()
55*490215a3Smrg #include <errno.h>
56*490215a3Smrg #include <fcntl.h>
57*490215a3Smrg #include <libkern/OSAtomic.h>
58*490215a3Smrg #include <mach-o/dyld.h>
59*490215a3Smrg #include <mach/mach.h>
60*490215a3Smrg #include <mach/mach_time.h>
61*490215a3Smrg #include <mach/vm_statistics.h>
62*490215a3Smrg #include <malloc/malloc.h>
63*490215a3Smrg #include <pthread.h>
64*490215a3Smrg #include <sched.h>
65*490215a3Smrg #include <signal.h>
66*490215a3Smrg #include <stdlib.h>
67*490215a3Smrg #include <sys/mman.h>
68*490215a3Smrg #include <sys/resource.h>
69*490215a3Smrg #include <sys/stat.h>
70*490215a3Smrg #include <sys/sysctl.h>
71*490215a3Smrg #include <sys/types.h>
72*490215a3Smrg #include <sys/wait.h>
73*490215a3Smrg #include <unistd.h>
74*490215a3Smrg #include <util.h>
75*490215a3Smrg 
76*490215a3Smrg // From <crt_externs.h>, but we don't have that file on iOS.
77*490215a3Smrg extern "C" {
78*490215a3Smrg   extern char ***_NSGetArgv(void);
79*490215a3Smrg   extern char ***_NSGetEnviron(void);
80*490215a3Smrg }
81*490215a3Smrg 
82*490215a3Smrg // From <mach/mach_vm.h>, but we don't have that file on iOS.
83*490215a3Smrg extern "C" {
84*490215a3Smrg   extern kern_return_t mach_vm_region_recurse(
85*490215a3Smrg     vm_map_t target_task,
86*490215a3Smrg     mach_vm_address_t *address,
87*490215a3Smrg     mach_vm_size_t *size,
88*490215a3Smrg     natural_t *nesting_depth,
89*490215a3Smrg     vm_region_recurse_info_t info,
90*490215a3Smrg     mach_msg_type_number_t *infoCnt);
91*490215a3Smrg }
92*490215a3Smrg 
93*490215a3Smrg namespace __sanitizer {
94*490215a3Smrg 
95*490215a3Smrg #include "sanitizer_syscall_generic.inc"
96*490215a3Smrg 
97*490215a3Smrg // Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
98*490215a3Smrg extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes,
99*490215a3Smrg                         off_t off) SANITIZER_WEAK_ATTRIBUTE;
100*490215a3Smrg extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
101*490215a3Smrg 
102*490215a3Smrg // ---------------------- sanitizer_libc.h
103*490215a3Smrg 
104*490215a3Smrg // From <mach/vm_statistics.h>, but not on older OSs.
105*490215a3Smrg #ifndef VM_MEMORY_SANITIZER
106*490215a3Smrg #define VM_MEMORY_SANITIZER 99
107*490215a3Smrg #endif
108*490215a3Smrg 
internal_mmap(void * addr,size_t length,int prot,int flags,int fd,u64 offset)109*490215a3Smrg uptr internal_mmap(void *addr, size_t length, int prot, int flags,
110*490215a3Smrg                    int fd, u64 offset) {
111*490215a3Smrg   if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER);
112*490215a3Smrg   if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset);
113*490215a3Smrg   return (uptr)mmap(addr, length, prot, flags, fd, offset);
114*490215a3Smrg }
115*490215a3Smrg 
internal_munmap(void * addr,uptr length)116*490215a3Smrg uptr internal_munmap(void *addr, uptr length) {
117*490215a3Smrg   if (&__munmap) return __munmap(addr, length);
118*490215a3Smrg   return munmap(addr, length);
119*490215a3Smrg }
120*490215a3Smrg 
internal_mprotect(void * addr,uptr length,int prot)121*490215a3Smrg int internal_mprotect(void *addr, uptr length, int prot) {
122*490215a3Smrg   return mprotect(addr, length, prot);
123*490215a3Smrg }
124*490215a3Smrg 
internal_close(fd_t fd)125*490215a3Smrg uptr internal_close(fd_t fd) {
126*490215a3Smrg   return close(fd);
127*490215a3Smrg }
128*490215a3Smrg 
internal_open(const char * filename,int flags)129*490215a3Smrg uptr internal_open(const char *filename, int flags) {
130*490215a3Smrg   return open(filename, flags);
131*490215a3Smrg }
132*490215a3Smrg 
internal_open(const char * filename,int flags,u32 mode)133*490215a3Smrg uptr internal_open(const char *filename, int flags, u32 mode) {
134*490215a3Smrg   return open(filename, flags, mode);
135*490215a3Smrg }
136*490215a3Smrg 
internal_read(fd_t fd,void * buf,uptr count)137*490215a3Smrg uptr internal_read(fd_t fd, void *buf, uptr count) {
138*490215a3Smrg   return read(fd, buf, count);
139*490215a3Smrg }
140*490215a3Smrg 
internal_write(fd_t fd,const void * buf,uptr count)141*490215a3Smrg uptr internal_write(fd_t fd, const void *buf, uptr count) {
142*490215a3Smrg   return write(fd, buf, count);
143*490215a3Smrg }
144*490215a3Smrg 
internal_stat(const char * path,void * buf)145*490215a3Smrg uptr internal_stat(const char *path, void *buf) {
146*490215a3Smrg   return stat(path, (struct stat *)buf);
147*490215a3Smrg }
148*490215a3Smrg 
internal_lstat(const char * path,void * buf)149*490215a3Smrg uptr internal_lstat(const char *path, void *buf) {
150*490215a3Smrg   return lstat(path, (struct stat *)buf);
151*490215a3Smrg }
152*490215a3Smrg 
internal_fstat(fd_t fd,void * buf)153*490215a3Smrg uptr internal_fstat(fd_t fd, void *buf) {
154*490215a3Smrg   return fstat(fd, (struct stat *)buf);
155*490215a3Smrg }
156*490215a3Smrg 
internal_filesize(fd_t fd)157*490215a3Smrg uptr internal_filesize(fd_t fd) {
158*490215a3Smrg   struct stat st;
159*490215a3Smrg   if (internal_fstat(fd, &st))
160*490215a3Smrg     return -1;
161*490215a3Smrg   return (uptr)st.st_size;
162*490215a3Smrg }
163*490215a3Smrg 
internal_dup2(int oldfd,int newfd)164*490215a3Smrg uptr internal_dup2(int oldfd, int newfd) {
165*490215a3Smrg   return dup2(oldfd, newfd);
166*490215a3Smrg }
167*490215a3Smrg 
internal_readlink(const char * path,char * buf,uptr bufsize)168*490215a3Smrg uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
169*490215a3Smrg   return readlink(path, buf, bufsize);
170*490215a3Smrg }
171*490215a3Smrg 
internal_unlink(const char * path)172*490215a3Smrg uptr internal_unlink(const char *path) {
173*490215a3Smrg   return unlink(path);
174*490215a3Smrg }
175*490215a3Smrg 
internal_sched_yield()176*490215a3Smrg uptr internal_sched_yield() {
177*490215a3Smrg   return sched_yield();
178*490215a3Smrg }
179*490215a3Smrg 
internal__exit(int exitcode)180*490215a3Smrg void internal__exit(int exitcode) {
181*490215a3Smrg   _exit(exitcode);
182*490215a3Smrg }
183*490215a3Smrg 
internal_sleep(unsigned int seconds)184*490215a3Smrg unsigned int internal_sleep(unsigned int seconds) {
185*490215a3Smrg   return sleep(seconds);
186*490215a3Smrg }
187*490215a3Smrg 
internal_getpid()188*490215a3Smrg uptr internal_getpid() {
189*490215a3Smrg   return getpid();
190*490215a3Smrg }
191*490215a3Smrg 
internal_dlinfo(void * handle,int request,void * p)192*490215a3Smrg int internal_dlinfo(void *handle, int request, void *p) {
193*490215a3Smrg   UNIMPLEMENTED();
194*490215a3Smrg }
195*490215a3Smrg 
internal_sigaction(int signum,const void * act,void * oldact)196*490215a3Smrg int internal_sigaction(int signum, const void *act, void *oldact) {
197*490215a3Smrg   return sigaction(signum,
198*490215a3Smrg                    (const struct sigaction *)act, (struct sigaction *)oldact);
199*490215a3Smrg }
200*490215a3Smrg 
internal_sigfillset(__sanitizer_sigset_t * set)201*490215a3Smrg void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); }
202*490215a3Smrg 
internal_sigprocmask(int how,__sanitizer_sigset_t * set,__sanitizer_sigset_t * oldset)203*490215a3Smrg uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
204*490215a3Smrg                           __sanitizer_sigset_t *oldset) {
205*490215a3Smrg   // Don't use sigprocmask here, because it affects all threads.
206*490215a3Smrg   return pthread_sigmask(how, set, oldset);
207*490215a3Smrg }
208*490215a3Smrg 
209*490215a3Smrg // Doesn't call pthread_atfork() handlers (but not available on 10.6).
210*490215a3Smrg extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE;
211*490215a3Smrg 
internal_fork()212*490215a3Smrg int internal_fork() {
213*490215a3Smrg   if (&__fork)
214*490215a3Smrg     return __fork();
215*490215a3Smrg   return fork();
216*490215a3Smrg }
217*490215a3Smrg 
internal_sysctl(const int * name,unsigned int namelen,void * oldp,uptr * oldlenp,const void * newp,uptr newlen)218*490215a3Smrg int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
219*490215a3Smrg                     uptr *oldlenp, const void *newp, uptr newlen) {
220*490215a3Smrg   return sysctl(const_cast<int *>(name), namelen, oldp, (size_t *)oldlenp,
221*490215a3Smrg                 const_cast<void *>(newp), (size_t)newlen);
222*490215a3Smrg }
223*490215a3Smrg 
internal_sysctlbyname(const char * sname,void * oldp,uptr * oldlenp,const void * newp,uptr newlen)224*490215a3Smrg int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
225*490215a3Smrg                           const void *newp, uptr newlen) {
226*490215a3Smrg   return sysctlbyname(sname, oldp, (size_t *)oldlenp, const_cast<void *>(newp),
227*490215a3Smrg                       (size_t)newlen);
228*490215a3Smrg }
229*490215a3Smrg 
internal_forkpty(int * amaster)230*490215a3Smrg int internal_forkpty(int *amaster) {
231*490215a3Smrg   int master, slave;
232*490215a3Smrg   if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1;
233*490215a3Smrg   int pid = internal_fork();
234*490215a3Smrg   if (pid == -1) {
235*490215a3Smrg     close(master);
236*490215a3Smrg     close(slave);
237*490215a3Smrg     return -1;
238*490215a3Smrg   }
239*490215a3Smrg   if (pid == 0) {
240*490215a3Smrg     close(master);
241*490215a3Smrg     if (login_tty(slave) != 0) {
242*490215a3Smrg       // We already forked, there's not much we can do.  Let's quit.
243*490215a3Smrg       Report("login_tty failed (errno %d)\n", errno);
244*490215a3Smrg       internal__exit(1);
245*490215a3Smrg     }
246*490215a3Smrg   } else {
247*490215a3Smrg     *amaster = master;
248*490215a3Smrg     close(slave);
249*490215a3Smrg   }
250*490215a3Smrg   return pid;
251*490215a3Smrg }
252*490215a3Smrg 
internal_rename(const char * oldpath,const char * newpath)253*490215a3Smrg uptr internal_rename(const char *oldpath, const char *newpath) {
254*490215a3Smrg   return rename(oldpath, newpath);
255*490215a3Smrg }
256*490215a3Smrg 
internal_ftruncate(fd_t fd,uptr size)257*490215a3Smrg uptr internal_ftruncate(fd_t fd, uptr size) {
258*490215a3Smrg   return ftruncate(fd, size);
259*490215a3Smrg }
260*490215a3Smrg 
internal_execve(const char * filename,char * const argv[],char * const envp[])261*490215a3Smrg uptr internal_execve(const char *filename, char *const argv[],
262*490215a3Smrg                      char *const envp[]) {
263*490215a3Smrg   return execve(filename, argv, envp);
264*490215a3Smrg }
265*490215a3Smrg 
internal_waitpid(int pid,int * status,int options)266*490215a3Smrg uptr internal_waitpid(int pid, int *status, int options) {
267*490215a3Smrg   return waitpid(pid, status, options);
268*490215a3Smrg }
269*490215a3Smrg 
270*490215a3Smrg // ----------------- sanitizer_common.h
FileExists(const char * filename)271*490215a3Smrg bool FileExists(const char *filename) {
272*490215a3Smrg   struct stat st;
273*490215a3Smrg   if (stat(filename, &st))
274*490215a3Smrg     return false;
275*490215a3Smrg   // Sanity check: filename is a regular file.
276*490215a3Smrg   return S_ISREG(st.st_mode);
277*490215a3Smrg }
278*490215a3Smrg 
GetTid()279*490215a3Smrg tid_t GetTid() {
280*490215a3Smrg   tid_t tid;
281*490215a3Smrg   pthread_threadid_np(nullptr, &tid);
282*490215a3Smrg   return tid;
283*490215a3Smrg }
284*490215a3Smrg 
GetThreadStackTopAndBottom(bool at_initialization,uptr * stack_top,uptr * stack_bottom)285*490215a3Smrg void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
286*490215a3Smrg                                 uptr *stack_bottom) {
287*490215a3Smrg   CHECK(stack_top);
288*490215a3Smrg   CHECK(stack_bottom);
289*490215a3Smrg   uptr stacksize = pthread_get_stacksize_np(pthread_self());
290*490215a3Smrg   // pthread_get_stacksize_np() returns an incorrect stack size for the main
291*490215a3Smrg   // thread on Mavericks. See
292*490215a3Smrg   // https://github.com/google/sanitizers/issues/261
293*490215a3Smrg   if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
294*490215a3Smrg       stacksize == (1 << 19))  {
295*490215a3Smrg     struct rlimit rl;
296*490215a3Smrg     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
297*490215a3Smrg     // Most often rl.rlim_cur will be the desired 8M.
298*490215a3Smrg     if (rl.rlim_cur < kMaxThreadStackSize) {
299*490215a3Smrg       stacksize = rl.rlim_cur;
300*490215a3Smrg     } else {
301*490215a3Smrg       stacksize = kMaxThreadStackSize;
302*490215a3Smrg     }
303*490215a3Smrg   }
304*490215a3Smrg   void *stackaddr = pthread_get_stackaddr_np(pthread_self());
305*490215a3Smrg   *stack_top = (uptr)stackaddr;
306*490215a3Smrg   *stack_bottom = *stack_top - stacksize;
307*490215a3Smrg }
308*490215a3Smrg 
GetEnviron()309*490215a3Smrg char **GetEnviron() {
310*490215a3Smrg #if !SANITIZER_IOS
311*490215a3Smrg   char ***env_ptr = _NSGetEnviron();
312*490215a3Smrg   if (!env_ptr) {
313*490215a3Smrg     Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
314*490215a3Smrg            "called after libSystem_initializer().\n");
315*490215a3Smrg     CHECK(env_ptr);
316*490215a3Smrg   }
317*490215a3Smrg   char **environ = *env_ptr;
318*490215a3Smrg #endif
319*490215a3Smrg   CHECK(environ);
320*490215a3Smrg   return environ;
321*490215a3Smrg }
322*490215a3Smrg 
GetEnv(const char * name)323*490215a3Smrg const char *GetEnv(const char *name) {
324*490215a3Smrg   char **env = GetEnviron();
325*490215a3Smrg   uptr name_len = internal_strlen(name);
326*490215a3Smrg   while (*env != 0) {
327*490215a3Smrg     uptr len = internal_strlen(*env);
328*490215a3Smrg     if (len > name_len) {
329*490215a3Smrg       const char *p = *env;
330*490215a3Smrg       if (!internal_memcmp(p, name, name_len) &&
331*490215a3Smrg           p[name_len] == '=') {  // Match.
332*490215a3Smrg         return *env + name_len + 1;  // String starting after =.
333*490215a3Smrg       }
334*490215a3Smrg     }
335*490215a3Smrg     env++;
336*490215a3Smrg   }
337*490215a3Smrg   return 0;
338*490215a3Smrg }
339*490215a3Smrg 
ReadBinaryName(char * buf,uptr buf_len)340*490215a3Smrg uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
341*490215a3Smrg   CHECK_LE(kMaxPathLength, buf_len);
342*490215a3Smrg 
343*490215a3Smrg   // On OS X the executable path is saved to the stack by dyld. Reading it
344*490215a3Smrg   // from there is much faster than calling dladdr, especially for large
345*490215a3Smrg   // binaries with symbols.
346*490215a3Smrg   InternalScopedString exe_path(kMaxPathLength);
347*490215a3Smrg   uint32_t size = exe_path.size();
348*490215a3Smrg   if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
349*490215a3Smrg       realpath(exe_path.data(), buf) != 0) {
350*490215a3Smrg     return internal_strlen(buf);
351*490215a3Smrg   }
352*490215a3Smrg   return 0;
353*490215a3Smrg }
354*490215a3Smrg 
ReadLongProcessName(char * buf,uptr buf_len)355*490215a3Smrg uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
356*490215a3Smrg   return ReadBinaryName(buf, buf_len);
357*490215a3Smrg }
358*490215a3Smrg 
ReExec()359*490215a3Smrg void ReExec() {
360*490215a3Smrg   UNIMPLEMENTED();
361*490215a3Smrg }
362*490215a3Smrg 
CheckASLR()363*490215a3Smrg void CheckASLR() {
364*490215a3Smrg   // Do nothing
365*490215a3Smrg }
366*490215a3Smrg 
GetPageSize()367*490215a3Smrg uptr GetPageSize() {
368*490215a3Smrg   return sysconf(_SC_PAGESIZE);
369*490215a3Smrg }
370*490215a3Smrg 
371*490215a3Smrg extern "C" unsigned malloc_num_zones;
372*490215a3Smrg extern "C" malloc_zone_t **malloc_zones;
373*490215a3Smrg malloc_zone_t sanitizer_zone;
374*490215a3Smrg 
375*490215a3Smrg // We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If
376*490215a3Smrg // libmalloc tries to set up a different zone as malloc_zones[0], it will call
377*490215a3Smrg // mprotect(malloc_zones, ..., PROT_READ).  This interceptor will catch that and
378*490215a3Smrg // make sure we are still the first (default) zone.
MprotectMallocZones(void * addr,int prot)379*490215a3Smrg void MprotectMallocZones(void *addr, int prot) {
380*490215a3Smrg   if (addr == malloc_zones && prot == PROT_READ) {
381*490215a3Smrg     if (malloc_num_zones > 1 && malloc_zones[0] != &sanitizer_zone) {
382*490215a3Smrg       for (unsigned i = 1; i < malloc_num_zones; i++) {
383*490215a3Smrg         if (malloc_zones[i] == &sanitizer_zone) {
384*490215a3Smrg           // Swap malloc_zones[0] and malloc_zones[i].
385*490215a3Smrg           malloc_zones[i] = malloc_zones[0];
386*490215a3Smrg           malloc_zones[0] = &sanitizer_zone;
387*490215a3Smrg           break;
388*490215a3Smrg         }
389*490215a3Smrg       }
390*490215a3Smrg     }
391*490215a3Smrg   }
392*490215a3Smrg }
393*490215a3Smrg 
BlockingMutex()394*490215a3Smrg BlockingMutex::BlockingMutex() {
395*490215a3Smrg   internal_memset(this, 0, sizeof(*this));
396*490215a3Smrg }
397*490215a3Smrg 
Lock()398*490215a3Smrg void BlockingMutex::Lock() {
399*490215a3Smrg   CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
400*490215a3Smrg   CHECK_EQ(OS_SPINLOCK_INIT, 0);
401*490215a3Smrg   CHECK_EQ(owner_, 0);
402*490215a3Smrg   OSSpinLockLock((OSSpinLock*)&opaque_storage_);
403*490215a3Smrg }
404*490215a3Smrg 
Unlock()405*490215a3Smrg void BlockingMutex::Unlock() {
406*490215a3Smrg   OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
407*490215a3Smrg }
408*490215a3Smrg 
CheckLocked()409*490215a3Smrg void BlockingMutex::CheckLocked() {
410*490215a3Smrg   CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0);
411*490215a3Smrg }
412*490215a3Smrg 
NanoTime()413*490215a3Smrg u64 NanoTime() {
414*490215a3Smrg   timeval tv;
415*490215a3Smrg   internal_memset(&tv, 0, sizeof(tv));
416*490215a3Smrg   gettimeofday(&tv, 0);
417*490215a3Smrg   return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
418*490215a3Smrg }
419*490215a3Smrg 
420*490215a3Smrg // This needs to be called during initialization to avoid being racy.
MonotonicNanoTime()421*490215a3Smrg u64 MonotonicNanoTime() {
422*490215a3Smrg   static mach_timebase_info_data_t timebase_info;
423*490215a3Smrg   if (timebase_info.denom == 0) mach_timebase_info(&timebase_info);
424*490215a3Smrg   return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom;
425*490215a3Smrg }
426*490215a3Smrg 
GetTlsSize()427*490215a3Smrg uptr GetTlsSize() {
428*490215a3Smrg   return 0;
429*490215a3Smrg }
430*490215a3Smrg 
InitTlsSize()431*490215a3Smrg void InitTlsSize() {
432*490215a3Smrg }
433*490215a3Smrg 
TlsBaseAddr()434*490215a3Smrg uptr TlsBaseAddr() {
435*490215a3Smrg   uptr segbase = 0;
436*490215a3Smrg #if defined(__x86_64__)
437*490215a3Smrg   asm("movq %%gs:0,%0" : "=r"(segbase));
438*490215a3Smrg #elif defined(__i386__)
439*490215a3Smrg   asm("movl %%gs:0,%0" : "=r"(segbase));
440*490215a3Smrg #endif
441*490215a3Smrg   return segbase;
442*490215a3Smrg }
443*490215a3Smrg 
444*490215a3Smrg // The size of the tls on darwin does not appear to be well documented,
445*490215a3Smrg // however the vm memory map suggests that it is 1024 uptrs in size,
446*490215a3Smrg // with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
TlsSize()447*490215a3Smrg uptr TlsSize() {
448*490215a3Smrg #if defined(__x86_64__) || defined(__i386__)
449*490215a3Smrg   return 1024 * sizeof(uptr);
450*490215a3Smrg #else
451*490215a3Smrg   return 0;
452*490215a3Smrg #endif
453*490215a3Smrg }
454*490215a3Smrg 
GetThreadStackAndTls(bool main,uptr * stk_addr,uptr * stk_size,uptr * tls_addr,uptr * tls_size)455*490215a3Smrg void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
456*490215a3Smrg                           uptr *tls_addr, uptr *tls_size) {
457*490215a3Smrg #if !SANITIZER_GO
458*490215a3Smrg   uptr stack_top, stack_bottom;
459*490215a3Smrg   GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
460*490215a3Smrg   *stk_addr = stack_bottom;
461*490215a3Smrg   *stk_size = stack_top - stack_bottom;
462*490215a3Smrg   *tls_addr = TlsBaseAddr();
463*490215a3Smrg   *tls_size = TlsSize();
464*490215a3Smrg #else
465*490215a3Smrg   *stk_addr = 0;
466*490215a3Smrg   *stk_size = 0;
467*490215a3Smrg   *tls_addr = 0;
468*490215a3Smrg   *tls_size = 0;
469*490215a3Smrg #endif
470*490215a3Smrg }
471*490215a3Smrg 
init()472*490215a3Smrg void ListOfModules::init() {
473*490215a3Smrg   clearOrInit();
474*490215a3Smrg   MemoryMappingLayout memory_mapping(false);
475*490215a3Smrg   memory_mapping.DumpListOfModules(&modules_);
476*490215a3Smrg }
477*490215a3Smrg 
fallbackInit()478*490215a3Smrg void ListOfModules::fallbackInit() { clear(); }
479*490215a3Smrg 
GetHandleSignalModeImpl(int signum)480*490215a3Smrg static HandleSignalMode GetHandleSignalModeImpl(int signum) {
481*490215a3Smrg   switch (signum) {
482*490215a3Smrg     case SIGABRT:
483*490215a3Smrg       return common_flags()->handle_abort;
484*490215a3Smrg     case SIGILL:
485*490215a3Smrg       return common_flags()->handle_sigill;
486*490215a3Smrg     case SIGTRAP:
487*490215a3Smrg       return common_flags()->handle_sigtrap;
488*490215a3Smrg     case SIGFPE:
489*490215a3Smrg       return common_flags()->handle_sigfpe;
490*490215a3Smrg     case SIGSEGV:
491*490215a3Smrg       return common_flags()->handle_segv;
492*490215a3Smrg     case SIGBUS:
493*490215a3Smrg       return common_flags()->handle_sigbus;
494*490215a3Smrg   }
495*490215a3Smrg   return kHandleSignalNo;
496*490215a3Smrg }
497*490215a3Smrg 
GetHandleSignalMode(int signum)498*490215a3Smrg HandleSignalMode GetHandleSignalMode(int signum) {
499*490215a3Smrg   // Handling fatal signals on watchOS and tvOS devices is disallowed.
500*490215a3Smrg   if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM))
501*490215a3Smrg     return kHandleSignalNo;
502*490215a3Smrg   HandleSignalMode result = GetHandleSignalModeImpl(signum);
503*490215a3Smrg   if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
504*490215a3Smrg     return kHandleSignalExclusive;
505*490215a3Smrg   return result;
506*490215a3Smrg }
507*490215a3Smrg 
508*490215a3Smrg MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
509*490215a3Smrg 
GetMacosVersionInternal()510*490215a3Smrg MacosVersion GetMacosVersionInternal() {
511*490215a3Smrg   int mib[2] = { CTL_KERN, KERN_OSRELEASE };
512*490215a3Smrg   char version[100];
513*490215a3Smrg   uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
514*490215a3Smrg   for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
515*490215a3Smrg   // Get the version length.
516*490215a3Smrg   CHECK_NE(internal_sysctl(mib, 2, 0, &len, 0, 0), -1);
517*490215a3Smrg   CHECK_LT(len, maxlen);
518*490215a3Smrg   CHECK_NE(internal_sysctl(mib, 2, version, &len, 0, 0), -1);
519*490215a3Smrg   switch (version[0]) {
520*490215a3Smrg     case '9': return MACOS_VERSION_LEOPARD;
521*490215a3Smrg     case '1': {
522*490215a3Smrg       switch (version[1]) {
523*490215a3Smrg         case '0': return MACOS_VERSION_SNOW_LEOPARD;
524*490215a3Smrg         case '1': return MACOS_VERSION_LION;
525*490215a3Smrg         case '2': return MACOS_VERSION_MOUNTAIN_LION;
526*490215a3Smrg         case '3': return MACOS_VERSION_MAVERICKS;
527*490215a3Smrg         case '4': return MACOS_VERSION_YOSEMITE;
528*490215a3Smrg         case '5': return MACOS_VERSION_EL_CAPITAN;
529*490215a3Smrg         case '6': return MACOS_VERSION_SIERRA;
530*490215a3Smrg         case '7': return MACOS_VERSION_HIGH_SIERRA;
531*490215a3Smrg         case '8': return MACOS_VERSION_MOJAVE;
532*490215a3Smrg         default:
533*490215a3Smrg           if (IsDigit(version[1]))
534*490215a3Smrg             return MACOS_VERSION_UNKNOWN_NEWER;
535*490215a3Smrg           else
536*490215a3Smrg             return MACOS_VERSION_UNKNOWN;
537*490215a3Smrg       }
538*490215a3Smrg     }
539*490215a3Smrg     default: return MACOS_VERSION_UNKNOWN;
540*490215a3Smrg   }
541*490215a3Smrg }
542*490215a3Smrg 
GetMacosVersion()543*490215a3Smrg MacosVersion GetMacosVersion() {
544*490215a3Smrg   atomic_uint32_t *cache =
545*490215a3Smrg       reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
546*490215a3Smrg   MacosVersion result =
547*490215a3Smrg       static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
548*490215a3Smrg   if (result == MACOS_VERSION_UNINITIALIZED) {
549*490215a3Smrg     result = GetMacosVersionInternal();
550*490215a3Smrg     atomic_store(cache, result, memory_order_release);
551*490215a3Smrg   }
552*490215a3Smrg   return result;
553*490215a3Smrg }
554*490215a3Smrg 
PlatformHasDifferentMemcpyAndMemmove()555*490215a3Smrg bool PlatformHasDifferentMemcpyAndMemmove() {
556*490215a3Smrg   // On OS X 10.7 memcpy() and memmove() are both resolved
557*490215a3Smrg   // into memmove$VARIANT$sse42.
558*490215a3Smrg   // See also https://github.com/google/sanitizers/issues/34.
559*490215a3Smrg   // TODO(glider): need to check dynamically that memcpy() and memmove() are
560*490215a3Smrg   // actually the same function.
561*490215a3Smrg   return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
562*490215a3Smrg }
563*490215a3Smrg 
GetRSS()564*490215a3Smrg uptr GetRSS() {
565*490215a3Smrg   struct task_basic_info info;
566*490215a3Smrg   unsigned count = TASK_BASIC_INFO_COUNT;
567*490215a3Smrg   kern_return_t result =
568*490215a3Smrg       task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
569*490215a3Smrg   if (UNLIKELY(result != KERN_SUCCESS)) {
570*490215a3Smrg     Report("Cannot get task info. Error: %d\n", result);
571*490215a3Smrg     Die();
572*490215a3Smrg   }
573*490215a3Smrg   return info.resident_size;
574*490215a3Smrg }
575*490215a3Smrg 
internal_start_thread(void (* func)(void * arg),void * arg)576*490215a3Smrg void *internal_start_thread(void(*func)(void *arg), void *arg) {
577*490215a3Smrg   // Start the thread with signals blocked, otherwise it can steal user signals.
578*490215a3Smrg   __sanitizer_sigset_t set, old;
579*490215a3Smrg   internal_sigfillset(&set);
580*490215a3Smrg   internal_sigprocmask(SIG_SETMASK, &set, &old);
581*490215a3Smrg   pthread_t th;
582*490215a3Smrg   pthread_create(&th, 0, (void*(*)(void *arg))func, arg);
583*490215a3Smrg   internal_sigprocmask(SIG_SETMASK, &old, 0);
584*490215a3Smrg   return th;
585*490215a3Smrg }
586*490215a3Smrg 
internal_join_thread(void * th)587*490215a3Smrg void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
588*490215a3Smrg 
589*490215a3Smrg #if !SANITIZER_GO
590*490215a3Smrg static BlockingMutex syslog_lock(LINKER_INITIALIZED);
591*490215a3Smrg #endif
592*490215a3Smrg 
WriteOneLineToSyslog(const char * s)593*490215a3Smrg void WriteOneLineToSyslog(const char *s) {
594*490215a3Smrg #if !SANITIZER_GO
595*490215a3Smrg   syslog_lock.CheckLocked();
596*490215a3Smrg   asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
597*490215a3Smrg #endif
598*490215a3Smrg }
599*490215a3Smrg 
LogMessageOnPrintf(const char * str)600*490215a3Smrg void LogMessageOnPrintf(const char *str) {
601*490215a3Smrg   // Log all printf output to CrashLog.
602*490215a3Smrg   if (common_flags()->abort_on_error)
603*490215a3Smrg     CRAppendCrashLogMessage(str);
604*490215a3Smrg }
605*490215a3Smrg 
LogFullErrorReport(const char * buffer)606*490215a3Smrg void LogFullErrorReport(const char *buffer) {
607*490215a3Smrg #if !SANITIZER_GO
608*490215a3Smrg   // Log with os_trace. This will make it into the crash log.
609*490215a3Smrg #if SANITIZER_OS_TRACE
610*490215a3Smrg   if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) {
611*490215a3Smrg     // os_trace requires the message (format parameter) to be a string literal.
612*490215a3Smrg     if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
613*490215a3Smrg                          sizeof("AddressSanitizer") - 1) == 0)
614*490215a3Smrg       os_trace("Address Sanitizer reported a failure.");
615*490215a3Smrg     else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
616*490215a3Smrg                               sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
617*490215a3Smrg       os_trace("Undefined Behavior Sanitizer reported a failure.");
618*490215a3Smrg     else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
619*490215a3Smrg                               sizeof("ThreadSanitizer") - 1) == 0)
620*490215a3Smrg       os_trace("Thread Sanitizer reported a failure.");
621*490215a3Smrg     else
622*490215a3Smrg       os_trace("Sanitizer tool reported a failure.");
623*490215a3Smrg 
624*490215a3Smrg     if (common_flags()->log_to_syslog)
625*490215a3Smrg       os_trace("Consult syslog for more information.");
626*490215a3Smrg   }
627*490215a3Smrg #endif
628*490215a3Smrg 
629*490215a3Smrg   // Log to syslog.
630*490215a3Smrg   // The logging on OS X may call pthread_create so we need the threading
631*490215a3Smrg   // environment to be fully initialized. Also, this should never be called when
632*490215a3Smrg   // holding the thread registry lock since that may result in a deadlock. If
633*490215a3Smrg   // the reporting thread holds the thread registry mutex, and asl_log waits
634*490215a3Smrg   // for GCD to dispatch a new thread, the process will deadlock, because the
635*490215a3Smrg   // pthread_create wrapper needs to acquire the lock as well.
636*490215a3Smrg   BlockingMutexLock l(&syslog_lock);
637*490215a3Smrg   if (common_flags()->log_to_syslog)
638*490215a3Smrg     WriteToSyslog(buffer);
639*490215a3Smrg 
640*490215a3Smrg   // The report is added to CrashLog as part of logging all of Printf output.
641*490215a3Smrg #endif
642*490215a3Smrg }
643*490215a3Smrg 
GetWriteFlag() const644*490215a3Smrg SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
645*490215a3Smrg #if defined(__x86_64__) || defined(__i386__)
646*490215a3Smrg   ucontext_t *ucontext = static_cast<ucontext_t*>(context);
647*490215a3Smrg   return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ;
648*490215a3Smrg #else
649*490215a3Smrg   return UNKNOWN;
650*490215a3Smrg #endif
651*490215a3Smrg }
652*490215a3Smrg 
GetPcSpBp(void * context,uptr * pc,uptr * sp,uptr * bp)653*490215a3Smrg static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
654*490215a3Smrg   ucontext_t *ucontext = (ucontext_t*)context;
655*490215a3Smrg # if defined(__aarch64__)
656*490215a3Smrg   *pc = ucontext->uc_mcontext->__ss.__pc;
657*490215a3Smrg #   if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
658*490215a3Smrg   *bp = ucontext->uc_mcontext->__ss.__fp;
659*490215a3Smrg #   else
660*490215a3Smrg   *bp = ucontext->uc_mcontext->__ss.__lr;
661*490215a3Smrg #   endif
662*490215a3Smrg   *sp = ucontext->uc_mcontext->__ss.__sp;
663*490215a3Smrg # elif defined(__x86_64__)
664*490215a3Smrg   *pc = ucontext->uc_mcontext->__ss.__rip;
665*490215a3Smrg   *bp = ucontext->uc_mcontext->__ss.__rbp;
666*490215a3Smrg   *sp = ucontext->uc_mcontext->__ss.__rsp;
667*490215a3Smrg # elif defined(__arm__)
668*490215a3Smrg   *pc = ucontext->uc_mcontext->__ss.__pc;
669*490215a3Smrg   *bp = ucontext->uc_mcontext->__ss.__r[7];
670*490215a3Smrg   *sp = ucontext->uc_mcontext->__ss.__sp;
671*490215a3Smrg # elif defined(__i386__)
672*490215a3Smrg   *pc = ucontext->uc_mcontext->__ss.__eip;
673*490215a3Smrg   *bp = ucontext->uc_mcontext->__ss.__ebp;
674*490215a3Smrg   *sp = ucontext->uc_mcontext->__ss.__esp;
675*490215a3Smrg # else
676*490215a3Smrg # error "Unknown architecture"
677*490215a3Smrg # endif
678*490215a3Smrg }
679*490215a3Smrg 
InitPcSpBp()680*490215a3Smrg void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
681*490215a3Smrg 
682*490215a3Smrg #if !SANITIZER_GO
683*490215a3Smrg static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
684*490215a3Smrg LowLevelAllocator allocator_for_env;
685*490215a3Smrg 
686*490215a3Smrg // Change the value of the env var |name|, leaking the original value.
687*490215a3Smrg // If |name_value| is NULL, the variable is deleted from the environment,
688*490215a3Smrg // otherwise the corresponding "NAME=value" string is replaced with
689*490215a3Smrg // |name_value|.
LeakyResetEnv(const char * name,const char * name_value)690*490215a3Smrg void LeakyResetEnv(const char *name, const char *name_value) {
691*490215a3Smrg   char **env = GetEnviron();
692*490215a3Smrg   uptr name_len = internal_strlen(name);
693*490215a3Smrg   while (*env != 0) {
694*490215a3Smrg     uptr len = internal_strlen(*env);
695*490215a3Smrg     if (len > name_len) {
696*490215a3Smrg       const char *p = *env;
697*490215a3Smrg       if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
698*490215a3Smrg         // Match.
699*490215a3Smrg         if (name_value) {
700*490215a3Smrg           // Replace the old value with the new one.
701*490215a3Smrg           *env = const_cast<char*>(name_value);
702*490215a3Smrg         } else {
703*490215a3Smrg           // Shift the subsequent pointers back.
704*490215a3Smrg           char **del = env;
705*490215a3Smrg           do {
706*490215a3Smrg             del[0] = del[1];
707*490215a3Smrg           } while (*del++);
708*490215a3Smrg         }
709*490215a3Smrg       }
710*490215a3Smrg     }
711*490215a3Smrg     env++;
712*490215a3Smrg   }
713*490215a3Smrg }
714*490215a3Smrg 
715*490215a3Smrg SANITIZER_WEAK_CXX_DEFAULT_IMPL
ReexecDisabled()716*490215a3Smrg bool ReexecDisabled() {
717*490215a3Smrg   return false;
718*490215a3Smrg }
719*490215a3Smrg 
720*490215a3Smrg extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber;
721*490215a3Smrg static const double kMinDyldVersionWithAutoInterposition = 360.0;
722*490215a3Smrg 
DyldNeedsEnvVariable()723*490215a3Smrg bool DyldNeedsEnvVariable() {
724*490215a3Smrg   // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users
725*490215a3Smrg   // still may want use them on older systems. On older Darwin platforms, dyld
726*490215a3Smrg   // doesn't export dyldVersionNumber symbol and we simply return true.
727*490215a3Smrg   if (!&dyldVersionNumber) return true;
728*490215a3Smrg   // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
729*490215a3Smrg   // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via
730*490215a3Smrg   // GetMacosVersion() doesn't work for the simulator. Let's instead check
731*490215a3Smrg   // `dyldVersionNumber`, which is exported by dyld, against a known version
732*490215a3Smrg   // number from the first OS release where this appeared.
733*490215a3Smrg   return dyldVersionNumber < kMinDyldVersionWithAutoInterposition;
734*490215a3Smrg }
735*490215a3Smrg 
MaybeReexec()736*490215a3Smrg void MaybeReexec() {
737*490215a3Smrg   // FIXME: This should really live in some "InitializePlatform" method.
738*490215a3Smrg   MonotonicNanoTime();
739*490215a3Smrg 
740*490215a3Smrg   if (ReexecDisabled()) return;
741*490215a3Smrg 
742*490215a3Smrg   // Make sure the dynamic runtime library is preloaded so that the
743*490215a3Smrg   // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
744*490215a3Smrg   // ourselves.
745*490215a3Smrg   Dl_info info;
746*490215a3Smrg   RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
747*490215a3Smrg   char *dyld_insert_libraries =
748*490215a3Smrg       const_cast<char*>(GetEnv(kDyldInsertLibraries));
749*490215a3Smrg   uptr old_env_len = dyld_insert_libraries ?
750*490215a3Smrg       internal_strlen(dyld_insert_libraries) : 0;
751*490215a3Smrg   uptr fname_len = internal_strlen(info.dli_fname);
752*490215a3Smrg   const char *dylib_name = StripModuleName(info.dli_fname);
753*490215a3Smrg   uptr dylib_name_len = internal_strlen(dylib_name);
754*490215a3Smrg 
755*490215a3Smrg   bool lib_is_in_env = dyld_insert_libraries &&
756*490215a3Smrg                        internal_strstr(dyld_insert_libraries, dylib_name);
757*490215a3Smrg   if (DyldNeedsEnvVariable() && !lib_is_in_env) {
758*490215a3Smrg     // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
759*490215a3Smrg     // library.
760*490215a3Smrg     InternalScopedString program_name(1024);
761*490215a3Smrg     uint32_t buf_size = program_name.size();
762*490215a3Smrg     _NSGetExecutablePath(program_name.data(), &buf_size);
763*490215a3Smrg     char *new_env = const_cast<char*>(info.dli_fname);
764*490215a3Smrg     if (dyld_insert_libraries) {
765*490215a3Smrg       // Append the runtime dylib name to the existing value of
766*490215a3Smrg       // DYLD_INSERT_LIBRARIES.
767*490215a3Smrg       new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
768*490215a3Smrg       internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
769*490215a3Smrg       new_env[old_env_len] = ':';
770*490215a3Smrg       // Copy fname_len and add a trailing zero.
771*490215a3Smrg       internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
772*490215a3Smrg                        fname_len + 1);
773*490215a3Smrg       // Ok to use setenv() since the wrappers don't depend on the value of
774*490215a3Smrg       // asan_inited.
775*490215a3Smrg       setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
776*490215a3Smrg     } else {
777*490215a3Smrg       // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
778*490215a3Smrg       setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
779*490215a3Smrg     }
780*490215a3Smrg     VReport(1, "exec()-ing the program with\n");
781*490215a3Smrg     VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
782*490215a3Smrg     VReport(1, "to enable wrappers.\n");
783*490215a3Smrg     execv(program_name.data(), *_NSGetArgv());
784*490215a3Smrg 
785*490215a3Smrg     // We get here only if execv() failed.
786*490215a3Smrg     Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
787*490215a3Smrg            "which is required for the sanitizer to work. We tried to set the "
788*490215a3Smrg            "environment variable and re-execute itself, but execv() failed, "
789*490215a3Smrg            "possibly because of sandbox restrictions. Make sure to launch the "
790*490215a3Smrg            "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
791*490215a3Smrg     RAW_CHECK("execv failed" && 0);
792*490215a3Smrg   }
793*490215a3Smrg 
794*490215a3Smrg   // Verify that interceptors really work.  We'll use dlsym to locate
795*490215a3Smrg   // "pthread_create", if interceptors are working, it should really point to
796*490215a3Smrg   // "wrap_pthread_create" within our own dylib.
797*490215a3Smrg   Dl_info info_pthread_create;
798*490215a3Smrg   void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create");
799*490215a3Smrg   RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create));
800*490215a3Smrg   if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) {
801*490215a3Smrg     Report(
802*490215a3Smrg         "ERROR: Interceptors are not working. This may be because %s is "
803*490215a3Smrg         "loaded too late (e.g. via dlopen). Please launch the executable "
804*490215a3Smrg         "with:\n%s=%s\n",
805*490215a3Smrg         SanitizerToolName, kDyldInsertLibraries, info.dli_fname);
806*490215a3Smrg     RAW_CHECK("interceptors not installed" && 0);
807*490215a3Smrg   }
808*490215a3Smrg 
809*490215a3Smrg   if (!lib_is_in_env)
810*490215a3Smrg     return;
811*490215a3Smrg 
812*490215a3Smrg   if (!common_flags()->strip_env)
813*490215a3Smrg     return;
814*490215a3Smrg 
815*490215a3Smrg   // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
816*490215a3Smrg   // the dylib from the environment variable, because interceptors are installed
817*490215a3Smrg   // and we don't want our children to inherit the variable.
818*490215a3Smrg 
819*490215a3Smrg   uptr env_name_len = internal_strlen(kDyldInsertLibraries);
820*490215a3Smrg   // Allocate memory to hold the previous env var name, its value, the '='
821*490215a3Smrg   // sign and the '\0' char.
822*490215a3Smrg   char *new_env = (char*)allocator_for_env.Allocate(
823*490215a3Smrg       old_env_len + 2 + env_name_len);
824*490215a3Smrg   RAW_CHECK(new_env);
825*490215a3Smrg   internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
826*490215a3Smrg   internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
827*490215a3Smrg   new_env[env_name_len] = '=';
828*490215a3Smrg   char *new_env_pos = new_env + env_name_len + 1;
829*490215a3Smrg 
830*490215a3Smrg   // Iterate over colon-separated pieces of |dyld_insert_libraries|.
831*490215a3Smrg   char *piece_start = dyld_insert_libraries;
832*490215a3Smrg   char *piece_end = NULL;
833*490215a3Smrg   char *old_env_end = dyld_insert_libraries + old_env_len;
834*490215a3Smrg   do {
835*490215a3Smrg     if (piece_start[0] == ':') piece_start++;
836*490215a3Smrg     piece_end = internal_strchr(piece_start, ':');
837*490215a3Smrg     if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
838*490215a3Smrg     if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
839*490215a3Smrg     uptr piece_len = piece_end - piece_start;
840*490215a3Smrg 
841*490215a3Smrg     char *filename_start =
842*490215a3Smrg         (char *)internal_memrchr(piece_start, '/', piece_len);
843*490215a3Smrg     uptr filename_len = piece_len;
844*490215a3Smrg     if (filename_start) {
845*490215a3Smrg       filename_start += 1;
846*490215a3Smrg       filename_len = piece_len - (filename_start - piece_start);
847*490215a3Smrg     } else {
848*490215a3Smrg       filename_start = piece_start;
849*490215a3Smrg     }
850*490215a3Smrg 
851*490215a3Smrg     // If the current piece isn't the runtime library name,
852*490215a3Smrg     // append it to new_env.
853*490215a3Smrg     if ((dylib_name_len != filename_len) ||
854*490215a3Smrg         (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
855*490215a3Smrg       if (new_env_pos != new_env + env_name_len + 1) {
856*490215a3Smrg         new_env_pos[0] = ':';
857*490215a3Smrg         new_env_pos++;
858*490215a3Smrg       }
859*490215a3Smrg       internal_strncpy(new_env_pos, piece_start, piece_len);
860*490215a3Smrg       new_env_pos += piece_len;
861*490215a3Smrg     }
862*490215a3Smrg     // Move on to the next piece.
863*490215a3Smrg     piece_start = piece_end;
864*490215a3Smrg   } while (piece_start < old_env_end);
865*490215a3Smrg 
866*490215a3Smrg   // Can't use setenv() here, because it requires the allocator to be
867*490215a3Smrg   // initialized.
868*490215a3Smrg   // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
869*490215a3Smrg   // a separate function called after InitializeAllocator().
870*490215a3Smrg   if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
871*490215a3Smrg   LeakyResetEnv(kDyldInsertLibraries, new_env);
872*490215a3Smrg }
873*490215a3Smrg #endif  // SANITIZER_GO
874*490215a3Smrg 
GetArgv()875*490215a3Smrg char **GetArgv() {
876*490215a3Smrg   return *_NSGetArgv();
877*490215a3Smrg }
878*490215a3Smrg 
879*490215a3Smrg #if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM
880*490215a3Smrg // The task_vm_info struct is normally provided by the macOS SDK, but we need
881*490215a3Smrg // fields only available in 10.12+. Declare the struct manually to be able to
882*490215a3Smrg // build against older SDKs.
883*490215a3Smrg struct __sanitizer_task_vm_info {
884*490215a3Smrg   mach_vm_size_t virtual_size;
885*490215a3Smrg   integer_t region_count;
886*490215a3Smrg   integer_t page_size;
887*490215a3Smrg   mach_vm_size_t resident_size;
888*490215a3Smrg   mach_vm_size_t resident_size_peak;
889*490215a3Smrg   mach_vm_size_t device;
890*490215a3Smrg   mach_vm_size_t device_peak;
891*490215a3Smrg   mach_vm_size_t internal;
892*490215a3Smrg   mach_vm_size_t internal_peak;
893*490215a3Smrg   mach_vm_size_t external;
894*490215a3Smrg   mach_vm_size_t external_peak;
895*490215a3Smrg   mach_vm_size_t reusable;
896*490215a3Smrg   mach_vm_size_t reusable_peak;
897*490215a3Smrg   mach_vm_size_t purgeable_volatile_pmap;
898*490215a3Smrg   mach_vm_size_t purgeable_volatile_resident;
899*490215a3Smrg   mach_vm_size_t purgeable_volatile_virtual;
900*490215a3Smrg   mach_vm_size_t compressed;
901*490215a3Smrg   mach_vm_size_t compressed_peak;
902*490215a3Smrg   mach_vm_size_t compressed_lifetime;
903*490215a3Smrg   mach_vm_size_t phys_footprint;
904*490215a3Smrg   mach_vm_address_t min_address;
905*490215a3Smrg   mach_vm_address_t max_address;
906*490215a3Smrg };
907*490215a3Smrg #define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \
908*490215a3Smrg     (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t)))
909*490215a3Smrg 
GetTaskInfoMaxAddress()910*490215a3Smrg uptr GetTaskInfoMaxAddress() {
911*490215a3Smrg   __sanitizer_task_vm_info vm_info = {} /* zero initialize */;
912*490215a3Smrg   mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT;
913*490215a3Smrg   int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count);
914*490215a3Smrg   if (err == 0 && vm_info.max_address != 0) {
915*490215a3Smrg     return vm_info.max_address - 1;
916*490215a3Smrg   } else {
917*490215a3Smrg     // xnu cannot provide vm address limit
918*490215a3Smrg     return 0x200000000 - 1;
919*490215a3Smrg   }
920*490215a3Smrg }
921*490215a3Smrg #endif
922*490215a3Smrg 
GetMaxUserVirtualAddress()923*490215a3Smrg uptr GetMaxUserVirtualAddress() {
924*490215a3Smrg #if SANITIZER_WORDSIZE == 64
925*490215a3Smrg # if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM
926*490215a3Smrg   // Get the maximum VM address
927*490215a3Smrg   static uptr max_vm = GetTaskInfoMaxAddress();
928*490215a3Smrg   CHECK(max_vm);
929*490215a3Smrg   return max_vm;
930*490215a3Smrg # else
931*490215a3Smrg   return (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
932*490215a3Smrg # endif
933*490215a3Smrg #else  // SANITIZER_WORDSIZE == 32
934*490215a3Smrg   return (1ULL << 32) - 1;  // 0xffffffff;
935*490215a3Smrg #endif  // SANITIZER_WORDSIZE
936*490215a3Smrg }
937*490215a3Smrg 
GetMaxVirtualAddress()938*490215a3Smrg uptr GetMaxVirtualAddress() {
939*490215a3Smrg   return GetMaxUserVirtualAddress();
940*490215a3Smrg }
941*490215a3Smrg 
FindAvailableMemoryRange(uptr size,uptr alignment,uptr left_padding,uptr * largest_gap_found,uptr * max_occupied_addr)942*490215a3Smrg uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
943*490215a3Smrg                               uptr *largest_gap_found,
944*490215a3Smrg                               uptr *max_occupied_addr) {
945*490215a3Smrg   typedef vm_region_submap_short_info_data_64_t RegionInfo;
946*490215a3Smrg   enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
947*490215a3Smrg   // Start searching for available memory region past PAGEZERO, which is
948*490215a3Smrg   // 4KB on 32-bit and 4GB on 64-bit.
949*490215a3Smrg   mach_vm_address_t start_address =
950*490215a3Smrg     (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
951*490215a3Smrg 
952*490215a3Smrg   mach_vm_address_t address = start_address;
953*490215a3Smrg   mach_vm_address_t free_begin = start_address;
954*490215a3Smrg   kern_return_t kr = KERN_SUCCESS;
955*490215a3Smrg   if (largest_gap_found) *largest_gap_found = 0;
956*490215a3Smrg   if (max_occupied_addr) *max_occupied_addr = 0;
957*490215a3Smrg   while (kr == KERN_SUCCESS) {
958*490215a3Smrg     mach_vm_size_t vmsize = 0;
959*490215a3Smrg     natural_t depth = 0;
960*490215a3Smrg     RegionInfo vminfo;
961*490215a3Smrg     mach_msg_type_number_t count = kRegionInfoSize;
962*490215a3Smrg     kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
963*490215a3Smrg                                 (vm_region_info_t)&vminfo, &count);
964*490215a3Smrg     if (kr == KERN_INVALID_ADDRESS) {
965*490215a3Smrg       // No more regions beyond "address", consider the gap at the end of VM.
966*490215a3Smrg       address = GetMaxVirtualAddress() + 1;
967*490215a3Smrg       vmsize = 0;
968*490215a3Smrg     } else {
969*490215a3Smrg       if (max_occupied_addr) *max_occupied_addr = address + vmsize;
970*490215a3Smrg     }
971*490215a3Smrg     if (free_begin != address) {
972*490215a3Smrg       // We found a free region [free_begin..address-1].
973*490215a3Smrg       uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
974*490215a3Smrg       uptr gap_end = RoundDownTo((uptr)address, alignment);
975*490215a3Smrg       uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0;
976*490215a3Smrg       if (size < gap_size) {
977*490215a3Smrg         return gap_start;
978*490215a3Smrg       }
979*490215a3Smrg 
980*490215a3Smrg       if (largest_gap_found && *largest_gap_found < gap_size) {
981*490215a3Smrg         *largest_gap_found = gap_size;
982*490215a3Smrg       }
983*490215a3Smrg     }
984*490215a3Smrg     // Move to the next region.
985*490215a3Smrg     address += vmsize;
986*490215a3Smrg     free_begin = address;
987*490215a3Smrg   }
988*490215a3Smrg 
989*490215a3Smrg   // We looked at all free regions and could not find one large enough.
990*490215a3Smrg   return 0;
991*490215a3Smrg }
992*490215a3Smrg 
993*490215a3Smrg // FIXME implement on this platform.
GetMemoryProfile(fill_profile_f cb,uptr * stats,uptr stats_size)994*490215a3Smrg void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
995*490215a3Smrg 
DumpAllRegisters(void * context)996*490215a3Smrg void SignalContext::DumpAllRegisters(void *context) {
997*490215a3Smrg   Report("Register values:\n");
998*490215a3Smrg 
999*490215a3Smrg   ucontext_t *ucontext = (ucontext_t*)context;
1000*490215a3Smrg # define DUMPREG64(r) \
1001*490215a3Smrg     Printf("%s = 0x%016llx  ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1002*490215a3Smrg # define DUMPREG32(r) \
1003*490215a3Smrg     Printf("%s = 0x%08x  ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1004*490215a3Smrg # define DUMPREG_(r)   Printf(" "); DUMPREG(r);
1005*490215a3Smrg # define DUMPREG__(r)  Printf("  "); DUMPREG(r);
1006*490215a3Smrg # define DUMPREG___(r) Printf("   "); DUMPREG(r);
1007*490215a3Smrg 
1008*490215a3Smrg # if defined(__x86_64__)
1009*490215a3Smrg #  define DUMPREG(r) DUMPREG64(r)
1010*490215a3Smrg   DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
1011*490215a3Smrg   DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
1012*490215a3Smrg   DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
1013*490215a3Smrg   DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
1014*490215a3Smrg # elif defined(__i386__)
1015*490215a3Smrg #  define DUMPREG(r) DUMPREG32(r)
1016*490215a3Smrg   DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
1017*490215a3Smrg   DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
1018*490215a3Smrg # elif defined(__aarch64__)
1019*490215a3Smrg #  define DUMPREG(r) DUMPREG64(r)
1020*490215a3Smrg   DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
1021*490215a3Smrg   DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
1022*490215a3Smrg   DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
1023*490215a3Smrg   DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
1024*490215a3Smrg   DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
1025*490215a3Smrg   DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
1026*490215a3Smrg   DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
1027*490215a3Smrg   DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n");
1028*490215a3Smrg # elif defined(__arm__)
1029*490215a3Smrg #  define DUMPREG(r) DUMPREG32(r)
1030*490215a3Smrg   DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
1031*490215a3Smrg   DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
1032*490215a3Smrg   DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
1033*490215a3Smrg   DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
1034*490215a3Smrg # else
1035*490215a3Smrg # error "Unknown architecture"
1036*490215a3Smrg # endif
1037*490215a3Smrg 
1038*490215a3Smrg # undef DUMPREG64
1039*490215a3Smrg # undef DUMPREG32
1040*490215a3Smrg # undef DUMPREG_
1041*490215a3Smrg # undef DUMPREG__
1042*490215a3Smrg # undef DUMPREG___
1043*490215a3Smrg # undef DUMPREG
1044*490215a3Smrg }
1045*490215a3Smrg 
CompareBaseAddress(const LoadedModule & a,const LoadedModule & b)1046*490215a3Smrg static inline bool CompareBaseAddress(const LoadedModule &a,
1047*490215a3Smrg                                       const LoadedModule &b) {
1048*490215a3Smrg   return a.base_address() < b.base_address();
1049*490215a3Smrg }
1050*490215a3Smrg 
FormatUUID(char * out,uptr size,const u8 * uuid)1051*490215a3Smrg void FormatUUID(char *out, uptr size, const u8 *uuid) {
1052*490215a3Smrg   internal_snprintf(out, size,
1053*490215a3Smrg                     "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
1054*490215a3Smrg                     "%02X%02X%02X%02X%02X%02X>",
1055*490215a3Smrg                     uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
1056*490215a3Smrg                     uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
1057*490215a3Smrg                     uuid[12], uuid[13], uuid[14], uuid[15]);
1058*490215a3Smrg }
1059*490215a3Smrg 
PrintModuleMap()1060*490215a3Smrg void PrintModuleMap() {
1061*490215a3Smrg   Printf("Process module map:\n");
1062*490215a3Smrg   MemoryMappingLayout memory_mapping(false);
1063*490215a3Smrg   InternalMmapVector<LoadedModule> modules;
1064*490215a3Smrg   modules.reserve(128);
1065*490215a3Smrg   memory_mapping.DumpListOfModules(&modules);
1066*490215a3Smrg   Sort(modules.data(), modules.size(), CompareBaseAddress);
1067*490215a3Smrg   for (uptr i = 0; i < modules.size(); ++i) {
1068*490215a3Smrg     char uuid_str[128];
1069*490215a3Smrg     FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
1070*490215a3Smrg     Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
1071*490215a3Smrg            modules[i].max_executable_address(), modules[i].full_name(),
1072*490215a3Smrg            ModuleArchToString(modules[i].arch()), uuid_str);
1073*490215a3Smrg   }
1074*490215a3Smrg   Printf("End of module map.\n");
1075*490215a3Smrg }
1076*490215a3Smrg 
CheckNoDeepBind(const char * filename,int flag)1077*490215a3Smrg void CheckNoDeepBind(const char *filename, int flag) {
1078*490215a3Smrg   // Do nothing.
1079*490215a3Smrg }
1080*490215a3Smrg 
GetRandom(void * buffer,uptr length,bool blocking)1081*490215a3Smrg bool GetRandom(void *buffer, uptr length, bool blocking) {
1082*490215a3Smrg   if (!buffer || !length || length > 256)
1083*490215a3Smrg     return false;
1084*490215a3Smrg   // arc4random never fails.
1085*490215a3Smrg   arc4random_buf(buffer, length);
1086*490215a3Smrg   return true;
1087*490215a3Smrg }
1088*490215a3Smrg 
GetNumberOfCPUs()1089*490215a3Smrg u32 GetNumberOfCPUs() {
1090*490215a3Smrg   return (u32)sysconf(_SC_NPROCESSORS_ONLN);
1091*490215a3Smrg }
1092*490215a3Smrg 
1093*490215a3Smrg }  // namespace __sanitizer
1094*490215a3Smrg 
1095*490215a3Smrg #endif  // SANITIZER_MAC
1096