]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
Update compiler-rt to trunk r228651. This enables using Address
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_mac.cc
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
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
56 uptr internal_munmap(void *addr, uptr length) {
57   return munmap(addr, length);
58 }
59
60 uptr internal_close(fd_t fd) {
61   return close(fd);
62 }
63
64 uptr internal_open(const char *filename, int flags) {
65   return open(filename, flags);
66 }
67
68 uptr internal_open(const char *filename, int flags, u32 mode) {
69   return open(filename, flags, mode);
70 }
71
72 uptr OpenFile(const char *filename, bool write) {
73   return internal_open(filename,
74       write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
75 }
76
77 uptr internal_read(fd_t fd, void *buf, uptr count) {
78   return read(fd, buf, count);
79 }
80
81 uptr internal_write(fd_t fd, const void *buf, uptr count) {
82   return write(fd, buf, count);
83 }
84
85 uptr internal_stat(const char *path, void *buf) {
86   return stat(path, (struct stat *)buf);
87 }
88
89 uptr internal_lstat(const char *path, void *buf) {
90   return lstat(path, (struct stat *)buf);
91 }
92
93 uptr internal_fstat(fd_t fd, void *buf) {
94   return fstat(fd, (struct stat *)buf);
95 }
96
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
104 uptr internal_dup2(int oldfd, int newfd) {
105   return dup2(oldfd, newfd);
106 }
107
108 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
109   return readlink(path, buf, bufsize);
110 }
111
112 uptr internal_unlink(const char *path) {
113   return unlink(path);
114 }
115
116 uptr internal_sched_yield() {
117   return sched_yield();
118 }
119
120 void internal__exit(int exitcode) {
121   _exit(exitcode);
122 }
123
124 uptr internal_getpid() {
125   return getpid();
126 }
127
128 int internal_sigaction(int signum, const void *act, void *oldact) {
129   return sigaction(signum,
130                    (struct sigaction *)act, (struct sigaction *)oldact);
131 }
132
133 int internal_fork() {
134   // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
135   return fork();
136 }
137
138 uptr internal_rename(const char *oldpath, const char *newpath) {
139   return rename(oldpath, newpath);
140 }
141
142 uptr internal_ftruncate(fd_t fd, uptr size) {
143   return ftruncate(fd, size);
144 }
145
146 // ----------------- sanitizer_common.h
147 bool FileExists(const char *filename) {
148   struct stat st;
149   if (stat(filename, &st))
150     return false;
151   // Sanity check: filename is a regular file.
152   return S_ISREG(st.st_mode);
153 }
154
155 uptr GetTid() {
156   return reinterpret_cast<uptr>(pthread_self());
157 }
158
159 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
160                                 uptr *stack_bottom) {
161   CHECK(stack_top);
162   CHECK(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))  {
169     struct rlimit rl;
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;
174     } else {
175       stacksize = kMaxThreadStackSize;
176     }
177   }
178   void *stackaddr = pthread_get_stackaddr_np(pthread_self());
179   *stack_top = (uptr)stackaddr;
180   *stack_bottom = *stack_top - stacksize;
181 }
182
183 const char *GetEnv(const char *name) {
184   char ***env_ptr = _NSGetEnviron();
185   if (!env_ptr) {
186     Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
187            "called after libSystem_initializer().\n");
188     CHECK(env_ptr);
189   }
190   char **environ = *env_ptr;
191   CHECK(environ);
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 =.
200       }
201     }
202     environ++;
203   }
204   return 0;
205 }
206
207 void ReExec() {
208   UNIMPLEMENTED();
209 }
210
211 void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
212   (void)args;
213   // Nothing here for now.
214 }
215
216 uptr GetPageSize() {
217   return sysconf(_SC_PAGESIZE);
218 }
219
220 BlockingMutex::BlockingMutex() {
221   internal_memset(this, 0, sizeof(*this));
222 }
223
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
233 void BlockingMutex::Unlock() {
234   CHECK(owner_ == (uptr)pthread_self());
235   owner_ = 0;
236   OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
237 }
238
239 void BlockingMutex::CheckLocked() {
240   CHECK_EQ((uptr)pthread_self(), owner_);
241 }
242
243 u64 NanoTime() {
244   return 0;
245 }
246
247 uptr GetTlsSize() {
248   return 0;
249 }
250
251 void InitTlsSize() {
252 }
253
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
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
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
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         case '4': return MACOS_VERSION_YOSEMITE;
301         default:
302           if (IsDigit(version[1]))
303             return MACOS_VERSION_UNKNOWN_NEWER;
304           else
305             return MACOS_VERSION_UNKNOWN;
306       }
307     }
308     default: return MACOS_VERSION_UNKNOWN;
309   }
310 }
311
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);
320   }
321   return result;
322 }
323
324 uptr GetRSS() {
325   return 0;
326 }
327
328 void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
329 void internal_join_thread(void *th) { }
330
331 }  // namespace __sanitizer
332
333 #endif  // SANITIZER_MAC