• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_mac.cc --------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is shared between various sanitizers' runtime libraries and
11 // implements OSX-specific functions.
12 //===----------------------------------------------------------------------===//
13 
14 #include "sanitizer_platform.h"
15 #if SANITIZER_MAC
16 
17 // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
18 // the clients will most certainly use 64-bit ones as well.
19 #ifndef _DARWIN_USE_64_BIT_INODE
20 #define _DARWIN_USE_64_BIT_INODE 1
21 #endif
22 #include <stdio.h>
23 
24 #include "sanitizer_common.h"
25 #include "sanitizer_flags.h"
26 #include "sanitizer_internal_defs.h"
27 #include "sanitizer_libc.h"
28 #include "sanitizer_mac.h"
29 #include "sanitizer_placement_new.h"
30 #include "sanitizer_procmaps.h"
31 
32 #include <crt_externs.h>  // for _NSGetEnviron
33 #include <fcntl.h>
34 #include <pthread.h>
35 #include <sched.h>
36 #include <signal.h>
37 #include <sys/mman.h>
38 #include <sys/resource.h>
39 #include <sys/stat.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
42 #include <unistd.h>
43 #include <libkern/OSAtomic.h>
44 #include <errno.h>
45 
46 namespace __sanitizer {
47 
48 #include "sanitizer_syscall_generic.inc"
49 
50 // ---------------------- sanitizer_libc.h
internal_mmap(void * addr,size_t length,int prot,int flags,int fd,u64 offset)51 uptr internal_mmap(void *addr, size_t length, int prot, int flags,
52                    int fd, u64 offset) {
53   return (uptr)mmap(addr, length, prot, flags, fd, offset);
54 }
55 
internal_munmap(void * addr,uptr length)56 uptr internal_munmap(void *addr, uptr length) {
57   return munmap(addr, length);
58 }
59 
internal_close(fd_t fd)60 uptr internal_close(fd_t fd) {
61   return close(fd);
62 }
63 
internal_open(const char * filename,int flags)64 uptr internal_open(const char *filename, int flags) {
65   return open(filename, flags);
66 }
67 
internal_open(const char * filename,int flags,u32 mode)68 uptr internal_open(const char *filename, int flags, u32 mode) {
69   return open(filename, flags, mode);
70 }
71 
OpenFile(const char * filename,bool write)72 uptr OpenFile(const char *filename, bool write) {
73   return internal_open(filename,
74       write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
75 }
76 
internal_read(fd_t fd,void * buf,uptr count)77 uptr internal_read(fd_t fd, void *buf, uptr count) {
78   return read(fd, buf, count);
79 }
80 
internal_write(fd_t fd,const void * buf,uptr count)81 uptr internal_write(fd_t fd, const void *buf, uptr count) {
82   return write(fd, buf, count);
83 }
84 
internal_stat(const char * path,void * buf)85 uptr internal_stat(const char *path, void *buf) {
86   return stat(path, (struct stat *)buf);
87 }
88 
internal_lstat(const char * path,void * buf)89 uptr internal_lstat(const char *path, void *buf) {
90   return lstat(path, (struct stat *)buf);
91 }
92 
internal_fstat(fd_t fd,void * buf)93 uptr internal_fstat(fd_t fd, void *buf) {
94   return fstat(fd, (struct stat *)buf);
95 }
96 
internal_filesize(fd_t fd)97 uptr internal_filesize(fd_t fd) {
98   struct stat st;
99   if (internal_fstat(fd, &st))
100     return -1;
101   return (uptr)st.st_size;
102 }
103 
internal_dup2(int oldfd,int newfd)104 uptr internal_dup2(int oldfd, int newfd) {
105   return dup2(oldfd, newfd);
106 }
107 
internal_readlink(const char * path,char * buf,uptr bufsize)108 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
109   return readlink(path, buf, bufsize);
110 }
111 
internal_sched_yield()112 uptr internal_sched_yield() {
113   return sched_yield();
114 }
115 
internal__exit(int exitcode)116 void internal__exit(int exitcode) {
117   _exit(exitcode);
118 }
119 
internal_getpid()120 uptr internal_getpid() {
121   return getpid();
122 }
123 
internal_sigaction(int signum,const void * act,void * oldact)124 int internal_sigaction(int signum, const void *act, void *oldact) {
125   return sigaction(signum,
126                    (struct sigaction *)act, (struct sigaction *)oldact);
127 }
128 
internal_fork()129 int internal_fork() {
130   // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
131   return fork();
132 }
133 
internal_rename(const char * oldpath,const char * newpath)134 uptr internal_rename(const char *oldpath, const char *newpath) {
135   return rename(oldpath, newpath);
136 }
137 
internal_ftruncate(fd_t fd,uptr size)138 uptr internal_ftruncate(fd_t fd, uptr size) {
139   return ftruncate(fd, size);
140 }
141 
142 // ----------------- sanitizer_common.h
FileExists(const char * filename)143 bool FileExists(const char *filename) {
144   struct stat st;
145   if (stat(filename, &st))
146     return false;
147   // Sanity check: filename is a regular file.
148   return S_ISREG(st.st_mode);
149 }
150 
GetTid()151 uptr GetTid() {
152   return reinterpret_cast<uptr>(pthread_self());
153 }
154 
GetThreadStackTopAndBottom(bool at_initialization,uptr * stack_top,uptr * stack_bottom)155 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
156                                 uptr *stack_bottom) {
157   CHECK(stack_top);
158   CHECK(stack_bottom);
159   uptr stacksize = pthread_get_stacksize_np(pthread_self());
160   // pthread_get_stacksize_np() returns an incorrect stack size for the main
161   // thread on Mavericks. See
162   // https://code.google.com/p/address-sanitizer/issues/detail?id=261
163   if ((GetMacosVersion() == MACOS_VERSION_MAVERICKS) && at_initialization &&
164       stacksize == (1 << 19))  {
165     struct rlimit rl;
166     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
167     // Most often rl.rlim_cur will be the desired 8M.
168     if (rl.rlim_cur < kMaxThreadStackSize) {
169       stacksize = rl.rlim_cur;
170     } else {
171       stacksize = kMaxThreadStackSize;
172     }
173   }
174   void *stackaddr = pthread_get_stackaddr_np(pthread_self());
175   *stack_top = (uptr)stackaddr;
176   *stack_bottom = *stack_top - stacksize;
177 }
178 
GetEnv(const char * name)179 const char *GetEnv(const char *name) {
180   char ***env_ptr = _NSGetEnviron();
181   if (!env_ptr) {
182     Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
183            "called after libSystem_initializer().\n");
184     CHECK(env_ptr);
185   }
186   char **environ = *env_ptr;
187   CHECK(environ);
188   uptr name_len = internal_strlen(name);
189   while (*environ != 0) {
190     uptr len = internal_strlen(*environ);
191     if (len > name_len) {
192       const char *p = *environ;
193       if (!internal_memcmp(p, name, name_len) &&
194           p[name_len] == '=') {  // Match.
195         return *environ + name_len + 1;  // String starting after =.
196       }
197     }
198     environ++;
199   }
200   return 0;
201 }
202 
ReExec()203 void ReExec() {
204   UNIMPLEMENTED();
205 }
206 
PrepareForSandboxing(__sanitizer_sandbox_arguments * args)207 void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
208   (void)args;
209   // Nothing here for now.
210 }
211 
GetPageSize()212 uptr GetPageSize() {
213   return sysconf(_SC_PAGESIZE);
214 }
215 
BlockingMutex(LinkerInitialized)216 BlockingMutex::BlockingMutex(LinkerInitialized) {
217   // We assume that OS_SPINLOCK_INIT is zero
218 }
219 
BlockingMutex()220 BlockingMutex::BlockingMutex() {
221   internal_memset(this, 0, sizeof(*this));
222 }
223 
Lock()224 void BlockingMutex::Lock() {
225   CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
226   CHECK_EQ(OS_SPINLOCK_INIT, 0);
227   CHECK_NE(owner_, (uptr)pthread_self());
228   OSSpinLockLock((OSSpinLock*)&opaque_storage_);
229   CHECK(!owner_);
230   owner_ = (uptr)pthread_self();
231 }
232 
Unlock()233 void BlockingMutex::Unlock() {
234   CHECK(owner_ == (uptr)pthread_self());
235   owner_ = 0;
236   OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
237 }
238 
CheckLocked()239 void BlockingMutex::CheckLocked() {
240   CHECK_EQ((uptr)pthread_self(), owner_);
241 }
242 
NanoTime()243 u64 NanoTime() {
244   return 0;
245 }
246 
GetTlsSize()247 uptr GetTlsSize() {
248   return 0;
249 }
250 
InitTlsSize()251 void InitTlsSize() {
252 }
253 
GetThreadStackAndTls(bool main,uptr * stk_addr,uptr * stk_size,uptr * tls_addr,uptr * tls_size)254 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
255                           uptr *tls_addr, uptr *tls_size) {
256 #ifndef SANITIZER_GO
257   uptr stack_top, stack_bottom;
258   GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
259   *stk_addr = stack_bottom;
260   *stk_size = stack_top - stack_bottom;
261   *tls_addr = 0;
262   *tls_size = 0;
263 #else
264   *stk_addr = 0;
265   *stk_size = 0;
266   *tls_addr = 0;
267   *tls_size = 0;
268 #endif
269 }
270 
GetListOfModules(LoadedModule * modules,uptr max_modules,string_predicate_t filter)271 uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
272                       string_predicate_t filter) {
273   MemoryMappingLayout memory_mapping(false);
274   return memory_mapping.DumpListOfModules(modules, max_modules, filter);
275 }
276 
IsDeadlySignal(int signum)277 bool IsDeadlySignal(int signum) {
278   return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
279 }
280 
281 MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
282 
GetMacosVersionInternal()283 MacosVersion GetMacosVersionInternal() {
284   int mib[2] = { CTL_KERN, KERN_OSRELEASE };
285   char version[100];
286   uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
287   for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
288   // Get the version length.
289   CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
290   CHECK_LT(len, maxlen);
291   CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
292   switch (version[0]) {
293     case '9': return MACOS_VERSION_LEOPARD;
294     case '1': {
295       switch (version[1]) {
296         case '0': return MACOS_VERSION_SNOW_LEOPARD;
297         case '1': return MACOS_VERSION_LION;
298         case '2': return MACOS_VERSION_MOUNTAIN_LION;
299         case '3': return MACOS_VERSION_MAVERICKS;
300         default: return MACOS_VERSION_UNKNOWN;
301       }
302     }
303     default: return MACOS_VERSION_UNKNOWN;
304   }
305 }
306 
GetMacosVersion()307 MacosVersion GetMacosVersion() {
308   atomic_uint32_t *cache =
309       reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
310   MacosVersion result =
311       static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
312   if (result == MACOS_VERSION_UNINITIALIZED) {
313     result = GetMacosVersionInternal();
314     atomic_store(cache, result, memory_order_release);
315   }
316   return result;
317 }
318 
319 }  // namespace __sanitizer
320 
321 #endif  // SANITIZER_MAC
322