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