1 //===-- sanitizer_mac.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is shared between various sanitizers' runtime libraries and
10 // implements OSX-specific functions.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
15 #include "sanitizer_mac.h"
16 #include "interception/interception.h"
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
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_platform_limits_posix.h"
31 #include "sanitizer_procmaps.h"
32 #include "sanitizer_ptrauth.h"
35 #include <crt_externs.h> // for _NSGetEnviron
37 extern char **environ
;
40 #if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
41 #define SANITIZER_OS_TRACE 1
44 #define SANITIZER_OS_TRACE 0
48 #include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
51 extern char ***_NSGetArgv(void);
56 #include <dlfcn.h> // for dladdr()
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>
70 #include <sys/ioctl.h>
72 #include <sys/resource.h>
74 #include <sys/sysctl.h>
75 #include <sys/types.h>
80 // From <crt_externs.h>, but we don't have that file on iOS.
82 extern char ***_NSGetArgv(void);
83 extern char ***_NSGetEnviron(void);
86 // From <mach/mach_vm.h>, but we don't have that file on iOS.
88 extern kern_return_t
mach_vm_region_recurse(
90 mach_vm_address_t
*address
,
92 natural_t
*nesting_depth
,
93 vm_region_recurse_info_t info
,
94 mach_msg_type_number_t
*infoCnt
);
97 namespace __sanitizer
{
99 #include "sanitizer_syscall_generic.inc"
101 // Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
102 extern "C" void *__mmap(void *addr
, size_t len
, int prot
, int flags
, int fildes
,
103 off_t off
) SANITIZER_WEAK_ATTRIBUTE
;
104 extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE
;
106 // ---------------------- sanitizer_libc.h
108 // From <mach/vm_statistics.h>, but not on older OSs.
109 #ifndef VM_MEMORY_SANITIZER
110 #define VM_MEMORY_SANITIZER 99
113 // XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of
114 // giant memory regions (i.e. shadow memory regions).
115 #define kXnuFastMmapFd 0x4
116 static size_t kXnuFastMmapThreshold
= 2 << 30; // 2 GB
117 static bool use_xnu_fast_mmap
= false;
119 uptr
internal_mmap(void *addr
, size_t length
, int prot
, int flags
,
120 int fd
, u64 offset
) {
122 fd
= VM_MAKE_TAG(VM_MEMORY_SANITIZER
);
123 if (length
>= kXnuFastMmapThreshold
) {
124 if (use_xnu_fast_mmap
) fd
|= kXnuFastMmapFd
;
127 if (&__mmap
) return (uptr
)__mmap(addr
, length
, prot
, flags
, fd
, offset
);
128 return (uptr
)mmap(addr
, length
, prot
, flags
, fd
, offset
);
131 uptr
internal_munmap(void *addr
, uptr length
) {
132 if (&__munmap
) return __munmap(addr
, length
);
133 return munmap(addr
, length
);
136 int internal_mprotect(void *addr
, uptr length
, int prot
) {
137 return mprotect(addr
, length
, prot
);
140 int internal_madvise(uptr addr
, uptr length
, int advice
) {
141 return madvise((void *)addr
, length
, advice
);
144 uptr
internal_close(fd_t fd
) {
148 uptr
internal_open(const char *filename
, int flags
) {
149 return open(filename
, flags
);
152 uptr
internal_open(const char *filename
, int flags
, u32 mode
) {
153 return open(filename
, flags
, mode
);
156 uptr
internal_read(fd_t fd
, void *buf
, uptr count
) {
157 return read(fd
, buf
, count
);
160 uptr
internal_write(fd_t fd
, const void *buf
, uptr count
) {
161 return write(fd
, buf
, count
);
164 uptr
internal_stat(const char *path
, void *buf
) {
165 return stat(path
, (struct stat
*)buf
);
168 uptr
internal_lstat(const char *path
, void *buf
) {
169 return lstat(path
, (struct stat
*)buf
);
172 uptr
internal_fstat(fd_t fd
, void *buf
) {
173 return fstat(fd
, (struct stat
*)buf
);
176 uptr
internal_filesize(fd_t fd
) {
178 if (internal_fstat(fd
, &st
))
180 return (uptr
)st
.st_size
;
183 uptr
internal_dup(int oldfd
) {
187 uptr
internal_dup2(int oldfd
, int newfd
) {
188 return dup2(oldfd
, newfd
);
191 uptr
internal_readlink(const char *path
, char *buf
, uptr bufsize
) {
192 return readlink(path
, buf
, bufsize
);
195 uptr
internal_unlink(const char *path
) {
199 uptr
internal_sched_yield() {
200 return sched_yield();
203 void internal__exit(int exitcode
) {
207 unsigned int internal_sleep(unsigned int seconds
) {
208 return sleep(seconds
);
211 uptr
internal_getpid() {
215 int internal_dlinfo(void *handle
, int request
, void *p
) {
219 int internal_sigaction(int signum
, const void *act
, void *oldact
) {
220 return sigaction(signum
,
221 (const struct sigaction
*)act
, (struct sigaction
*)oldact
);
224 void internal_sigfillset(__sanitizer_sigset_t
*set
) { sigfillset(set
); }
226 uptr
internal_sigprocmask(int how
, __sanitizer_sigset_t
*set
,
227 __sanitizer_sigset_t
*oldset
) {
228 // Don't use sigprocmask here, because it affects all threads.
229 return pthread_sigmask(how
, set
, oldset
);
232 // Doesn't call pthread_atfork() handlers (but not available on 10.6).
233 extern "C" pid_t
__fork(void) SANITIZER_WEAK_ATTRIBUTE
;
235 int internal_fork() {
241 int internal_sysctl(const int *name
, unsigned int namelen
, void *oldp
,
242 uptr
*oldlenp
, const void *newp
, uptr newlen
) {
243 return sysctl(const_cast<int *>(name
), namelen
, oldp
, (size_t *)oldlenp
,
244 const_cast<void *>(newp
), (size_t)newlen
);
247 int internal_sysctlbyname(const char *sname
, void *oldp
, uptr
*oldlenp
,
248 const void *newp
, uptr newlen
) {
249 return sysctlbyname(sname
, oldp
, (size_t *)oldlenp
, const_cast<void *>(newp
),
253 static fd_t
internal_spawn_impl(const char *argv
[], const char *envp
[],
255 fd_t master_fd
= kInvalidFd
;
256 fd_t slave_fd
= kInvalidFd
;
258 auto fd_closer
= at_scope_exit([&] {
259 internal_close(master_fd
);
260 internal_close(slave_fd
);
263 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
264 // in particular detects when it's talking to a pipe and forgets to flush the
265 // output stream after sending a response.
266 master_fd
= posix_openpt(O_RDWR
);
267 if (master_fd
== kInvalidFd
) return kInvalidFd
;
269 int res
= grantpt(master_fd
) || unlockpt(master_fd
);
270 if (res
!= 0) return kInvalidFd
;
272 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
273 char slave_pty_name
[128];
274 res
= ioctl(master_fd
, TIOCPTYGNAME
, slave_pty_name
);
275 if (res
== -1) return kInvalidFd
;
277 slave_fd
= internal_open(slave_pty_name
, O_RDWR
);
278 if (slave_fd
== kInvalidFd
) return kInvalidFd
;
280 // File descriptor actions
281 posix_spawn_file_actions_t acts
;
282 res
= posix_spawn_file_actions_init(&acts
);
283 if (res
!= 0) return kInvalidFd
;
285 auto acts_cleanup
= at_scope_exit([&] {
286 posix_spawn_file_actions_destroy(&acts
);
289 res
= posix_spawn_file_actions_adddup2(&acts
, slave_fd
, STDIN_FILENO
) ||
290 posix_spawn_file_actions_adddup2(&acts
, slave_fd
, STDOUT_FILENO
) ||
291 posix_spawn_file_actions_addclose(&acts
, slave_fd
);
292 if (res
!= 0) return kInvalidFd
;
295 posix_spawnattr_t attrs
;
296 res
= posix_spawnattr_init(&attrs
);
297 if (res
!= 0) return kInvalidFd
;
299 auto attrs_cleanup
= at_scope_exit([&] {
300 posix_spawnattr_destroy(&attrs
);
303 // In the spawned process, close all file descriptors that are not explicitly
304 // described by the file actions object. This is Darwin-specific extension.
305 res
= posix_spawnattr_setflags(&attrs
, POSIX_SPAWN_CLOEXEC_DEFAULT
);
306 if (res
!= 0) return kInvalidFd
;
309 char **argv_casted
= const_cast<char **>(argv
);
310 char **envp_casted
= const_cast<char **>(envp
);
311 res
= posix_spawn(pid
, argv
[0], &acts
, &attrs
, argv_casted
, envp_casted
);
312 if (res
!= 0) return kInvalidFd
;
314 // Disable echo in the new terminal, disable CR.
315 struct termios termflags
;
316 tcgetattr(master_fd
, &termflags
);
317 termflags
.c_oflag
&= ~ONLCR
;
318 termflags
.c_lflag
&= ~ECHO
;
319 tcsetattr(master_fd
, TCSANOW
, &termflags
);
321 // On success, do not close master_fd on scope exit.
323 master_fd
= kInvalidFd
;
328 fd_t
internal_spawn(const char *argv
[], const char *envp
[], pid_t
*pid
) {
329 // The client program may close its stdin and/or stdout and/or stderr thus
330 // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
331 // case the communication is broken if either the parent or the child tries to
332 // close or duplicate these descriptors. We temporarily reserve these
333 // descriptors here to prevent this.
337 for (; count
< 3; count
++) {
338 low_fds
[count
] = posix_openpt(O_RDWR
);
339 if (low_fds
[count
] >= STDERR_FILENO
)
343 fd_t fd
= internal_spawn_impl(argv
, envp
, pid
);
345 for (; count
> 0; count
--) {
346 internal_close(low_fds
[count
]);
352 uptr
internal_rename(const char *oldpath
, const char *newpath
) {
353 return rename(oldpath
, newpath
);
356 uptr
internal_ftruncate(fd_t fd
, uptr size
) {
357 return ftruncate(fd
, size
);
360 uptr
internal_execve(const char *filename
, char *const argv
[],
361 char *const envp
[]) {
362 return execve(filename
, argv
, envp
);
365 uptr
internal_waitpid(int pid
, int *status
, int options
) {
366 return waitpid(pid
, status
, options
);
369 // ----------------- sanitizer_common.h
370 bool FileExists(const char *filename
) {
371 if (ShouldMockFailureToOpen(filename
))
374 if (stat(filename
, &st
))
376 // Sanity check: filename is a regular file.
377 return S_ISREG(st
.st_mode
);
382 pthread_threadid_np(nullptr, &tid
);
386 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
387 uptr
*stack_bottom
) {
390 uptr stacksize
= pthread_get_stacksize_np(pthread_self());
391 // pthread_get_stacksize_np() returns an incorrect stack size for the main
392 // thread on Mavericks. See
393 // https://github.com/google/sanitizers/issues/261
394 if ((GetMacosAlignedVersion() >= MacosVersion(10, 9)) && at_initialization
&&
395 stacksize
== (1 << 19)) {
397 CHECK_EQ(getrlimit(RLIMIT_STACK
, &rl
), 0);
398 // Most often rl.rlim_cur will be the desired 8M.
399 if (rl
.rlim_cur
< kMaxThreadStackSize
) {
400 stacksize
= rl
.rlim_cur
;
402 stacksize
= kMaxThreadStackSize
;
405 void *stackaddr
= pthread_get_stackaddr_np(pthread_self());
406 *stack_top
= (uptr
)stackaddr
;
407 *stack_bottom
= *stack_top
- stacksize
;
410 char **GetEnviron() {
412 char ***env_ptr
= _NSGetEnviron();
414 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
415 "called after libSystem_initializer().\n");
418 char **environ
= *env_ptr
;
424 const char *GetEnv(const char *name
) {
425 char **env
= GetEnviron();
426 uptr name_len
= internal_strlen(name
);
428 uptr len
= internal_strlen(*env
);
429 if (len
> name_len
) {
430 const char *p
= *env
;
431 if (!internal_memcmp(p
, name
, name_len
) &&
432 p
[name_len
] == '=') { // Match.
433 return *env
+ name_len
+ 1; // String starting after =.
441 uptr
ReadBinaryName(/*out*/char *buf
, uptr buf_len
) {
442 CHECK_LE(kMaxPathLength
, buf_len
);
444 // On OS X the executable path is saved to the stack by dyld. Reading it
445 // from there is much faster than calling dladdr, especially for large
446 // binaries with symbols.
447 InternalScopedString
exe_path(kMaxPathLength
);
448 uint32_t size
= exe_path
.size();
449 if (_NSGetExecutablePath(exe_path
.data(), &size
) == 0 &&
450 realpath(exe_path
.data(), buf
) != 0) {
451 return internal_strlen(buf
);
456 uptr
ReadLongProcessName(/*out*/char *buf
, uptr buf_len
) {
457 return ReadBinaryName(buf
, buf_len
);
468 void CheckMPROTECT() {
473 return sysconf(_SC_PAGESIZE
);
476 extern "C" unsigned malloc_num_zones
;
477 extern "C" malloc_zone_t
**malloc_zones
;
478 malloc_zone_t sanitizer_zone
;
480 // We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If
481 // libmalloc tries to set up a different zone as malloc_zones[0], it will call
482 // mprotect(malloc_zones, ..., PROT_READ). This interceptor will catch that and
483 // make sure we are still the first (default) zone.
484 void MprotectMallocZones(void *addr
, int prot
) {
485 if (addr
== malloc_zones
&& prot
== PROT_READ
) {
486 if (malloc_num_zones
> 1 && malloc_zones
[0] != &sanitizer_zone
) {
487 for (unsigned i
= 1; i
< malloc_num_zones
; i
++) {
488 if (malloc_zones
[i
] == &sanitizer_zone
) {
489 // Swap malloc_zones[0] and malloc_zones[i].
490 malloc_zones
[i
] = malloc_zones
[0];
491 malloc_zones
[0] = &sanitizer_zone
;
499 BlockingMutex::BlockingMutex() {
500 internal_memset(this, 0, sizeof(*this));
503 void BlockingMutex::Lock() {
504 CHECK(sizeof(OSSpinLock
) <= sizeof(opaque_storage_
));
505 CHECK_EQ(OS_SPINLOCK_INIT
, 0);
507 OSSpinLockLock((OSSpinLock
*)&opaque_storage_
);
510 void BlockingMutex::Unlock() {
511 OSSpinLockUnlock((OSSpinLock
*)&opaque_storage_
);
514 void BlockingMutex::CheckLocked() {
515 CHECK_NE(*(OSSpinLock
*)&opaque_storage_
, 0);
520 internal_memset(&tv
, 0, sizeof(tv
));
521 gettimeofday(&tv
, 0);
522 return (u64
)tv
.tv_sec
* 1000*1000*1000 + tv
.tv_usec
* 1000;
525 // This needs to be called during initialization to avoid being racy.
526 u64
MonotonicNanoTime() {
527 static mach_timebase_info_data_t timebase_info
;
528 if (timebase_info
.denom
== 0) mach_timebase_info(&timebase_info
);
529 return (mach_absolute_time() * timebase_info
.numer
) / timebase_info
.denom
;
541 #if defined(__x86_64__)
542 asm("movq %%gs:0,%0" : "=r"(segbase
));
543 #elif defined(__i386__)
544 asm("movl %%gs:0,%0" : "=r"(segbase
));
549 // The size of the tls on darwin does not appear to be well documented,
550 // however the vm memory map suggests that it is 1024 uptrs in size,
551 // with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
553 #if defined(__x86_64__) || defined(__i386__)
554 return 1024 * sizeof(uptr
);
560 void GetThreadStackAndTls(bool main
, uptr
*stk_addr
, uptr
*stk_size
,
561 uptr
*tls_addr
, uptr
*tls_size
) {
563 uptr stack_top
, stack_bottom
;
564 GetThreadStackTopAndBottom(main
, &stack_top
, &stack_bottom
);
565 *stk_addr
= stack_bottom
;
566 *stk_size
= stack_top
- stack_bottom
;
567 *tls_addr
= TlsBaseAddr();
568 *tls_size
= TlsSize();
577 void ListOfModules::init() {
579 MemoryMappingLayout
memory_mapping(false);
580 memory_mapping
.DumpListOfModules(&modules_
);
583 void ListOfModules::fallbackInit() { clear(); }
585 static HandleSignalMode
GetHandleSignalModeImpl(int signum
) {
588 return common_flags()->handle_abort
;
590 return common_flags()->handle_sigill
;
592 return common_flags()->handle_sigtrap
;
594 return common_flags()->handle_sigfpe
;
596 return common_flags()->handle_segv
;
598 return common_flags()->handle_sigbus
;
600 return kHandleSignalNo
;
603 HandleSignalMode
GetHandleSignalMode(int signum
) {
604 // Handling fatal signals on watchOS and tvOS devices is disallowed.
605 if ((SANITIZER_WATCHOS
|| SANITIZER_TVOS
) && !(SANITIZER_IOSSIM
))
606 return kHandleSignalNo
;
607 HandleSignalMode result
= GetHandleSignalModeImpl(signum
);
608 if (result
== kHandleSignalYes
&& !common_flags()->allow_user_segv_handler
)
609 return kHandleSignalExclusive
;
614 // XNU 17 -- macOS 10.13 -- iOS 11 -- tvOS 11 -- watchOS 4
615 constexpr u16
GetOSMajorKernelOffset() {
616 if (TARGET_OS_OSX
) return 4;
617 if (TARGET_OS_IOS
|| TARGET_OS_TV
) return 6;
618 if (TARGET_OS_WATCH
) return 13;
621 using VersStr
= char[64];
623 static void GetOSVersion(VersStr vers
) {
624 uptr len
= sizeof(VersStr
);
625 if (SANITIZER_IOSSIM
) {
626 const char *vers_env
= GetEnv("SIMULATOR_RUNTIME_VERSION");
628 Report("ERROR: Running in simulator but SIMULATOR_RUNTIME_VERSION env "
629 "var is not set.\n");
632 len
= internal_strlcpy(vers
, vers_env
, len
);
635 internal_sysctlbyname("kern.osproductversion", vers
, &len
, nullptr, 0);
637 // Fallback for XNU 17 (macOS 10.13) and below that do not provide the
638 // `kern.osproductversion` property.
639 u16 kernel_major
= GetDarwinKernelVersion().major
;
640 u16 offset
= GetOSMajorKernelOffset();
641 CHECK_LE(kernel_major
, 17);
642 CHECK_GE(kernel_major
, offset
);
643 u16 os_major
= kernel_major
- offset
;
645 auto format
= TARGET_OS_OSX
? "10.%d" : "%d.0";
646 len
= internal_snprintf(vers
, len
, format
, os_major
);
649 CHECK_LT(len
, sizeof(VersStr
));
652 void ParseVersion(const char *vers
, u16
*major
, u16
*minor
) {
653 // Format: <major>.<minor>[.<patch>]\0
654 CHECK_GE(internal_strlen(vers
), 3);
655 const char *p
= vers
;
656 *major
= internal_simple_strtoll(p
, &p
, /*base=*/10);
659 *minor
= internal_simple_strtoll(p
, &p
, /*base=*/10);
662 // Aligned versions example:
663 // macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6
664 static void MapToMacos(u16
*major
, u16
*minor
) {
668 if (TARGET_OS_IOS
|| TARGET_OS_TV
)
670 else if (TARGET_OS_WATCH
)
673 UNREACHABLE("unsupported platform");
675 if (*major
>= 16) { // macOS 11+
677 } else { // macOS 10.15 and below
683 static MacosVersion
GetMacosAlignedVersionInternal() {
688 ParseVersion(vers
, &major
, &minor
);
689 MapToMacos(&major
, &minor
);
691 return MacosVersion(major
, minor
);
694 static_assert(sizeof(MacosVersion
) == sizeof(atomic_uint32_t::Type
),
695 "MacosVersion cache size");
696 static atomic_uint32_t cached_macos_version
;
698 MacosVersion
GetMacosAlignedVersion() {
699 atomic_uint32_t::Type result
=
700 atomic_load(&cached_macos_version
, memory_order_acquire
);
702 MacosVersion version
= GetMacosAlignedVersionInternal();
703 result
= *reinterpret_cast<atomic_uint32_t::Type
*>(&version
);
704 atomic_store(&cached_macos_version
, result
, memory_order_release
);
706 return *reinterpret_cast<MacosVersion
*>(&result
);
709 DarwinKernelVersion
GetDarwinKernelVersion() {
711 uptr len
= sizeof(VersStr
);
712 int res
= internal_sysctlbyname("kern.osrelease", vers
, &len
, nullptr, 0);
714 CHECK_LT(len
, sizeof(VersStr
));
717 ParseVersion(vers
, &major
, &minor
);
719 return DarwinKernelVersion(major
, minor
);
723 struct task_basic_info info
;
724 unsigned count
= TASK_BASIC_INFO_COUNT
;
725 kern_return_t result
=
726 task_info(mach_task_self(), TASK_BASIC_INFO
, (task_info_t
)&info
, &count
);
727 if (UNLIKELY(result
!= KERN_SUCCESS
)) {
728 Report("Cannot get task info. Error: %d\n", result
);
731 return info
.resident_size
;
734 void *internal_start_thread(void *(*func
)(void *arg
), void *arg
) {
735 // Start the thread with signals blocked, otherwise it can steal user signals.
736 __sanitizer_sigset_t set
, old
;
737 internal_sigfillset(&set
);
738 internal_sigprocmask(SIG_SETMASK
, &set
, &old
);
740 pthread_create(&th
, 0, func
, arg
);
741 internal_sigprocmask(SIG_SETMASK
, &old
, 0);
745 void internal_join_thread(void *th
) { pthread_join((pthread_t
)th
, 0); }
748 static BlockingMutex
syslog_lock(LINKER_INITIALIZED
);
751 void WriteOneLineToSyslog(const char *s
) {
753 syslog_lock
.CheckLocked();
754 asl_log(nullptr, nullptr, ASL_LEVEL_ERR
, "%s", s
);
758 void LogMessageOnPrintf(const char *str
) {
759 // Log all printf output to CrashLog.
760 if (common_flags()->abort_on_error
)
761 CRAppendCrashLogMessage(str
);
764 void LogFullErrorReport(const char *buffer
) {
766 // Log with os_trace. This will make it into the crash log.
767 #if SANITIZER_OS_TRACE
768 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
769 // os_trace requires the message (format parameter) to be a string literal.
770 if (internal_strncmp(SanitizerToolName
, "AddressSanitizer",
771 sizeof("AddressSanitizer") - 1) == 0)
772 os_trace("Address Sanitizer reported a failure.");
773 else if (internal_strncmp(SanitizerToolName
, "UndefinedBehaviorSanitizer",
774 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
775 os_trace("Undefined Behavior Sanitizer reported a failure.");
776 else if (internal_strncmp(SanitizerToolName
, "ThreadSanitizer",
777 sizeof("ThreadSanitizer") - 1) == 0)
778 os_trace("Thread Sanitizer reported a failure.");
780 os_trace("Sanitizer tool reported a failure.");
782 if (common_flags()->log_to_syslog
)
783 os_trace("Consult syslog for more information.");
788 // The logging on OS X may call pthread_create so we need the threading
789 // environment to be fully initialized. Also, this should never be called when
790 // holding the thread registry lock since that may result in a deadlock. If
791 // the reporting thread holds the thread registry mutex, and asl_log waits
792 // for GCD to dispatch a new thread, the process will deadlock, because the
793 // pthread_create wrapper needs to acquire the lock as well.
794 BlockingMutexLock
l(&syslog_lock
);
795 if (common_flags()->log_to_syslog
)
796 WriteToSyslog(buffer
);
798 // The report is added to CrashLog as part of logging all of Printf output.
802 SignalContext::WriteFlag
SignalContext::GetWriteFlag() const {
803 #if defined(__x86_64__) || defined(__i386__)
804 ucontext_t
*ucontext
= static_cast<ucontext_t
*>(context
);
805 return ucontext
->uc_mcontext
->__es
.__err
& 2 /*T_PF_WRITE*/ ? WRITE
: READ
;
811 bool SignalContext::IsTrueFaultingAddress() const {
812 auto si
= static_cast<const siginfo_t
*>(siginfo
);
813 // "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
814 return si
->si_signo
== SIGSEGV
&& si
->si_code
!= 0;
817 #if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
818 #define AARCH64_GET_REG(r) \
819 (uptr)ptrauth_strip( \
820 (void *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0)
822 #define AARCH64_GET_REG(r) ucontext->uc_mcontext->__ss.__##r
825 static void GetPcSpBp(void *context
, uptr
*pc
, uptr
*sp
, uptr
*bp
) {
826 ucontext_t
*ucontext
= (ucontext_t
*)context
;
827 # if defined(__aarch64__)
828 *pc
= AARCH64_GET_REG(pc
);
829 # if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
830 *bp
= AARCH64_GET_REG(fp
);
832 *bp
= AARCH64_GET_REG(lr
);
834 *sp
= AARCH64_GET_REG(sp
);
835 # elif defined(__x86_64__)
836 *pc
= ucontext
->uc_mcontext
->__ss
.__rip
;
837 *bp
= ucontext
->uc_mcontext
->__ss
.__rbp
;
838 *sp
= ucontext
->uc_mcontext
->__ss
.__rsp
;
839 # elif defined(__arm__)
840 *pc
= ucontext
->uc_mcontext
->__ss
.__pc
;
841 *bp
= ucontext
->uc_mcontext
->__ss
.__r
[7];
842 *sp
= ucontext
->uc_mcontext
->__ss
.__sp
;
843 # elif defined(__i386__)
844 *pc
= ucontext
->uc_mcontext
->__ss
.__eip
;
845 *bp
= ucontext
->uc_mcontext
->__ss
.__ebp
;
846 *sp
= ucontext
->uc_mcontext
->__ss
.__esp
;
848 # error "Unknown architecture"
852 void SignalContext::InitPcSpBp() {
853 addr
= (uptr
)ptrauth_strip((void *)addr
, 0);
854 GetPcSpBp(context
, &pc
, &sp
, &bp
);
857 // ASan/TSan use mmap in a way that creates “deallocation gaps” which triggers
858 // EXC_GUARD exceptions on macOS 10.15+ (XNU 19.0+).
859 static void DisableMmapExcGuardExceptions() {
860 using task_exc_guard_behavior_t
= uint32_t;
861 using task_set_exc_guard_behavior_t
=
862 kern_return_t(task_t task
, task_exc_guard_behavior_t behavior
);
863 auto *set_behavior
= (task_set_exc_guard_behavior_t
*)dlsym(
864 RTLD_DEFAULT
, "task_set_exc_guard_behavior");
865 if (set_behavior
== nullptr) return;
866 const task_exc_guard_behavior_t task_exc_guard_none
= 0;
867 set_behavior(mach_task_self(), task_exc_guard_none
);
870 void InitializePlatformEarly() {
871 // Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
873 #if defined(__x86_64__)
874 GetDarwinKernelVersion() >= DarwinKernelVersion(17, 5);
878 if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0))
879 DisableMmapExcGuardExceptions();
883 static const char kDyldInsertLibraries
[] = "DYLD_INSERT_LIBRARIES";
884 LowLevelAllocator allocator_for_env
;
886 // Change the value of the env var |name|, leaking the original value.
887 // If |name_value| is NULL, the variable is deleted from the environment,
888 // otherwise the corresponding "NAME=value" string is replaced with
890 void LeakyResetEnv(const char *name
, const char *name_value
) {
891 char **env
= GetEnviron();
892 uptr name_len
= internal_strlen(name
);
894 uptr len
= internal_strlen(*env
);
895 if (len
> name_len
) {
896 const char *p
= *env
;
897 if (!internal_memcmp(p
, name
, name_len
) && p
[name_len
] == '=') {
900 // Replace the old value with the new one.
901 *env
= const_cast<char*>(name_value
);
903 // Shift the subsequent pointers back.
915 SANITIZER_WEAK_CXX_DEFAULT_IMPL
916 bool ReexecDisabled() {
920 static bool DyldNeedsEnvVariable() {
921 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
922 // DYLD_INSERT_LIBRARIES is not set.
923 return GetMacosAlignedVersion() < MacosVersion(10, 11);
927 // FIXME: This should really live in some "InitializePlatform" method.
930 if (ReexecDisabled()) return;
932 // Make sure the dynamic runtime library is preloaded so that the
933 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
936 RAW_CHECK(dladdr((void*)((uptr
)&__sanitizer_report_error_summary
), &info
));
937 char *dyld_insert_libraries
=
938 const_cast<char*>(GetEnv(kDyldInsertLibraries
));
939 uptr old_env_len
= dyld_insert_libraries
?
940 internal_strlen(dyld_insert_libraries
) : 0;
941 uptr fname_len
= internal_strlen(info
.dli_fname
);
942 const char *dylib_name
= StripModuleName(info
.dli_fname
);
943 uptr dylib_name_len
= internal_strlen(dylib_name
);
945 bool lib_is_in_env
= dyld_insert_libraries
&&
946 internal_strstr(dyld_insert_libraries
, dylib_name
);
947 if (DyldNeedsEnvVariable() && !lib_is_in_env
) {
948 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
950 InternalScopedString
program_name(1024);
951 uint32_t buf_size
= program_name
.size();
952 _NSGetExecutablePath(program_name
.data(), &buf_size
);
953 char *new_env
= const_cast<char*>(info
.dli_fname
);
954 if (dyld_insert_libraries
) {
955 // Append the runtime dylib name to the existing value of
956 // DYLD_INSERT_LIBRARIES.
957 new_env
= (char*)allocator_for_env
.Allocate(old_env_len
+ fname_len
+ 2);
958 internal_strncpy(new_env
, dyld_insert_libraries
, old_env_len
);
959 new_env
[old_env_len
] = ':';
960 // Copy fname_len and add a trailing zero.
961 internal_strncpy(new_env
+ old_env_len
+ 1, info
.dli_fname
,
963 // Ok to use setenv() since the wrappers don't depend on the value of
965 setenv(kDyldInsertLibraries
, new_env
, /*overwrite*/1);
967 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
968 setenv(kDyldInsertLibraries
, info
.dli_fname
, /*overwrite*/0);
970 VReport(1, "exec()-ing the program with\n");
971 VReport(1, "%s=%s\n", kDyldInsertLibraries
, new_env
);
972 VReport(1, "to enable wrappers.\n");
973 execv(program_name
.data(), *_NSGetArgv());
975 // We get here only if execv() failed.
976 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
977 "which is required for the sanitizer to work. We tried to set the "
978 "environment variable and re-execute itself, but execv() failed, "
979 "possibly because of sandbox restrictions. Make sure to launch the "
980 "executable with:\n%s=%s\n", kDyldInsertLibraries
, new_env
);
981 RAW_CHECK("execv failed" && 0);
984 // Verify that interceptors really work. We'll use dlsym to locate
985 // "pthread_create", if interceptors are working, it should really point to
986 // "wrap_pthread_create" within our own dylib.
987 Dl_info info_pthread_create
;
988 void *dlopen_addr
= dlsym(RTLD_DEFAULT
, "pthread_create");
989 RAW_CHECK(dladdr(dlopen_addr
, &info_pthread_create
));
990 if (internal_strcmp(info
.dli_fname
, info_pthread_create
.dli_fname
) != 0) {
992 "ERROR: Interceptors are not working. This may be because %s is "
993 "loaded too late (e.g. via dlopen). Please launch the executable "
995 SanitizerToolName
, kDyldInsertLibraries
, info
.dli_fname
);
996 RAW_CHECK("interceptors not installed" && 0);
1002 if (!common_flags()->strip_env
)
1005 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
1006 // the dylib from the environment variable, because interceptors are installed
1007 // and we don't want our children to inherit the variable.
1009 uptr env_name_len
= internal_strlen(kDyldInsertLibraries
);
1010 // Allocate memory to hold the previous env var name, its value, the '='
1011 // sign and the '\0' char.
1012 char *new_env
= (char*)allocator_for_env
.Allocate(
1013 old_env_len
+ 2 + env_name_len
);
1015 internal_memset(new_env
, '\0', old_env_len
+ 2 + env_name_len
);
1016 internal_strncpy(new_env
, kDyldInsertLibraries
, env_name_len
);
1017 new_env
[env_name_len
] = '=';
1018 char *new_env_pos
= new_env
+ env_name_len
+ 1;
1020 // Iterate over colon-separated pieces of |dyld_insert_libraries|.
1021 char *piece_start
= dyld_insert_libraries
;
1022 char *piece_end
= NULL
;
1023 char *old_env_end
= dyld_insert_libraries
+ old_env_len
;
1025 if (piece_start
[0] == ':') piece_start
++;
1026 piece_end
= internal_strchr(piece_start
, ':');
1027 if (!piece_end
) piece_end
= dyld_insert_libraries
+ old_env_len
;
1028 if ((uptr
)(piece_start
- dyld_insert_libraries
) > old_env_len
) break;
1029 uptr piece_len
= piece_end
- piece_start
;
1031 char *filename_start
=
1032 (char *)internal_memrchr(piece_start
, '/', piece_len
);
1033 uptr filename_len
= piece_len
;
1034 if (filename_start
) {
1035 filename_start
+= 1;
1036 filename_len
= piece_len
- (filename_start
- piece_start
);
1038 filename_start
= piece_start
;
1041 // If the current piece isn't the runtime library name,
1042 // append it to new_env.
1043 if ((dylib_name_len
!= filename_len
) ||
1044 (internal_memcmp(filename_start
, dylib_name
, dylib_name_len
) != 0)) {
1045 if (new_env_pos
!= new_env
+ env_name_len
+ 1) {
1046 new_env_pos
[0] = ':';
1049 internal_strncpy(new_env_pos
, piece_start
, piece_len
);
1050 new_env_pos
+= piece_len
;
1052 // Move on to the next piece.
1053 piece_start
= piece_end
;
1054 } while (piece_start
< old_env_end
);
1056 // Can't use setenv() here, because it requires the allocator to be
1058 // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
1059 // a separate function called after InitializeAllocator().
1060 if (new_env_pos
== new_env
+ env_name_len
+ 1) new_env
= NULL
;
1061 LeakyResetEnv(kDyldInsertLibraries
, new_env
);
1063 #endif // SANITIZER_GO
1066 return *_NSGetArgv();
1070 // The task_vm_info struct is normally provided by the macOS SDK, but we need
1071 // fields only available in 10.12+. Declare the struct manually to be able to
1072 // build against older SDKs.
1073 struct __sanitizer_task_vm_info
{
1074 mach_vm_size_t virtual_size
;
1075 integer_t region_count
;
1076 integer_t page_size
;
1077 mach_vm_size_t resident_size
;
1078 mach_vm_size_t resident_size_peak
;
1079 mach_vm_size_t device
;
1080 mach_vm_size_t device_peak
;
1081 mach_vm_size_t internal
;
1082 mach_vm_size_t internal_peak
;
1083 mach_vm_size_t external
;
1084 mach_vm_size_t external_peak
;
1085 mach_vm_size_t reusable
;
1086 mach_vm_size_t reusable_peak
;
1087 mach_vm_size_t purgeable_volatile_pmap
;
1088 mach_vm_size_t purgeable_volatile_resident
;
1089 mach_vm_size_t purgeable_volatile_virtual
;
1090 mach_vm_size_t compressed
;
1091 mach_vm_size_t compressed_peak
;
1092 mach_vm_size_t compressed_lifetime
;
1093 mach_vm_size_t phys_footprint
;
1094 mach_vm_address_t min_address
;
1095 mach_vm_address_t max_address
;
1097 #define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \
1098 (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t)))
1100 static uptr
GetTaskInfoMaxAddress() {
1101 __sanitizer_task_vm_info vm_info
= {} /* zero initialize */;
1102 mach_msg_type_number_t count
= __SANITIZER_TASK_VM_INFO_COUNT
;
1103 int err
= task_info(mach_task_self(), TASK_VM_INFO
, (int *)&vm_info
, &count
);
1104 return err
? 0 : vm_info
.max_address
;
1107 uptr
GetMaxUserVirtualAddress() {
1108 static uptr max_vm
= GetTaskInfoMaxAddress();
1112 // xnu cannot provide vm address limit
1113 # if SANITIZER_WORDSIZE == 32
1114 return 0xffe00000 - 1;
1116 return 0x200000000 - 1;
1120 #else // !SANITIZER_IOS
1122 uptr
GetMaxUserVirtualAddress() {
1123 # if SANITIZER_WORDSIZE == 64
1124 return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
1125 # else // SANITIZER_WORDSIZE == 32
1126 static_assert(SANITIZER_WORDSIZE
== 32, "Wrong wordsize");
1127 return (1ULL << 32) - 1; // 0xffffffff;
1132 uptr
GetMaxVirtualAddress() {
1133 return GetMaxUserVirtualAddress();
1136 uptr
MapDynamicShadow(uptr shadow_size_bytes
, uptr shadow_scale
,
1137 uptr min_shadow_base_alignment
, uptr
&high_mem_end
) {
1138 const uptr granularity
= GetMmapGranularity();
1139 const uptr alignment
=
1140 Max
<uptr
>(granularity
<< shadow_scale
, 1ULL << min_shadow_base_alignment
);
1141 const uptr left_padding
=
1142 Max
<uptr
>(granularity
, 1ULL << min_shadow_base_alignment
);
1144 uptr space_size
= shadow_size_bytes
+ left_padding
;
1146 uptr largest_gap_found
= 0;
1147 uptr max_occupied_addr
= 0;
1148 VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size
);
1150 FindAvailableMemoryRange(space_size
, alignment
, granularity
,
1151 &largest_gap_found
, &max_occupied_addr
);
1152 // If the shadow doesn't fit, restrict the address space to make it fit.
1153 if (shadow_start
== 0) {
1156 "Shadow doesn't fit, largest_gap_found = %p, max_occupied_addr = %p\n",
1157 largest_gap_found
, max_occupied_addr
);
1158 uptr new_max_vm
= RoundDownTo(largest_gap_found
<< shadow_scale
, alignment
);
1159 if (new_max_vm
< max_occupied_addr
) {
1160 Report("Unable to find a memory range for dynamic shadow.\n");
1162 "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
1163 "new_max_vm = %p\n",
1164 space_size
, largest_gap_found
, max_occupied_addr
, new_max_vm
);
1165 CHECK(0 && "cannot place shadow");
1167 RestrictMemoryToMaxAddress(new_max_vm
);
1168 high_mem_end
= new_max_vm
- 1;
1169 space_size
= (high_mem_end
>> shadow_scale
) + left_padding
;
1170 VReport(2, "FindDynamicShadowStart, space_size = %p\n", space_size
);
1171 shadow_start
= FindAvailableMemoryRange(space_size
, alignment
, granularity
,
1173 if (shadow_start
== 0) {
1174 Report("Unable to find a memory range after restricting VM.\n");
1175 CHECK(0 && "cannot place shadow after restricting vm");
1178 CHECK_NE((uptr
)0, shadow_start
);
1179 CHECK(IsAligned(shadow_start
, alignment
));
1180 return shadow_start
;
1183 uptr
FindAvailableMemoryRange(uptr size
, uptr alignment
, uptr left_padding
,
1184 uptr
*largest_gap_found
,
1185 uptr
*max_occupied_addr
) {
1186 typedef vm_region_submap_short_info_data_64_t RegionInfo
;
1187 enum { kRegionInfoSize
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
};
1188 // Start searching for available memory region past PAGEZERO, which is
1189 // 4KB on 32-bit and 4GB on 64-bit.
1190 mach_vm_address_t start_address
=
1191 (SANITIZER_WORDSIZE
== 32) ? 0x000000001000 : 0x000100000000;
1193 mach_vm_address_t address
= start_address
;
1194 mach_vm_address_t free_begin
= start_address
;
1195 kern_return_t kr
= KERN_SUCCESS
;
1196 if (largest_gap_found
) *largest_gap_found
= 0;
1197 if (max_occupied_addr
) *max_occupied_addr
= 0;
1198 while (kr
== KERN_SUCCESS
) {
1199 mach_vm_size_t vmsize
= 0;
1200 natural_t depth
= 0;
1202 mach_msg_type_number_t count
= kRegionInfoSize
;
1203 kr
= mach_vm_region_recurse(mach_task_self(), &address
, &vmsize
, &depth
,
1204 (vm_region_info_t
)&vminfo
, &count
);
1205 if (kr
== KERN_INVALID_ADDRESS
) {
1206 // No more regions beyond "address", consider the gap at the end of VM.
1207 address
= GetMaxVirtualAddress() + 1;
1210 if (max_occupied_addr
) *max_occupied_addr
= address
+ vmsize
;
1212 if (free_begin
!= address
) {
1213 // We found a free region [free_begin..address-1].
1214 uptr gap_start
= RoundUpTo((uptr
)free_begin
+ left_padding
, alignment
);
1215 uptr gap_end
= RoundDownTo((uptr
)address
, alignment
);
1216 uptr gap_size
= gap_end
> gap_start
? gap_end
- gap_start
: 0;
1217 if (size
< gap_size
) {
1221 if (largest_gap_found
&& *largest_gap_found
< gap_size
) {
1222 *largest_gap_found
= gap_size
;
1225 // Move to the next region.
1227 free_begin
= address
;
1230 // We looked at all free regions and could not find one large enough.
1234 // FIXME implement on this platform.
1235 void GetMemoryProfile(fill_profile_f cb
, uptr
*stats
, uptr stats_size
) { }
1237 void SignalContext::DumpAllRegisters(void *context
) {
1238 Report("Register values:\n");
1240 ucontext_t
*ucontext
= (ucontext_t
*)context
;
1241 # define DUMPREG64(r) \
1242 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1243 # define DUMPREGA64(r) \
1244 Printf(" %s = 0x%016llx ", #r, AARCH64_GET_REG(r));
1245 # define DUMPREG32(r) \
1246 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1247 # define DUMPREG_(r) Printf(" "); DUMPREG(r);
1248 # define DUMPREG__(r) Printf(" "); DUMPREG(r);
1249 # define DUMPREG___(r) Printf(" "); DUMPREG(r);
1251 # if defined(__x86_64__)
1252 # define DUMPREG(r) DUMPREG64(r)
1253 DUMPREG(rax
); DUMPREG(rbx
); DUMPREG(rcx
); DUMPREG(rdx
); Printf("\n");
1254 DUMPREG(rdi
); DUMPREG(rsi
); DUMPREG(rbp
); DUMPREG(rsp
); Printf("\n");
1255 DUMPREG_(r8
); DUMPREG_(r9
); DUMPREG(r10
); DUMPREG(r11
); Printf("\n");
1256 DUMPREG(r12
); DUMPREG(r13
); DUMPREG(r14
); DUMPREG(r15
); Printf("\n");
1257 # elif defined(__i386__)
1258 # define DUMPREG(r) DUMPREG32(r)
1259 DUMPREG(eax
); DUMPREG(ebx
); DUMPREG(ecx
); DUMPREG(edx
); Printf("\n");
1260 DUMPREG(edi
); DUMPREG(esi
); DUMPREG(ebp
); DUMPREG(esp
); Printf("\n");
1261 # elif defined(__aarch64__)
1262 # define DUMPREG(r) DUMPREG64(r)
1263 DUMPREG_(x
[0]); DUMPREG_(x
[1]); DUMPREG_(x
[2]); DUMPREG_(x
[3]); Printf("\n");
1264 DUMPREG_(x
[4]); DUMPREG_(x
[5]); DUMPREG_(x
[6]); DUMPREG_(x
[7]); Printf("\n");
1265 DUMPREG_(x
[8]); DUMPREG_(x
[9]); DUMPREG(x
[10]); DUMPREG(x
[11]); Printf("\n");
1266 DUMPREG(x
[12]); DUMPREG(x
[13]); DUMPREG(x
[14]); DUMPREG(x
[15]); Printf("\n");
1267 DUMPREG(x
[16]); DUMPREG(x
[17]); DUMPREG(x
[18]); DUMPREG(x
[19]); Printf("\n");
1268 DUMPREG(x
[20]); DUMPREG(x
[21]); DUMPREG(x
[22]); DUMPREG(x
[23]); Printf("\n");
1269 DUMPREG(x
[24]); DUMPREG(x
[25]); DUMPREG(x
[26]); DUMPREG(x
[27]); Printf("\n");
1270 DUMPREG(x
[28]); DUMPREGA64(fp
); DUMPREGA64(lr
); DUMPREGA64(sp
); Printf("\n");
1271 # elif defined(__arm__)
1272 # define DUMPREG(r) DUMPREG32(r)
1273 DUMPREG_(r
[0]); DUMPREG_(r
[1]); DUMPREG_(r
[2]); DUMPREG_(r
[3]); Printf("\n");
1274 DUMPREG_(r
[4]); DUMPREG_(r
[5]); DUMPREG_(r
[6]); DUMPREG_(r
[7]); Printf("\n");
1275 DUMPREG_(r
[8]); DUMPREG_(r
[9]); DUMPREG(r
[10]); DUMPREG(r
[11]); Printf("\n");
1276 DUMPREG(r
[12]); DUMPREG___(sp
); DUMPREG___(lr
); DUMPREG___(pc
); Printf("\n");
1278 # error "Unknown architecture"
1289 static inline bool CompareBaseAddress(const LoadedModule
&a
,
1290 const LoadedModule
&b
) {
1291 return a
.base_address() < b
.base_address();
1294 void FormatUUID(char *out
, uptr size
, const u8
*uuid
) {
1295 internal_snprintf(out
, size
,
1296 "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
1297 "%02X%02X%02X%02X%02X%02X>",
1298 uuid
[0], uuid
[1], uuid
[2], uuid
[3], uuid
[4], uuid
[5],
1299 uuid
[6], uuid
[7], uuid
[8], uuid
[9], uuid
[10], uuid
[11],
1300 uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
1303 void PrintModuleMap() {
1304 Printf("Process module map:\n");
1305 MemoryMappingLayout
memory_mapping(false);
1306 InternalMmapVector
<LoadedModule
> modules
;
1307 modules
.reserve(128);
1308 memory_mapping
.DumpListOfModules(&modules
);
1309 Sort(modules
.data(), modules
.size(), CompareBaseAddress
);
1310 for (uptr i
= 0; i
< modules
.size(); ++i
) {
1312 FormatUUID(uuid_str
, sizeof(uuid_str
), modules
[i
].uuid());
1313 Printf("0x%zx-0x%zx %s (%s) %s\n", modules
[i
].base_address(),
1314 modules
[i
].max_executable_address(), modules
[i
].full_name(),
1315 ModuleArchToString(modules
[i
].arch()), uuid_str
);
1317 Printf("End of module map.\n");
1320 void CheckNoDeepBind(const char *filename
, int flag
) {
1324 bool GetRandom(void *buffer
, uptr length
, bool blocking
) {
1325 if (!buffer
|| !length
|| length
> 256)
1327 // arc4random never fails.
1328 REAL(arc4random_buf
)(buffer
, length
);
1332 u32
GetNumberOfCPUs() {
1333 return (u32
)sysconf(_SC_NPROCESSORS_ONLN
);
1336 } // namespace __sanitizer
1338 #endif // SANITIZER_MAC