1 //===-- sanitizer_mac.cc --------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between various sanitizers' runtime libraries and
11 // implements OSX-specific functions.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_platform.h"
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
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"
32 #include <crt_externs.h> // for _NSGetEnviron
38 #include <sys/resource.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
43 #include <libkern/OSAtomic.h>
46 namespace __sanitizer {
48 #include "sanitizer_syscall_generic.inc"
50 // ---------------------- sanitizer_libc.h
51 uptr internal_mmap(void *addr, size_t length, int prot, int flags,
53 return (uptr)mmap(addr, length, prot, flags, fd, offset);
56 uptr internal_munmap(void *addr, uptr length) {
57 return munmap(addr, length);
60 uptr internal_close(fd_t fd) {
64 uptr internal_open(const char *filename, int flags) {
65 return open(filename, flags);
68 uptr internal_open(const char *filename, int flags, u32 mode) {
69 return open(filename, flags, mode);
72 uptr OpenFile(const char *filename, bool write) {
73 return internal_open(filename,
74 write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
77 uptr internal_read(fd_t fd, void *buf, uptr count) {
78 return read(fd, buf, count);
81 uptr internal_write(fd_t fd, const void *buf, uptr count) {
82 return write(fd, buf, count);
85 uptr internal_stat(const char *path, void *buf) {
86 return stat(path, (struct stat *)buf);
89 uptr internal_lstat(const char *path, void *buf) {
90 return lstat(path, (struct stat *)buf);
93 uptr internal_fstat(fd_t fd, void *buf) {
94 return fstat(fd, (struct stat *)buf);
97 uptr internal_filesize(fd_t fd) {
99 if (internal_fstat(fd, &st))
101 return (uptr)st.st_size;
104 uptr internal_dup2(int oldfd, int newfd) {
105 return dup2(oldfd, newfd);
108 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
109 return readlink(path, buf, bufsize);
112 uptr internal_unlink(const char *path) {
116 uptr internal_sched_yield() {
117 return sched_yield();
120 void internal__exit(int exitcode) {
124 uptr internal_getpid() {
128 int internal_sigaction(int signum, const void *act, void *oldact) {
129 return sigaction(signum,
130 (struct sigaction *)act, (struct sigaction *)oldact);
133 int internal_fork() {
134 // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
138 uptr internal_rename(const char *oldpath, const char *newpath) {
139 return rename(oldpath, newpath);
142 uptr internal_ftruncate(fd_t fd, uptr size) {
143 return ftruncate(fd, size);
146 // ----------------- sanitizer_common.h
147 bool FileExists(const char *filename) {
149 if (stat(filename, &st))
151 // Sanity check: filename is a regular file.
152 return S_ISREG(st.st_mode);
156 return reinterpret_cast<uptr>(pthread_self());
159 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
160 uptr *stack_bottom) {
163 uptr stacksize = pthread_get_stacksize_np(pthread_self());
164 // pthread_get_stacksize_np() returns an incorrect stack size for the main
165 // thread on Mavericks. See
166 // https://code.google.com/p/address-sanitizer/issues/detail?id=261
167 if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
168 stacksize == (1 << 19)) {
170 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
171 // Most often rl.rlim_cur will be the desired 8M.
172 if (rl.rlim_cur < kMaxThreadStackSize) {
173 stacksize = rl.rlim_cur;
175 stacksize = kMaxThreadStackSize;
178 void *stackaddr = pthread_get_stackaddr_np(pthread_self());
179 *stack_top = (uptr)stackaddr;
180 *stack_bottom = *stack_top - stacksize;
183 const char *GetEnv(const char *name) {
184 char ***env_ptr = _NSGetEnviron();
186 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
187 "called after libSystem_initializer().\n");
190 char **environ = *env_ptr;
192 uptr name_len = internal_strlen(name);
193 while (*environ != 0) {
194 uptr len = internal_strlen(*environ);
195 if (len > name_len) {
196 const char *p = *environ;
197 if (!internal_memcmp(p, name, name_len) &&
198 p[name_len] == '=') { // Match.
199 return *environ + name_len + 1; // String starting after =.
211 void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
213 // Nothing here for now.
217 return sysconf(_SC_PAGESIZE);
220 BlockingMutex::BlockingMutex() {
221 internal_memset(this, 0, sizeof(*this));
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_);
230 owner_ = (uptr)pthread_self();
233 void BlockingMutex::Unlock() {
234 CHECK(owner_ == (uptr)pthread_self());
236 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
239 void BlockingMutex::CheckLocked() {
240 CHECK_EQ((uptr)pthread_self(), owner_);
254 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
255 uptr *tls_addr, uptr *tls_size) {
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;
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);
277 bool IsDeadlySignal(int signum) {
278 return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
281 MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
283 MacosVersion GetMacosVersionInternal() {
284 int mib[2] = { CTL_KERN, KERN_OSRELEASE };
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;
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 case '4': return MACOS_VERSION_YOSEMITE;
302 if (IsDigit(version[1]))
303 return MACOS_VERSION_UNKNOWN_NEWER;
305 return MACOS_VERSION_UNKNOWN;
308 default: return MACOS_VERSION_UNKNOWN;
312 MacosVersion GetMacosVersion() {
313 atomic_uint32_t *cache =
314 reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
315 MacosVersion result =
316 static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
317 if (result == MACOS_VERSION_UNINITIALIZED) {
318 result = GetMacosVersionInternal();
319 atomic_store(cache, result, memory_order_release);
328 void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
329 void internal_join_thread(void *th) { }
331 } // namespace __sanitizer
333 #endif // SANITIZER_MAC