blob: d448ddaba648322bb922043ce5942c0da99b8341 [file] [log] [blame]
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +00001//===-- 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//
Alexander Potapenko768e3152014-02-03 15:32:19 +000010// This file is shared between various sanitizers' runtime libraries and
11// implements OSX-specific functions.
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000012//===----------------------------------------------------------------------===//
13
Evgeniy Stepanov0af67232013-03-19 14:33:38 +000014#include "sanitizer_platform.h"
15#if SANITIZER_MAC
16
Alexander Potapenkod895ae92013-02-06 14:41:15 +000017// 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>
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000023
Alexey Samsonov4b1f1032012-06-07 07:13:46 +000024#include "sanitizer_common.h"
Alexander Potapenko789e3e12014-01-31 13:10:07 +000025#include "sanitizer_flags.h"
Alexey Samsonov5bbf8292012-06-05 14:25:27 +000026#include "sanitizer_internal_defs.h"
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000027#include "sanitizer_libc.h"
Alexander Potapenko768e3152014-02-03 15:32:19 +000028#include "sanitizer_mac.h"
Alexey Samsonov7a36e612013-09-10 14:36:16 +000029#include "sanitizer_placement_new.h"
Ismail Pazarbasi0da8da52015-05-12 21:30:16 +000030#include "sanitizer_platform_limits_posix.h"
Alexey Samsonov28a98952012-06-07 06:15:12 +000031#include "sanitizer_procmaps.h"
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000032
Chris Bienemane13272a2015-06-23 21:39:49 +000033#if !SANITIZER_IOS
Alexey Samsonov0c53a382012-06-14 14:07:21 +000034#include <crt_externs.h> // for _NSGetEnviron
Chris Bienemane13272a2015-06-23 21:39:49 +000035#else
36extern char **environ;
37#endif
38
Ismail Pazarbasib981dc82015-05-12 20:47:21 +000039#include <errno.h>
Alexey Samsonov4b1f1032012-06-07 07:13:46 +000040#include <fcntl.h>
Ismail Pazarbasib981dc82015-05-12 20:47:21 +000041#include <libkern/OSAtomic.h>
Anna Zaks22490492015-02-27 03:12:19 +000042#include <mach-o/dyld.h>
Ismail Pazarbasib981dc82015-05-12 20:47:21 +000043#include <mach/mach.h>
Alexey Samsonov4b1f1032012-06-07 07:13:46 +000044#include <pthread.h>
Alexey Samsonov58a3c582012-06-18 08:44:30 +000045#include <sched.h>
Alexander Potapenko789e3e12014-01-31 13:10:07 +000046#include <signal.h>
Anna Zaks22490492015-02-27 03:12:19 +000047#include <stdlib.h>
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000048#include <sys/mman.h>
Alexey Samsonov4b1f1032012-06-07 07:13:46 +000049#include <sys/resource.h>
Alexey Samsonovdde1f112012-06-05 07:05:10 +000050#include <sys/stat.h>
Alexander Potapenko768e3152014-02-03 15:32:19 +000051#include <sys/sysctl.h>
Alexey Samsonovdde1f112012-06-05 07:05:10 +000052#include <sys/types.h>
Alexey Samsonov03c8b842012-06-05 08:32:53 +000053#include <unistd.h>
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000054
55namespace __sanitizer {
56
Peter Collingbourne6f4be192013-05-08 14:43:49 +000057#include "sanitizer_syscall_generic.inc"
58
Alexey Samsonov4b1f1032012-06-07 07:13:46 +000059// ---------------------- sanitizer_libc.h
Peter Collingbourne8e110ce2013-05-08 15:07:12 +000060uptr internal_mmap(void *addr, size_t length, int prot, int flags,
61 int fd, u64 offset) {
62 return (uptr)mmap(addr, length, prot, flags, fd, offset);
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000063}
64
Peter Collingbourne8e110ce2013-05-08 15:07:12 +000065uptr internal_munmap(void *addr, uptr length) {
Alexey Samsonov7ac77d62012-06-05 09:49:25 +000066 return munmap(addr, length);
67}
68
Timur Iskhodzhanovea1f3322015-04-10 15:02:19 +000069int internal_mprotect(void *addr, uptr length, int prot) {
70 return mprotect(addr, length, prot);
71}
72
Peter Collingbourne6f4be192013-05-08 14:43:49 +000073uptr internal_close(fd_t fd) {
Alexey Samsonov03c8b842012-06-05 08:32:53 +000074 return close(fd);
75}
76
Peter Collingbourne6f4be192013-05-08 14:43:49 +000077uptr internal_open(const char *filename, int flags) {
Alexey Samsonov39313b72013-02-01 15:58:46 +000078 return open(filename, flags);
79}
80
Peter Collingbourne6f4be192013-05-08 14:43:49 +000081uptr internal_open(const char *filename, int flags, u32 mode) {
Alexey Samsonov39313b72013-02-01 15:58:46 +000082 return open(filename, flags, mode);
83}
84
Alexey Samsonov03c8b842012-06-05 08:32:53 +000085uptr internal_read(fd_t fd, void *buf, uptr count) {
86 return read(fd, buf, count);
87}
88
89uptr internal_write(fd_t fd, const void *buf, uptr count) {
90 return write(fd, buf, count);
91}
92
Peter Collingbourne6f4be192013-05-08 14:43:49 +000093uptr internal_stat(const char *path, void *buf) {
Alexey Samsonov576e2702013-02-04 10:31:39 +000094 return stat(path, (struct stat *)buf);
Alexey Samsonov2c5cbd22013-02-04 10:16:50 +000095}
96
Peter Collingbourne6f4be192013-05-08 14:43:49 +000097uptr internal_lstat(const char *path, void *buf) {
Alexey Samsonov576e2702013-02-04 10:31:39 +000098 return lstat(path, (struct stat *)buf);
Alexey Samsonov2c5cbd22013-02-04 10:16:50 +000099}
100
Peter Collingbourne6f4be192013-05-08 14:43:49 +0000101uptr internal_fstat(fd_t fd, void *buf) {
Alexey Samsonov576e2702013-02-04 10:31:39 +0000102 return fstat(fd, (struct stat *)buf);
Alexey Samsonov2c5cbd22013-02-04 10:16:50 +0000103}
104
Alexey Samsonovca2b5d72012-06-06 07:30:33 +0000105uptr internal_filesize(fd_t fd) {
Alexey Samsonovce8d4972012-08-02 10:09:31 +0000106 struct stat st;
Alexey Samsonov2c5cbd22013-02-04 10:16:50 +0000107 if (internal_fstat(fd, &st))
Alexey Samsonovca2b5d72012-06-06 07:30:33 +0000108 return -1;
109 return (uptr)st.st_size;
110}
111
Peter Collingbourne6f4be192013-05-08 14:43:49 +0000112uptr internal_dup2(int oldfd, int newfd) {
Alexey Samsonovca2b5d72012-06-06 07:30:33 +0000113 return dup2(oldfd, newfd);
114}
115
Alexey Samsonovf6d21252012-09-05 14:48:24 +0000116uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
117 return readlink(path, buf, bufsize);
118}
119
Kuba Breckac52f3002014-12-29 02:18:59 +0000120uptr internal_unlink(const char *path) {
121 return unlink(path);
122}
123
Peter Collingbourne6f4be192013-05-08 14:43:49 +0000124uptr internal_sched_yield() {
Alexey Samsonov58a3c582012-06-18 08:44:30 +0000125 return sched_yield();
126}
127
Alexey Samsonovaadd1f22013-02-20 13:54:32 +0000128void internal__exit(int exitcode) {
129 _exit(exitcode);
130}
131
Peter Collingbourneffaf2ea2013-05-17 16:56:53 +0000132uptr internal_getpid() {
133 return getpid();
134}
135
Alexander Potapenko789e3e12014-01-31 13:10:07 +0000136int internal_sigaction(int signum, const void *act, void *oldact) {
137 return sigaction(signum,
138 (struct sigaction *)act, (struct sigaction *)oldact);
139}
140
Ismail Pazarbasi6fb3b4b2015-05-12 20:56:44 +0000141void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); }
142
143uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
144 __sanitizer_sigset_t *oldset) {
145 return sigprocmask(how, set, oldset);
146}
147
Alexander Potapenko4a6cac42014-05-13 16:17:54 +0000148int internal_fork() {
149 // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
150 return fork();
151}
152
Evgeniy Stepanov567e5162014-05-27 12:37:52 +0000153uptr internal_rename(const char *oldpath, const char *newpath) {
154 return rename(oldpath, newpath);
155}
156
157uptr internal_ftruncate(fd_t fd, uptr size) {
158 return ftruncate(fd, size);
159}
160
Alexey Samsonov4b1f1032012-06-07 07:13:46 +0000161// ----------------- sanitizer_common.h
Alexey Samsonovae9b18b2012-11-09 14:45:30 +0000162bool FileExists(const char *filename) {
163 struct stat st;
164 if (stat(filename, &st))
165 return false;
166 // Sanity check: filename is a regular file.
167 return S_ISREG(st.st_mode);
168}
169
Dmitry Vyukov56faa552012-10-02 12:58:14 +0000170uptr GetTid() {
171 return reinterpret_cast<uptr>(pthread_self());
172}
173
Alexey Samsonovcf4d3a02012-06-07 07:32:00 +0000174void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
Alexey Samsonov4b1f1032012-06-07 07:13:46 +0000175 uptr *stack_bottom) {
176 CHECK(stack_top);
177 CHECK(stack_bottom);
178 uptr stacksize = pthread_get_stacksize_np(pthread_self());
Alexander Potapenkof6ff6b02014-02-03 16:42:29 +0000179 // pthread_get_stacksize_np() returns an incorrect stack size for the main
180 // thread on Mavericks. See
181 // https://code.google.com/p/address-sanitizer/issues/detail?id=261
Kuba Brecka0078cea72014-11-05 18:55:38 +0000182 if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
Alexander Potapenkof6ff6b02014-02-03 16:42:29 +0000183 stacksize == (1 << 19)) {
184 struct rlimit rl;
185 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
186 // Most often rl.rlim_cur will be the desired 8M.
187 if (rl.rlim_cur < kMaxThreadStackSize) {
188 stacksize = rl.rlim_cur;
189 } else {
190 stacksize = kMaxThreadStackSize;
191 }
192 }
Alexey Samsonov4b1f1032012-06-07 07:13:46 +0000193 void *stackaddr = pthread_get_stackaddr_np(pthread_self());
194 *stack_top = (uptr)stackaddr;
Alexey Samsonovcf4d3a02012-06-07 07:32:00 +0000195 *stack_bottom = *stack_top - stacksize;
Alexey Samsonov4b1f1032012-06-07 07:13:46 +0000196}
197
Chris Bienemane13272a2015-06-23 21:39:49 +0000198char **GetEnviron() {
199#if !SANITIZER_IOS
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000200 char ***env_ptr = _NSGetEnviron();
Alexander Potapenkofa82ba92013-11-13 13:34:53 +0000201 if (!env_ptr) {
202 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
203 "called after libSystem_initializer().\n");
204 CHECK(env_ptr);
205 }
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000206 char **environ = *env_ptr;
Chris Bienemane13272a2015-06-23 21:39:49 +0000207#endif
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000208 CHECK(environ);
Chris Bienemane13272a2015-06-23 21:39:49 +0000209 return environ;
210}
211
212const char *GetEnv(const char *name) {
213 char **env = GetEnviron();
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000214 uptr name_len = internal_strlen(name);
Chris Bienemane13272a2015-06-23 21:39:49 +0000215 while (*env != 0) {
216 uptr len = internal_strlen(*env);
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000217 if (len > name_len) {
Chris Bienemane13272a2015-06-23 21:39:49 +0000218 const char *p = *env;
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000219 if (!internal_memcmp(p, name, name_len) &&
220 p[name_len] == '=') { // Match.
Chris Bienemane13272a2015-06-23 21:39:49 +0000221 return *env + name_len + 1; // String starting after =.
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000222 }
223 }
Chris Bienemane13272a2015-06-23 21:39:49 +0000224 env++;
Alexey Samsonov0c53a382012-06-14 14:07:21 +0000225 }
226 return 0;
227}
Alexey Samsonov4b1f1032012-06-07 07:13:46 +0000228
Anna Zaks22490492015-02-27 03:12:19 +0000229uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
230 CHECK_LE(kMaxPathLength, buf_len);
231
232 // On OS X the executable path is saved to the stack by dyld. Reading it
233 // from there is much faster than calling dladdr, especially for large
234 // binaries with symbols.
235 InternalScopedString exe_path(kMaxPathLength);
236 uint32_t size = exe_path.size();
237 if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
238 realpath(exe_path.data(), buf) != 0) {
239 return internal_strlen(buf);
240 }
241 return 0;
242}
243
Evgeniy Stepanov30257172015-07-28 21:01:42 +0000244uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
245 return ReadBinaryName(buf, buf_len);
246}
247
Alexey Samsonov97ca3062012-09-17 09:12:39 +0000248void ReExec() {
249 UNIMPLEMENTED();
250}
251
Peter Collingbourneb69b8a42013-05-20 17:05:29 +0000252uptr GetPageSize() {
253 return sysconf(_SC_PAGESIZE);
254}
255
Alexey Samsonova097f7b2013-03-14 13:30:56 +0000256BlockingMutex::BlockingMutex() {
257 internal_memset(this, 0, sizeof(*this));
258}
259
Dmitry Vyukovf22982b2013-01-14 07:51:39 +0000260void BlockingMutex::Lock() {
261 CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
Kostya Serebryany459df6f2013-02-26 12:59:06 +0000262 CHECK_EQ(OS_SPINLOCK_INIT, 0);
263 CHECK_NE(owner_, (uptr)pthread_self());
Dmitry Vyukovf22982b2013-01-14 07:51:39 +0000264 OSSpinLockLock((OSSpinLock*)&opaque_storage_);
265 CHECK(!owner_);
266 owner_ = (uptr)pthread_self();
267}
268
269void BlockingMutex::Unlock() {
270 CHECK(owner_ == (uptr)pthread_self());
271 owner_ = 0;
272 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
273}
274
Alexey Samsonovdb7d9652013-03-11 15:45:20 +0000275void BlockingMutex::CheckLocked() {
276 CHECK_EQ((uptr)pthread_self(), owner_);
277}
278
Dmitry Vyukovc9e304a2013-06-06 13:00:32 +0000279u64 NanoTime() {
280 return 0;
281}
282
Evgeniy Stepanov5697b582013-03-13 08:19:53 +0000283uptr GetTlsSize() {
284 return 0;
285}
286
287void InitTlsSize() {
288}
289
Sergey Matveev954c6ef12013-05-07 14:41:43 +0000290void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
291 uptr *tls_addr, uptr *tls_size) {
Dmitry Vyukovce0247c2013-06-06 13:20:40 +0000292#ifndef SANITIZER_GO
Sergey Matveev954c6ef12013-05-07 14:41:43 +0000293 uptr stack_top, stack_bottom;
294 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
295 *stk_addr = stack_bottom;
296 *stk_size = stack_top - stack_bottom;
297 *tls_addr = 0;
298 *tls_size = 0;
Dmitry Vyukovce0247c2013-06-06 13:20:40 +0000299#else
300 *stk_addr = 0;
301 *stk_size = 0;
302 *tls_addr = 0;
303 *tls_size = 0;
304#endif
Sergey Matveev954c6ef12013-05-07 14:41:43 +0000305}
306
Alexey Samsonov7a36e612013-09-10 14:36:16 +0000307uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
308 string_predicate_t filter) {
309 MemoryMappingLayout memory_mapping(false);
Alexey Samsonov64ffa592013-12-25 08:39:38 +0000310 return memory_mapping.DumpListOfModules(modules, max_modules, filter);
Alexey Samsonov7a36e612013-09-10 14:36:16 +0000311}
312
Alexander Potapenko789e3e12014-01-31 13:10:07 +0000313bool IsDeadlySignal(int signum) {
314 return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
315}
316
Alexander Potapenko768e3152014-02-03 15:32:19 +0000317MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
318
319MacosVersion GetMacosVersionInternal() {
320 int mib[2] = { CTL_KERN, KERN_OSRELEASE };
321 char version[100];
322 uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
323 for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
324 // Get the version length.
325 CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
326 CHECK_LT(len, maxlen);
327 CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
328 switch (version[0]) {
329 case '9': return MACOS_VERSION_LEOPARD;
330 case '1': {
331 switch (version[1]) {
332 case '0': return MACOS_VERSION_SNOW_LEOPARD;
333 case '1': return MACOS_VERSION_LION;
334 case '2': return MACOS_VERSION_MOUNTAIN_LION;
335 case '3': return MACOS_VERSION_MAVERICKS;
Kuba Breckaf4bdbde2014-11-05 18:53:22 +0000336 case '4': return MACOS_VERSION_YOSEMITE;
Kuba Brecka731089b2014-12-16 04:46:15 +0000337 default:
338 if (IsDigit(version[1]))
339 return MACOS_VERSION_UNKNOWN_NEWER;
340 else
341 return MACOS_VERSION_UNKNOWN;
Alexander Potapenko768e3152014-02-03 15:32:19 +0000342 }
343 }
344 default: return MACOS_VERSION_UNKNOWN;
345 }
346}
347
348MacosVersion GetMacosVersion() {
349 atomic_uint32_t *cache =
350 reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
351 MacosVersion result =
352 static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
353 if (result == MACOS_VERSION_UNINITIALIZED) {
354 result = GetMacosVersionInternal();
355 atomic_store(cache, result, memory_order_release);
356 }
357 return result;
358}
359
Kostya Serebryany6c54a6b2014-12-09 01:22:59 +0000360uptr GetRSS() {
Ismail Pazarbasib981dc82015-05-12 20:47:21 +0000361 struct task_basic_info info;
362 unsigned count = TASK_BASIC_INFO_COUNT;
363 kern_return_t result =
364 task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
365 if (UNLIKELY(result != KERN_SUCCESS)) {
366 Report("Cannot get task info. Error: %d\n", result);
367 Die();
368 }
369 return info.resident_size;
Kostya Serebryany6c54a6b2014-12-09 01:22:59 +0000370}
371
Kostya Serebryany43eb7732014-12-16 19:13:01 +0000372void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
Kostya Serebryany5f5bc4a2014-12-16 21:06:07 +0000373void internal_join_thread(void *th) { }
Kostya Serebryany43eb7732014-12-16 19:13:01 +0000374
Dmitry Vyukovb79ac882015-03-02 17:36:02 +0000375void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
376 ucontext_t *ucontext = (ucontext_t*)context;
Chris Bienemane13272a2015-06-23 21:39:49 +0000377# if defined(__aarch64__)
378 *pc = ucontext->uc_mcontext->__ss.__pc;
379# if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
380 *bp = ucontext->uc_mcontext->__ss.__fp;
381# else
382 *bp = ucontext->uc_mcontext->__ss.__lr;
383# endif
384 *sp = ucontext->uc_mcontext->__ss.__sp;
385# elif defined(__x86_64__)
Dmitry Vyukovb79ac882015-03-02 17:36:02 +0000386 *pc = ucontext->uc_mcontext->__ss.__rip;
387 *bp = ucontext->uc_mcontext->__ss.__rbp;
388 *sp = ucontext->uc_mcontext->__ss.__rsp;
Chris Bienemane13272a2015-06-23 21:39:49 +0000389# elif defined(__arm__)
390 *pc = ucontext->uc_mcontext->__ss.__pc;
391 *bp = ucontext->uc_mcontext->__ss.__r[7];
392 *sp = ucontext->uc_mcontext->__ss.__sp;
393# elif defined(__i386__)
Dmitry Vyukovb79ac882015-03-02 17:36:02 +0000394 *pc = ucontext->uc_mcontext->__ss.__eip;
395 *bp = ucontext->uc_mcontext->__ss.__ebp;
396 *sp = ucontext->uc_mcontext->__ss.__esp;
Chris Bienemane13272a2015-06-23 21:39:49 +0000397# else
398# error "Unknown architecture"
399# endif
Dmitry Vyukovb79ac882015-03-02 17:36:02 +0000400}
401
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +0000402} // namespace __sanitizer
403
Alexey Samsonova0e28a72013-04-03 07:24:35 +0000404#endif // SANITIZER_MAC