diff options
Diffstat (limited to 'contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc')
-rw-r--r-- | contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc | 109 |
1 files changed, 83 insertions, 26 deletions
diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 180d7c199aef..8954a7a88073 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -108,9 +108,20 @@ extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE; #define VM_MEMORY_SANITIZER 99 #endif +// XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of +// giant memory regions (i.e. shadow memory regions). +#define kXnuFastMmapFd 0x4 +static size_t kXnuFastMmapThreshold = 2 << 30; // 2 GB +static bool use_xnu_fast_mmap = false; + uptr internal_mmap(void *addr, size_t length, int prot, int flags, int fd, u64 offset) { - if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER); + if (fd == -1) { + fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER); + if (length >= kXnuFastMmapThreshold) { + if (use_xnu_fast_mmap) fd |= kXnuFastMmapFd; + } + } if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset); return (uptr)mmap(addr, length, prot, flags, fd, offset); } @@ -163,6 +174,10 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } +uptr internal_dup(int oldfd) { + return dup(oldfd); +} + uptr internal_dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); } @@ -213,6 +228,18 @@ int internal_fork() { return fork(); } +int internal_sysctl(const int *name, unsigned int namelen, void *oldp, + uptr *oldlenp, const void *newp, uptr newlen) { + return sysctl(const_cast<int *>(name), namelen, oldp, (size_t *)oldlenp, + const_cast<void *>(newp), (size_t)newlen); +} + +int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, + const void *newp, uptr newlen) { + return sysctlbyname(sname, oldp, (size_t *)oldlenp, const_cast<void *>(newp), + (size_t)newlen); +} + int internal_forkpty(int *amaster) { int master, slave; if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; @@ -255,6 +282,8 @@ uptr internal_waitpid(int pid, int *status, int options) { // ----------------- sanitizer_common.h bool FileExists(const char *filename) { + if (ShouldMockFailureToOpen(filename)) + return false; struct stat st; if (stat(filename, &st)) return false; @@ -350,6 +379,10 @@ void CheckASLR() { // Do nothing } +void CheckMPROTECT() { + // Do nothing +} + uptr GetPageSize() { return sysconf(_SC_PAGESIZE); } @@ -499,26 +532,38 @@ MacosVersion GetMacosVersionInternal() { uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; // Get the version length. - CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1); + CHECK_NE(internal_sysctl(mib, 2, 0, &len, 0, 0), -1); CHECK_LT(len, maxlen); - CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1); - switch (version[0]) { - case '9': return MACOS_VERSION_LEOPARD; - case '1': { - switch (version[1]) { - case '0': return MACOS_VERSION_SNOW_LEOPARD; - case '1': return MACOS_VERSION_LION; - case '2': return MACOS_VERSION_MOUNTAIN_LION; - case '3': return MACOS_VERSION_MAVERICKS; - case '4': return MACOS_VERSION_YOSEMITE; - default: - if (IsDigit(version[1])) - return MACOS_VERSION_UNKNOWN_NEWER; - else - return MACOS_VERSION_UNKNOWN; - } - } - default: return MACOS_VERSION_UNKNOWN; + CHECK_NE(internal_sysctl(mib, 2, version, &len, 0, 0), -1); + + // Expect <major>.<minor>(.<patch>) + CHECK_GE(len, 3); + const char *p = version; + int major = internal_simple_strtoll(p, &p, /*base=*/10); + if (*p != '.') return MACOS_VERSION_UNKNOWN; + p += 1; + int minor = internal_simple_strtoll(p, &p, /*base=*/10); + if (*p != '.') return MACOS_VERSION_UNKNOWN; + + switch (major) { + case 9: return MACOS_VERSION_LEOPARD; + case 10: return MACOS_VERSION_SNOW_LEOPARD; + case 11: return MACOS_VERSION_LION; + case 12: return MACOS_VERSION_MOUNTAIN_LION; + case 13: return MACOS_VERSION_MAVERICKS; + case 14: return MACOS_VERSION_YOSEMITE; + case 15: return MACOS_VERSION_EL_CAPITAN; + case 16: return MACOS_VERSION_SIERRA; + case 17: + // Not a typo, 17.5 Darwin Kernel Version maps to High Sierra 10.13.4. + if (minor >= 5) + return MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; + return MACOS_VERSION_HIGH_SIERRA; + case 18: + return MACOS_VERSION_MOJAVE; + default: + if (major < 9) return MACOS_VERSION_UNKNOWN; + return MACOS_VERSION_UNKNOWN_NEWER; } } @@ -661,6 +706,16 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } +void InitializePlatformEarly() { + // Only use xnu_fast_mmap when on x86_64 and the OS supports it. + use_xnu_fast_mmap = +#if defined(__x86_64__) + GetMacosVersion() >= MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; +#else + false; +#endif +} + #if !SANITIZER_GO static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; LowLevelAllocator allocator_for_env; @@ -890,10 +945,10 @@ struct __sanitizer_task_vm_info { (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t))) uptr GetTaskInfoMaxAddress() { - __sanitizer_task_vm_info vm_info = {}; + __sanitizer_task_vm_info vm_info = {} /* zero initialize */; mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT; int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count); - if (err == 0) { + if (err == 0 && vm_info.max_address != 0) { return vm_info.max_address - 1; } else { // xnu cannot provide vm address limit @@ -1060,14 +1115,16 @@ void CheckNoDeepBind(const char *filename, int flag) { // Do nothing. } -// FIXME: implement on this platform. bool GetRandom(void *buffer, uptr length, bool blocking) { - UNIMPLEMENTED(); + if (!buffer || !length || length > 256) + return false; + // arc4random never fails. + arc4random_buf(buffer, length); + return true; } -// FIXME: implement on this platform. u32 GetNumberOfCPUs() { - UNIMPLEMENTED(); + return (u32)sysconf(_SC_NPROCESSORS_ONLN); } } // namespace __sanitizer |