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 #include "sanitizer_mac.h" 17 18 // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so 19 // the clients will most certainly use 64-bit ones as well. 20 #ifndef _DARWIN_USE_64_BIT_INODE 21 #define _DARWIN_USE_64_BIT_INODE 1 22 #endif 23 #include <stdio.h> 24 25 #include "sanitizer_common.h" 26 #include "sanitizer_file.h" 27 #include "sanitizer_flags.h" 28 #include "sanitizer_internal_defs.h" 29 #include "sanitizer_libc.h" 30 #include "sanitizer_placement_new.h" 31 #include "sanitizer_platform_limits_posix.h" 32 #include "sanitizer_procmaps.h" 33 34 #if !SANITIZER_IOS 35 #include <crt_externs.h> // for _NSGetEnviron 36 #else 37 extern char **environ; 38 #endif 39 40 #if defined(__has_include) && __has_include(<os/trace.h>) 41 #define SANITIZER_OS_TRACE 1 42 #include <os/trace.h> 43 #else 44 #define SANITIZER_OS_TRACE 0 45 #endif 46 47 #if !SANITIZER_IOS 48 #include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron 49 #else 50 extern "C" { 51 extern char ***_NSGetArgv(void); 52 } 53 #endif 54 55 #include <asl.h> 56 #include <dlfcn.h> // for dladdr() 57 #include <errno.h> 58 #include <fcntl.h> 59 #include <libkern/OSAtomic.h> 60 #include <mach-o/dyld.h> 61 #include <mach/mach.h> 62 #include <mach/mach_time.h> 63 #include <mach/vm_statistics.h> 64 #include <malloc/malloc.h> 65 #include <pthread.h> 66 #include <sched.h> 67 #include <signal.h> 68 #include <stdlib.h> 69 #include <sys/mman.h> 70 #include <sys/resource.h> 71 #include <sys/stat.h> 72 #include <sys/sysctl.h> 73 #include <sys/types.h> 74 #include <sys/wait.h> 75 #include <unistd.h> 76 #include <util.h> 77 78 // From <crt_externs.h>, but we don't have that file on iOS. 79 extern "C" { 80 extern char ***_NSGetArgv(void); 81 extern char ***_NSGetEnviron(void); 82 } 83 84 // From <mach/mach_vm.h>, but we don't have that file on iOS. 85 extern "C" { 86 extern kern_return_t mach_vm_region_recurse( 87 vm_map_t target_task, 88 mach_vm_address_t *address, 89 mach_vm_size_t *size, 90 natural_t *nesting_depth, 91 vm_region_recurse_info_t info, 92 mach_msg_type_number_t *infoCnt); 93 } 94 95 namespace __sanitizer { 96 97 #include "sanitizer_syscall_generic.inc" 98 99 // Direct syscalls, don't call libmalloc hooks (but not available on 10.6). 100 extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes, 101 off_t off) SANITIZER_WEAK_ATTRIBUTE; 102 extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE; 103 104 // ---------------------- sanitizer_libc.h 105 106 // From <mach/vm_statistics.h>, but not on older OSs. 107 #ifndef VM_MEMORY_SANITIZER 108 #define VM_MEMORY_SANITIZER 99 109 #endif 110 111 // XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of 112 // giant memory regions (i.e. shadow memory regions). 113 #define kXnuFastMmapFd 0x4 114 static size_t kXnuFastMmapThreshold = 2 << 30; // 2 GB 115 static bool use_xnu_fast_mmap = false; 116 117 uptr internal_mmap(void *addr, size_t length, int prot, int flags, 118 int fd, u64 offset) { 119 if (fd == -1) { 120 fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER); 121 if (length >= kXnuFastMmapThreshold) { 122 if (use_xnu_fast_mmap) fd |= kXnuFastMmapFd; 123 } 124 } 125 if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset); 126 return (uptr)mmap(addr, length, prot, flags, fd, offset); 127 } 128 129 uptr internal_munmap(void *addr, uptr length) { 130 if (&__munmap) return __munmap(addr, length); 131 return munmap(addr, length); 132 } 133 134 int internal_mprotect(void *addr, uptr length, int prot) { 135 return mprotect(addr, length, prot); 136 } 137 138 uptr internal_close(fd_t fd) { 139 return close(fd); 140 } 141 142 uptr internal_open(const char *filename, int flags) { 143 return open(filename, flags); 144 } 145 146 uptr internal_open(const char *filename, int flags, u32 mode) { 147 return open(filename, flags, mode); 148 } 149 150 uptr internal_read(fd_t fd, void *buf, uptr count) { 151 return read(fd, buf, count); 152 } 153 154 uptr internal_write(fd_t fd, const void *buf, uptr count) { 155 return write(fd, buf, count); 156 } 157 158 uptr internal_stat(const char *path, void *buf) { 159 return stat(path, (struct stat *)buf); 160 } 161 162 uptr internal_lstat(const char *path, void *buf) { 163 return lstat(path, (struct stat *)buf); 164 } 165 166 uptr internal_fstat(fd_t fd, void *buf) { 167 return fstat(fd, (struct stat *)buf); 168 } 169 170 uptr internal_filesize(fd_t fd) { 171 struct stat st; 172 if (internal_fstat(fd, &st)) 173 return -1; 174 return (uptr)st.st_size; 175 } 176 177 uptr internal_dup(int oldfd) { 178 return dup(oldfd); 179 } 180 181 uptr internal_dup2(int oldfd, int newfd) { 182 return dup2(oldfd, newfd); 183 } 184 185 uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 186 return readlink(path, buf, bufsize); 187 } 188 189 uptr internal_unlink(const char *path) { 190 return unlink(path); 191 } 192 193 uptr internal_sched_yield() { 194 return sched_yield(); 195 } 196 197 void internal__exit(int exitcode) { 198 _exit(exitcode); 199 } 200 201 unsigned int internal_sleep(unsigned int seconds) { 202 return sleep(seconds); 203 } 204 205 uptr internal_getpid() { 206 return getpid(); 207 } 208 209 int internal_sigaction(int signum, const void *act, void *oldact) { 210 return sigaction(signum, 211 (const struct sigaction *)act, (struct sigaction *)oldact); 212 } 213 214 void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); } 215 216 uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 217 __sanitizer_sigset_t *oldset) { 218 // Don't use sigprocmask here, because it affects all threads. 219 return pthread_sigmask(how, set, oldset); 220 } 221 222 // Doesn't call pthread_atfork() handlers (but not available on 10.6). 223 extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE; 224 225 int internal_fork() { 226 if (&__fork) 227 return __fork(); 228 return fork(); 229 } 230 231 int internal_sysctl(const int *name, unsigned int namelen, void *oldp, 232 uptr *oldlenp, const void *newp, uptr newlen) { 233 return sysctl(const_cast<int *>(name), namelen, oldp, (size_t *)oldlenp, 234 const_cast<void *>(newp), (size_t)newlen); 235 } 236 237 int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, 238 const void *newp, uptr newlen) { 239 return sysctlbyname(sname, oldp, (size_t *)oldlenp, const_cast<void *>(newp), 240 (size_t)newlen); 241 } 242 243 int internal_forkpty(int *amaster) { 244 int master, slave; 245 if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; 246 int pid = internal_fork(); 247 if (pid == -1) { 248 close(master); 249 close(slave); 250 return -1; 251 } 252 if (pid == 0) { 253 close(master); 254 if (login_tty(slave) != 0) { 255 // We already forked, there's not much we can do. Let's quit. 256 Report("login_tty failed (errno %d)\n", errno); 257 internal__exit(1); 258 } 259 } else { 260 *amaster = master; 261 close(slave); 262 } 263 return pid; 264 } 265 266 uptr internal_rename(const char *oldpath, const char *newpath) { 267 return rename(oldpath, newpath); 268 } 269 270 uptr internal_ftruncate(fd_t fd, uptr size) { 271 return ftruncate(fd, size); 272 } 273 274 uptr internal_execve(const char *filename, char *const argv[], 275 char *const envp[]) { 276 return execve(filename, argv, envp); 277 } 278 279 uptr internal_waitpid(int pid, int *status, int options) { 280 return waitpid(pid, status, options); 281 } 282 283 // ----------------- sanitizer_common.h 284 bool FileExists(const char *filename) { 285 if (ShouldMockFailureToOpen(filename)) 286 return false; 287 struct stat st; 288 if (stat(filename, &st)) 289 return false; 290 // Sanity check: filename is a regular file. 291 return S_ISREG(st.st_mode); 292 } 293 294 tid_t GetTid() { 295 tid_t tid; 296 pthread_threadid_np(nullptr, &tid); 297 return tid; 298 } 299 300 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 301 uptr *stack_bottom) { 302 CHECK(stack_top); 303 CHECK(stack_bottom); 304 uptr stacksize = pthread_get_stacksize_np(pthread_self()); 305 // pthread_get_stacksize_np() returns an incorrect stack size for the main 306 // thread on Mavericks. See 307 // https://github.com/google/sanitizers/issues/261 308 if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization && 309 stacksize == (1 << 19)) { 310 struct rlimit rl; 311 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 312 // Most often rl.rlim_cur will be the desired 8M. 313 if (rl.rlim_cur < kMaxThreadStackSize) { 314 stacksize = rl.rlim_cur; 315 } else { 316 stacksize = kMaxThreadStackSize; 317 } 318 } 319 void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 320 *stack_top = (uptr)stackaddr; 321 *stack_bottom = *stack_top - stacksize; 322 } 323 324 char **GetEnviron() { 325 #if !SANITIZER_IOS 326 char ***env_ptr = _NSGetEnviron(); 327 if (!env_ptr) { 328 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is " 329 "called after libSystem_initializer().\n"); 330 CHECK(env_ptr); 331 } 332 char **environ = *env_ptr; 333 #endif 334 CHECK(environ); 335 return environ; 336 } 337 338 const char *GetEnv(const char *name) { 339 char **env = GetEnviron(); 340 uptr name_len = internal_strlen(name); 341 while (*env != 0) { 342 uptr len = internal_strlen(*env); 343 if (len > name_len) { 344 const char *p = *env; 345 if (!internal_memcmp(p, name, name_len) && 346 p[name_len] == '=') { // Match. 347 return *env + name_len + 1; // String starting after =. 348 } 349 } 350 env++; 351 } 352 return 0; 353 } 354 355 uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { 356 CHECK_LE(kMaxPathLength, buf_len); 357 358 // On OS X the executable path is saved to the stack by dyld. Reading it 359 // from there is much faster than calling dladdr, especially for large 360 // binaries with symbols. 361 InternalScopedString exe_path(kMaxPathLength); 362 uint32_t size = exe_path.size(); 363 if (_NSGetExecutablePath(exe_path.data(), &size) == 0 && 364 realpath(exe_path.data(), buf) != 0) { 365 return internal_strlen(buf); 366 } 367 return 0; 368 } 369 370 uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) { 371 return ReadBinaryName(buf, buf_len); 372 } 373 374 void ReExec() { 375 UNIMPLEMENTED(); 376 } 377 378 void CheckASLR() { 379 // Do nothing 380 } 381 382 void CheckMPROTECT() { 383 // Do nothing 384 } 385 386 uptr GetPageSize() { 387 return sysconf(_SC_PAGESIZE); 388 } 389 390 extern "C" unsigned malloc_num_zones; 391 extern "C" malloc_zone_t **malloc_zones; 392 malloc_zone_t sanitizer_zone; 393 394 // We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If 395 // libmalloc tries to set up a different zone as malloc_zones[0], it will call 396 // mprotect(malloc_zones, ..., PROT_READ). This interceptor will catch that and 397 // make sure we are still the first (default) zone. 398 void MprotectMallocZones(void *addr, int prot) { 399 if (addr == malloc_zones && prot == PROT_READ) { 400 if (malloc_num_zones > 1 && malloc_zones[0] != &sanitizer_zone) { 401 for (unsigned i = 1; i < malloc_num_zones; i++) { 402 if (malloc_zones[i] == &sanitizer_zone) { 403 // Swap malloc_zones[0] and malloc_zones[i]. 404 malloc_zones[i] = malloc_zones[0]; 405 malloc_zones[0] = &sanitizer_zone; 406 break; 407 } 408 } 409 } 410 } 411 } 412 413 BlockingMutex::BlockingMutex() { 414 internal_memset(this, 0, sizeof(*this)); 415 } 416 417 void BlockingMutex::Lock() { 418 CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 419 CHECK_EQ(OS_SPINLOCK_INIT, 0); 420 CHECK_EQ(owner_, 0); 421 OSSpinLockLock((OSSpinLock*)&opaque_storage_); 422 } 423 424 void BlockingMutex::Unlock() { 425 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 426 } 427 428 void BlockingMutex::CheckLocked() { 429 CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0); 430 } 431 432 u64 NanoTime() { 433 timeval tv; 434 internal_memset(&tv, 0, sizeof(tv)); 435 gettimeofday(&tv, 0); 436 return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; 437 } 438 439 // This needs to be called during initialization to avoid being racy. 440 u64 MonotonicNanoTime() { 441 static mach_timebase_info_data_t timebase_info; 442 if (timebase_info.denom == 0) mach_timebase_info(&timebase_info); 443 return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom; 444 } 445 446 uptr GetTlsSize() { 447 return 0; 448 } 449 450 void InitTlsSize() { 451 } 452 453 uptr TlsBaseAddr() { 454 uptr segbase = 0; 455 #if defined(__x86_64__) 456 asm("movq %%gs:0,%0" : "=r"(segbase)); 457 #elif defined(__i386__) 458 asm("movl %%gs:0,%0" : "=r"(segbase)); 459 #endif 460 return segbase; 461 } 462 463 // The size of the tls on darwin does not appear to be well documented, 464 // however the vm memory map suggests that it is 1024 uptrs in size, 465 // with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386. 466 uptr TlsSize() { 467 #if defined(__x86_64__) || defined(__i386__) 468 return 1024 * sizeof(uptr); 469 #else 470 return 0; 471 #endif 472 } 473 474 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 475 uptr *tls_addr, uptr *tls_size) { 476 #if !SANITIZER_GO 477 uptr stack_top, stack_bottom; 478 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 479 *stk_addr = stack_bottom; 480 *stk_size = stack_top - stack_bottom; 481 *tls_addr = TlsBaseAddr(); 482 *tls_size = TlsSize(); 483 #else 484 *stk_addr = 0; 485 *stk_size = 0; 486 *tls_addr = 0; 487 *tls_size = 0; 488 #endif 489 } 490 491 void ListOfModules::init() { 492 clearOrInit(); 493 MemoryMappingLayout memory_mapping(false); 494 memory_mapping.DumpListOfModules(&modules_); 495 } 496 497 void ListOfModules::fallbackInit() { clear(); } 498 499 static HandleSignalMode GetHandleSignalModeImpl(int signum) { 500 switch (signum) { 501 case SIGABRT: 502 return common_flags()->handle_abort; 503 case SIGILL: 504 return common_flags()->handle_sigill; 505 case SIGTRAP: 506 return common_flags()->handle_sigtrap; 507 case SIGFPE: 508 return common_flags()->handle_sigfpe; 509 case SIGSEGV: 510 return common_flags()->handle_segv; 511 case SIGBUS: 512 return common_flags()->handle_sigbus; 513 } 514 return kHandleSignalNo; 515 } 516 517 HandleSignalMode GetHandleSignalMode(int signum) { 518 // Handling fatal signals on watchOS and tvOS devices is disallowed. 519 if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM)) 520 return kHandleSignalNo; 521 HandleSignalMode result = GetHandleSignalModeImpl(signum); 522 if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) 523 return kHandleSignalExclusive; 524 return result; 525 } 526 527 MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; 528 529 MacosVersion GetMacosVersionInternal() { 530 int mib[2] = { CTL_KERN, KERN_OSRELEASE }; 531 char version[100]; 532 uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); 533 for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; 534 // Get the version length. 535 CHECK_NE(internal_sysctl(mib, 2, 0, &len, 0, 0), -1); 536 CHECK_LT(len, maxlen); 537 CHECK_NE(internal_sysctl(mib, 2, version, &len, 0, 0), -1); 538 539 // Expect <major>.<minor>(.<patch>) 540 CHECK_GE(len, 3); 541 const char *p = version; 542 int major = internal_simple_strtoll(p, &p, /*base=*/10); 543 if (*p != '.') return MACOS_VERSION_UNKNOWN; 544 p += 1; 545 int minor = internal_simple_strtoll(p, &p, /*base=*/10); 546 if (*p != '.') return MACOS_VERSION_UNKNOWN; 547 548 switch (major) { 549 case 9: return MACOS_VERSION_LEOPARD; 550 case 10: return MACOS_VERSION_SNOW_LEOPARD; 551 case 11: return MACOS_VERSION_LION; 552 case 12: return MACOS_VERSION_MOUNTAIN_LION; 553 case 13: return MACOS_VERSION_MAVERICKS; 554 case 14: return MACOS_VERSION_YOSEMITE; 555 case 15: return MACOS_VERSION_EL_CAPITAN; 556 case 16: return MACOS_VERSION_SIERRA; 557 case 17: 558 // Not a typo, 17.5 Darwin Kernel Version maps to High Sierra 10.13.4. 559 if (minor >= 5) 560 return MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; 561 return MACOS_VERSION_HIGH_SIERRA; 562 case 18: 563 return MACOS_VERSION_MOJAVE; 564 default: 565 if (major < 9) return MACOS_VERSION_UNKNOWN; 566 return MACOS_VERSION_UNKNOWN_NEWER; 567 } 568 } 569 570 MacosVersion GetMacosVersion() { 571 atomic_uint32_t *cache = 572 reinterpret_cast<atomic_uint32_t*>(&cached_macos_version); 573 MacosVersion result = 574 static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire)); 575 if (result == MACOS_VERSION_UNINITIALIZED) { 576 result = GetMacosVersionInternal(); 577 atomic_store(cache, result, memory_order_release); 578 } 579 return result; 580 } 581 582 bool PlatformHasDifferentMemcpyAndMemmove() { 583 // On OS X 10.7 memcpy() and memmove() are both resolved 584 // into memmove$VARIANT$sse42. 585 // See also https://github.com/google/sanitizers/issues/34. 586 // TODO(glider): need to check dynamically that memcpy() and memmove() are 587 // actually the same function. 588 return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; 589 } 590 591 uptr GetRSS() { 592 struct task_basic_info info; 593 unsigned count = TASK_BASIC_INFO_COUNT; 594 kern_return_t result = 595 task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count); 596 if (UNLIKELY(result != KERN_SUCCESS)) { 597 Report("Cannot get task info. Error: %d\n", result); 598 Die(); 599 } 600 return info.resident_size; 601 } 602 603 void *internal_start_thread(void(*func)(void *arg), void *arg) { 604 // Start the thread with signals blocked, otherwise it can steal user signals. 605 __sanitizer_sigset_t set, old; 606 internal_sigfillset(&set); 607 internal_sigprocmask(SIG_SETMASK, &set, &old); 608 pthread_t th; 609 pthread_create(&th, 0, (void*(*)(void *arg))func, arg); 610 internal_sigprocmask(SIG_SETMASK, &old, 0); 611 return th; 612 } 613 614 void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); } 615 616 #if !SANITIZER_GO 617 static BlockingMutex syslog_lock(LINKER_INITIALIZED); 618 #endif 619 620 void WriteOneLineToSyslog(const char *s) { 621 #if !SANITIZER_GO 622 syslog_lock.CheckLocked(); 623 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); 624 #endif 625 } 626 627 void LogMessageOnPrintf(const char *str) { 628 // Log all printf output to CrashLog. 629 if (common_flags()->abort_on_error) 630 CRAppendCrashLogMessage(str); 631 } 632 633 void LogFullErrorReport(const char *buffer) { 634 #if !SANITIZER_GO 635 // Log with os_trace. This will make it into the crash log. 636 #if SANITIZER_OS_TRACE 637 if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { 638 // os_trace requires the message (format parameter) to be a string literal. 639 if (internal_strncmp(SanitizerToolName, "AddressSanitizer", 640 sizeof("AddressSanitizer") - 1) == 0) 641 os_trace("Address Sanitizer reported a failure."); 642 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", 643 sizeof("UndefinedBehaviorSanitizer") - 1) == 0) 644 os_trace("Undefined Behavior Sanitizer reported a failure."); 645 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", 646 sizeof("ThreadSanitizer") - 1) == 0) 647 os_trace("Thread Sanitizer reported a failure."); 648 else 649 os_trace("Sanitizer tool reported a failure."); 650 651 if (common_flags()->log_to_syslog) 652 os_trace("Consult syslog for more information."); 653 } 654 #endif 655 656 // Log to syslog. 657 // The logging on OS X may call pthread_create so we need the threading 658 // environment to be fully initialized. Also, this should never be called when 659 // holding the thread registry lock since that may result in a deadlock. If 660 // the reporting thread holds the thread registry mutex, and asl_log waits 661 // for GCD to dispatch a new thread, the process will deadlock, because the 662 // pthread_create wrapper needs to acquire the lock as well. 663 BlockingMutexLock l(&syslog_lock); 664 if (common_flags()->log_to_syslog) 665 WriteToSyslog(buffer); 666 667 // The report is added to CrashLog as part of logging all of Printf output. 668 #endif 669 } 670 671 SignalContext::WriteFlag SignalContext::GetWriteFlag() const { 672 #if defined(__x86_64__) || defined(__i386__) 673 ucontext_t *ucontext = static_cast<ucontext_t*>(context); 674 return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ; 675 #else 676 return UNKNOWN; 677 #endif 678 } 679 680 static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 681 ucontext_t *ucontext = (ucontext_t*)context; 682 # if defined(__aarch64__) 683 *pc = ucontext->uc_mcontext->__ss.__pc; 684 # if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 685 *bp = ucontext->uc_mcontext->__ss.__fp; 686 # else 687 *bp = ucontext->uc_mcontext->__ss.__lr; 688 # endif 689 *sp = ucontext->uc_mcontext->__ss.__sp; 690 # elif defined(__x86_64__) 691 *pc = ucontext->uc_mcontext->__ss.__rip; 692 *bp = ucontext->uc_mcontext->__ss.__rbp; 693 *sp = ucontext->uc_mcontext->__ss.__rsp; 694 # elif defined(__arm__) 695 *pc = ucontext->uc_mcontext->__ss.__pc; 696 *bp = ucontext->uc_mcontext->__ss.__r[7]; 697 *sp = ucontext->uc_mcontext->__ss.__sp; 698 # elif defined(__i386__) 699 *pc = ucontext->uc_mcontext->__ss.__eip; 700 *bp = ucontext->uc_mcontext->__ss.__ebp; 701 *sp = ucontext->uc_mcontext->__ss.__esp; 702 # else 703 # error "Unknown architecture" 704 # endif 705 } 706 707 void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } 708 709 void InitializePlatformEarly() { 710 // Only use xnu_fast_mmap when on x86_64 and the OS supports it. 711 use_xnu_fast_mmap = 712 #if defined(__x86_64__) 713 GetMacosVersion() >= MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; 714 #else 715 false; 716 #endif 717 } 718 719 #if !SANITIZER_GO 720 static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; 721 LowLevelAllocator allocator_for_env; 722 723 // Change the value of the env var |name|, leaking the original value. 724 // If |name_value| is NULL, the variable is deleted from the environment, 725 // otherwise the corresponding "NAME=value" string is replaced with 726 // |name_value|. 727 void LeakyResetEnv(const char *name, const char *name_value) { 728 char **env = GetEnviron(); 729 uptr name_len = internal_strlen(name); 730 while (*env != 0) { 731 uptr len = internal_strlen(*env); 732 if (len > name_len) { 733 const char *p = *env; 734 if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { 735 // Match. 736 if (name_value) { 737 // Replace the old value with the new one. 738 *env = const_cast<char*>(name_value); 739 } else { 740 // Shift the subsequent pointers back. 741 char **del = env; 742 do { 743 del[0] = del[1]; 744 } while (*del++); 745 } 746 } 747 } 748 env++; 749 } 750 } 751 752 SANITIZER_WEAK_CXX_DEFAULT_IMPL 753 bool ReexecDisabled() { 754 return false; 755 } 756 757 extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber; 758 static const double kMinDyldVersionWithAutoInterposition = 360.0; 759 760 bool DyldNeedsEnvVariable() { 761 // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users 762 // still may want use them on older systems. On older Darwin platforms, dyld 763 // doesn't export dyldVersionNumber symbol and we simply return true. 764 if (!&dyldVersionNumber) return true; 765 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if 766 // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via 767 // GetMacosVersion() doesn't work for the simulator. Let's instead check 768 // `dyldVersionNumber`, which is exported by dyld, against a known version 769 // number from the first OS release where this appeared. 770 return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; 771 } 772 773 void MaybeReexec() { 774 // FIXME: This should really live in some "InitializePlatform" method. 775 MonotonicNanoTime(); 776 777 if (ReexecDisabled()) return; 778 779 // Make sure the dynamic runtime library is preloaded so that the 780 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec 781 // ourselves. 782 Dl_info info; 783 RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info)); 784 char *dyld_insert_libraries = 785 const_cast<char*>(GetEnv(kDyldInsertLibraries)); 786 uptr old_env_len = dyld_insert_libraries ? 787 internal_strlen(dyld_insert_libraries) : 0; 788 uptr fname_len = internal_strlen(info.dli_fname); 789 const char *dylib_name = StripModuleName(info.dli_fname); 790 uptr dylib_name_len = internal_strlen(dylib_name); 791 792 bool lib_is_in_env = dyld_insert_libraries && 793 internal_strstr(dyld_insert_libraries, dylib_name); 794 if (DyldNeedsEnvVariable() && !lib_is_in_env) { 795 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime 796 // library. 797 InternalScopedString program_name(1024); 798 uint32_t buf_size = program_name.size(); 799 _NSGetExecutablePath(program_name.data(), &buf_size); 800 char *new_env = const_cast<char*>(info.dli_fname); 801 if (dyld_insert_libraries) { 802 // Append the runtime dylib name to the existing value of 803 // DYLD_INSERT_LIBRARIES. 804 new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); 805 internal_strncpy(new_env, dyld_insert_libraries, old_env_len); 806 new_env[old_env_len] = ':'; 807 // Copy fname_len and add a trailing zero. 808 internal_strncpy(new_env + old_env_len + 1, info.dli_fname, 809 fname_len + 1); 810 // Ok to use setenv() since the wrappers don't depend on the value of 811 // asan_inited. 812 setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); 813 } else { 814 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. 815 setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); 816 } 817 VReport(1, "exec()-ing the program with\n"); 818 VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); 819 VReport(1, "to enable wrappers.\n"); 820 execv(program_name.data(), *_NSGetArgv()); 821 822 // We get here only if execv() failed. 823 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " 824 "which is required for the sanitizer to work. We tried to set the " 825 "environment variable and re-execute itself, but execv() failed, " 826 "possibly because of sandbox restrictions. Make sure to launch the " 827 "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); 828 RAW_CHECK("execv failed" && 0); 829 } 830 831 // Verify that interceptors really work. We'll use dlsym to locate 832 // "pthread_create", if interceptors are working, it should really point to 833 // "wrap_pthread_create" within our own dylib. 834 Dl_info info_pthread_create; 835 void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create"); 836 RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create)); 837 if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) { 838 Report( 839 "ERROR: Interceptors are not working. This may be because %s is " 840 "loaded too late (e.g. via dlopen). Please launch the executable " 841 "with:\n%s=%s\n", 842 SanitizerToolName, kDyldInsertLibraries, info.dli_fname); 843 RAW_CHECK("interceptors not installed" && 0); 844 } 845 846 if (!lib_is_in_env) 847 return; 848 849 if (!common_flags()->strip_env) 850 return; 851 852 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove 853 // the dylib from the environment variable, because interceptors are installed 854 // and we don't want our children to inherit the variable. 855 856 uptr env_name_len = internal_strlen(kDyldInsertLibraries); 857 // Allocate memory to hold the previous env var name, its value, the '=' 858 // sign and the '\0' char. 859 char *new_env = (char*)allocator_for_env.Allocate( 860 old_env_len + 2 + env_name_len); 861 RAW_CHECK(new_env); 862 internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); 863 internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); 864 new_env[env_name_len] = '='; 865 char *new_env_pos = new_env + env_name_len + 1; 866 867 // Iterate over colon-separated pieces of |dyld_insert_libraries|. 868 char *piece_start = dyld_insert_libraries; 869 char *piece_end = NULL; 870 char *old_env_end = dyld_insert_libraries + old_env_len; 871 do { 872 if (piece_start[0] == ':') piece_start++; 873 piece_end = internal_strchr(piece_start, ':'); 874 if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; 875 if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; 876 uptr piece_len = piece_end - piece_start; 877 878 char *filename_start = 879 (char *)internal_memrchr(piece_start, '/', piece_len); 880 uptr filename_len = piece_len; 881 if (filename_start) { 882 filename_start += 1; 883 filename_len = piece_len - (filename_start - piece_start); 884 } else { 885 filename_start = piece_start; 886 } 887 888 // If the current piece isn't the runtime library name, 889 // append it to new_env. 890 if ((dylib_name_len != filename_len) || 891 (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { 892 if (new_env_pos != new_env + env_name_len + 1) { 893 new_env_pos[0] = ':'; 894 new_env_pos++; 895 } 896 internal_strncpy(new_env_pos, piece_start, piece_len); 897 new_env_pos += piece_len; 898 } 899 // Move on to the next piece. 900 piece_start = piece_end; 901 } while (piece_start < old_env_end); 902 903 // Can't use setenv() here, because it requires the allocator to be 904 // initialized. 905 // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in 906 // a separate function called after InitializeAllocator(). 907 if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; 908 LeakyResetEnv(kDyldInsertLibraries, new_env); 909 } 910 #endif // SANITIZER_GO 911 912 char **GetArgv() { 913 return *_NSGetArgv(); 914 } 915 916 #if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM 917 // The task_vm_info struct is normally provided by the macOS SDK, but we need 918 // fields only available in 10.12+. Declare the struct manually to be able to 919 // build against older SDKs. 920 struct __sanitizer_task_vm_info { 921 mach_vm_size_t virtual_size; 922 integer_t region_count; 923 integer_t page_size; 924 mach_vm_size_t resident_size; 925 mach_vm_size_t resident_size_peak; 926 mach_vm_size_t device; 927 mach_vm_size_t device_peak; 928 mach_vm_size_t internal; 929 mach_vm_size_t internal_peak; 930 mach_vm_size_t external; 931 mach_vm_size_t external_peak; 932 mach_vm_size_t reusable; 933 mach_vm_size_t reusable_peak; 934 mach_vm_size_t purgeable_volatile_pmap; 935 mach_vm_size_t purgeable_volatile_resident; 936 mach_vm_size_t purgeable_volatile_virtual; 937 mach_vm_size_t compressed; 938 mach_vm_size_t compressed_peak; 939 mach_vm_size_t compressed_lifetime; 940 mach_vm_size_t phys_footprint; 941 mach_vm_address_t min_address; 942 mach_vm_address_t max_address; 943 }; 944 #define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \ 945 (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t))) 946 947 uptr GetTaskInfoMaxAddress() { 948 __sanitizer_task_vm_info vm_info = {} /* zero initialize */; 949 mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT; 950 int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count); 951 if (err == 0 && vm_info.max_address != 0) { 952 return vm_info.max_address - 1; 953 } else { 954 // xnu cannot provide vm address limit 955 return 0x200000000 - 1; 956 } 957 } 958 #endif 959 960 uptr GetMaxUserVirtualAddress() { 961 #if SANITIZER_WORDSIZE == 64 962 # if defined(__aarch64__) && SANITIZER_IOS && !SANITIZER_IOSSIM 963 // Get the maximum VM address 964 static uptr max_vm = GetTaskInfoMaxAddress(); 965 CHECK(max_vm); 966 return max_vm; 967 # else 968 return (1ULL << 47) - 1; // 0x00007fffffffffffUL; 969 # endif 970 #else // SANITIZER_WORDSIZE == 32 971 return (1ULL << 32) - 1; // 0xffffffff; 972 #endif // SANITIZER_WORDSIZE 973 } 974 975 uptr GetMaxVirtualAddress() { 976 return GetMaxUserVirtualAddress(); 977 } 978 979 uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, 980 uptr *largest_gap_found, 981 uptr *max_occupied_addr) { 982 typedef vm_region_submap_short_info_data_64_t RegionInfo; 983 enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 }; 984 // Start searching for available memory region past PAGEZERO, which is 985 // 4KB on 32-bit and 4GB on 64-bit. 986 mach_vm_address_t start_address = 987 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000; 988 989 mach_vm_address_t address = start_address; 990 mach_vm_address_t free_begin = start_address; 991 kern_return_t kr = KERN_SUCCESS; 992 if (largest_gap_found) *largest_gap_found = 0; 993 if (max_occupied_addr) *max_occupied_addr = 0; 994 while (kr == KERN_SUCCESS) { 995 mach_vm_size_t vmsize = 0; 996 natural_t depth = 0; 997 RegionInfo vminfo; 998 mach_msg_type_number_t count = kRegionInfoSize; 999 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth, 1000 (vm_region_info_t)&vminfo, &count); 1001 if (kr == KERN_INVALID_ADDRESS) { 1002 // No more regions beyond "address", consider the gap at the end of VM. 1003 address = GetMaxVirtualAddress() + 1; 1004 vmsize = 0; 1005 } else { 1006 if (max_occupied_addr) *max_occupied_addr = address + vmsize; 1007 } 1008 if (free_begin != address) { 1009 // We found a free region [free_begin..address-1]. 1010 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment); 1011 uptr gap_end = RoundDownTo((uptr)address, alignment); 1012 uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0; 1013 if (size < gap_size) { 1014 return gap_start; 1015 } 1016 1017 if (largest_gap_found && *largest_gap_found < gap_size) { 1018 *largest_gap_found = gap_size; 1019 } 1020 } 1021 // Move to the next region. 1022 address += vmsize; 1023 free_begin = address; 1024 } 1025 1026 // We looked at all free regions and could not find one large enough. 1027 return 0; 1028 } 1029 1030 // FIXME implement on this platform. 1031 void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { } 1032 1033 void SignalContext::DumpAllRegisters(void *context) { 1034 Report("Register values:\n"); 1035 1036 ucontext_t *ucontext = (ucontext_t*)context; 1037 # define DUMPREG64(r) \ 1038 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r); 1039 # define DUMPREG32(r) \ 1040 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r); 1041 # define DUMPREG_(r) Printf(" "); DUMPREG(r); 1042 # define DUMPREG__(r) Printf(" "); DUMPREG(r); 1043 # define DUMPREG___(r) Printf(" "); DUMPREG(r); 1044 1045 # if defined(__x86_64__) 1046 # define DUMPREG(r) DUMPREG64(r) 1047 DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n"); 1048 DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n"); 1049 DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n"); 1050 DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n"); 1051 # elif defined(__i386__) 1052 # define DUMPREG(r) DUMPREG32(r) 1053 DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n"); 1054 DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n"); 1055 # elif defined(__aarch64__) 1056 # define DUMPREG(r) DUMPREG64(r) 1057 DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n"); 1058 DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n"); 1059 DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n"); 1060 DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n"); 1061 DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n"); 1062 DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n"); 1063 DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n"); 1064 DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n"); 1065 # elif defined(__arm__) 1066 # define DUMPREG(r) DUMPREG32(r) 1067 DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n"); 1068 DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n"); 1069 DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n"); 1070 DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n"); 1071 # else 1072 # error "Unknown architecture" 1073 # endif 1074 1075 # undef DUMPREG64 1076 # undef DUMPREG32 1077 # undef DUMPREG_ 1078 # undef DUMPREG__ 1079 # undef DUMPREG___ 1080 # undef DUMPREG 1081 } 1082 1083 static inline bool CompareBaseAddress(const LoadedModule &a, 1084 const LoadedModule &b) { 1085 return a.base_address() < b.base_address(); 1086 } 1087 1088 void FormatUUID(char *out, uptr size, const u8 *uuid) { 1089 internal_snprintf(out, size, 1090 "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-" 1091 "%02X%02X%02X%02X%02X%02X>", 1092 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], 1093 uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], 1094 uuid[12], uuid[13], uuid[14], uuid[15]); 1095 } 1096 1097 void PrintModuleMap() { 1098 Printf("Process module map:\n"); 1099 MemoryMappingLayout memory_mapping(false); 1100 InternalMmapVector<LoadedModule> modules; 1101 modules.reserve(128); 1102 memory_mapping.DumpListOfModules(&modules); 1103 Sort(modules.data(), modules.size(), CompareBaseAddress); 1104 for (uptr i = 0; i < modules.size(); ++i) { 1105 char uuid_str[128]; 1106 FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid()); 1107 Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(), 1108 modules[i].max_executable_address(), modules[i].full_name(), 1109 ModuleArchToString(modules[i].arch()), uuid_str); 1110 } 1111 Printf("End of module map.\n"); 1112 } 1113 1114 void CheckNoDeepBind(const char *filename, int flag) { 1115 // Do nothing. 1116 } 1117 1118 bool GetRandom(void *buffer, uptr length, bool blocking) { 1119 if (!buffer || !length || length > 256) 1120 return false; 1121 // arc4random never fails. 1122 arc4random_buf(buffer, length); 1123 return true; 1124 } 1125 1126 u32 GetNumberOfCPUs() { 1127 return (u32)sysconf(_SC_NPROCESSORS_ONLN); 1128 } 1129 1130 } // namespace __sanitizer 1131 1132 #endif // SANITIZER_MAC 1133