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_interface_internal.h"
29 #include "sanitizer_internal_defs.h"
30 #include "sanitizer_libc.h"
31 #include "sanitizer_platform_limits_posix.h"
32 #include "sanitizer_procmaps.h"
33 #include "sanitizer_ptrauth.h"
36 #include <crt_externs.h> // for _NSGetEnviron
38 extern char **environ
;
41 #if defined(__has_include) && __has_include(<os/trace.h>)
42 #define SANITIZER_OS_TRACE 1
45 #define SANITIZER_OS_TRACE 0
48 // import new crash reporting api
49 #if defined(__has_include) && __has_include(<CrashReporterClient.h>)
50 #define HAVE_CRASHREPORTERCLIENT_H 1
51 #include <CrashReporterClient.h>
53 #define HAVE_CRASHREPORTERCLIENT_H 0
57 #include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
60 extern char ***_NSGetArgv(void);
65 #include <dlfcn.h> // for dladdr()
68 #include <libkern/OSAtomic.h>
69 #include <mach-o/dyld.h>
70 #include <mach/mach.h>
71 #include <mach/mach_time.h>
72 #include <mach/vm_statistics.h>
73 #include <malloc/malloc.h>
80 #include <sys/ioctl.h>
82 #include <sys/resource.h>
84 #include <sys/sysctl.h>
85 #include <sys/types.h>
90 // From <crt_externs.h>, but we don't have that file on iOS.
92 extern char ***_NSGetArgv(void);
93 extern char ***_NSGetEnviron(void);
96 // From <mach/mach_vm.h>, but we don't have that file on iOS.
98 extern kern_return_t
mach_vm_region_recurse(
100 mach_vm_address_t
*address
,
101 mach_vm_size_t
*size
,
102 natural_t
*nesting_depth
,
103 vm_region_recurse_info_t info
,
104 mach_msg_type_number_t
*infoCnt
);
107 namespace __sanitizer
{
109 #include "sanitizer_syscall_generic.inc"
111 // Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
112 extern "C" void *__mmap(void *addr
, size_t len
, int prot
, int flags
, int fildes
,
113 off_t off
) SANITIZER_WEAK_ATTRIBUTE
;
114 extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE
;
116 // ---------------------- sanitizer_libc.h
118 // From <mach/vm_statistics.h>, but not on older OSs.
119 #ifndef VM_MEMORY_SANITIZER
120 #define VM_MEMORY_SANITIZER 99
123 // XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of
124 // giant memory regions (i.e. shadow memory regions).
125 #define kXnuFastMmapFd 0x4
126 static size_t kXnuFastMmapThreshold
= 2 << 30; // 2 GB
127 static bool use_xnu_fast_mmap
= false;
129 uptr
internal_mmap(void *addr
, size_t length
, int prot
, int flags
,
130 int fd
, u64 offset
) {
132 fd
= VM_MAKE_TAG(VM_MEMORY_SANITIZER
);
133 if (length
>= kXnuFastMmapThreshold
) {
134 if (use_xnu_fast_mmap
) fd
|= kXnuFastMmapFd
;
137 if (&__mmap
) return (uptr
)__mmap(addr
, length
, prot
, flags
, fd
, offset
);
138 return (uptr
)mmap(addr
, length
, prot
, flags
, fd
, offset
);
141 uptr
internal_munmap(void *addr
, uptr length
) {
142 if (&__munmap
) return __munmap(addr
, length
);
143 return munmap(addr
, length
);
146 uptr
internal_mremap(void *old_address
, uptr old_size
, uptr new_size
, int flags
,
148 CHECK(false && "internal_mremap is unimplemented on Mac");
152 int internal_mprotect(void *addr
, uptr length
, int prot
) {
153 return mprotect(addr
, length
, prot
);
156 int internal_madvise(uptr addr
, uptr length
, int advice
) {
157 return madvise((void *)addr
, length
, advice
);
160 uptr
internal_close(fd_t fd
) {
164 uptr
internal_open(const char *filename
, int flags
) {
165 return open(filename
, flags
);
168 uptr
internal_open(const char *filename
, int flags
, u32 mode
) {
169 return open(filename
, flags
, mode
);
172 uptr
internal_read(fd_t fd
, void *buf
, uptr count
) {
173 return read(fd
, buf
, count
);
176 uptr
internal_write(fd_t fd
, const void *buf
, uptr count
) {
177 return write(fd
, buf
, count
);
180 uptr
internal_stat(const char *path
, void *buf
) {
181 return stat(path
, (struct stat
*)buf
);
184 uptr
internal_lstat(const char *path
, void *buf
) {
185 return lstat(path
, (struct stat
*)buf
);
188 uptr
internal_fstat(fd_t fd
, void *buf
) {
189 return fstat(fd
, (struct stat
*)buf
);
192 uptr
internal_filesize(fd_t fd
) {
194 if (internal_fstat(fd
, &st
))
196 return (uptr
)st
.st_size
;
199 uptr
internal_dup(int oldfd
) {
203 uptr
internal_dup2(int oldfd
, int newfd
) {
204 return dup2(oldfd
, newfd
);
207 uptr
internal_readlink(const char *path
, char *buf
, uptr bufsize
) {
208 return readlink(path
, buf
, bufsize
);
211 uptr
internal_unlink(const char *path
) {
215 uptr
internal_sched_yield() {
216 return sched_yield();
219 void internal__exit(int exitcode
) {
223 void internal_usleep(u64 useconds
) { usleep(useconds
); }
225 uptr
internal_getpid() {
229 int internal_dlinfo(void *handle
, int request
, void *p
) {
233 int internal_sigaction(int signum
, const void *act
, void *oldact
) {
234 return sigaction(signum
,
235 (const struct sigaction
*)act
, (struct sigaction
*)oldact
);
238 void internal_sigfillset(__sanitizer_sigset_t
*set
) { sigfillset(set
); }
240 uptr
internal_sigprocmask(int how
, __sanitizer_sigset_t
*set
,
241 __sanitizer_sigset_t
*oldset
) {
242 // Don't use sigprocmask here, because it affects all threads.
243 return pthread_sigmask(how
, set
, oldset
);
246 // Doesn't call pthread_atfork() handlers (but not available on 10.6).
247 extern "C" pid_t
__fork(void) SANITIZER_WEAK_ATTRIBUTE
;
249 int internal_fork() {
255 int internal_sysctl(const int *name
, unsigned int namelen
, void *oldp
,
256 uptr
*oldlenp
, const void *newp
, uptr newlen
) {
257 return sysctl(const_cast<int *>(name
), namelen
, oldp
, (size_t *)oldlenp
,
258 const_cast<void *>(newp
), (size_t)newlen
);
261 int internal_sysctlbyname(const char *sname
, void *oldp
, uptr
*oldlenp
,
262 const void *newp
, uptr newlen
) {
263 return sysctlbyname(sname
, oldp
, (size_t *)oldlenp
, const_cast<void *>(newp
),
267 static fd_t
internal_spawn_impl(const char *argv
[], const char *envp
[],
269 fd_t primary_fd
= kInvalidFd
;
270 fd_t secondary_fd
= kInvalidFd
;
272 auto fd_closer
= at_scope_exit([&] {
273 internal_close(primary_fd
);
274 internal_close(secondary_fd
);
277 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
278 // in particular detects when it's talking to a pipe and forgets to flush the
279 // output stream after sending a response.
280 primary_fd
= posix_openpt(O_RDWR
);
281 if (primary_fd
== kInvalidFd
)
284 int res
= grantpt(primary_fd
) || unlockpt(primary_fd
);
285 if (res
!= 0) return kInvalidFd
;
287 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
288 char secondary_pty_name
[128];
289 res
= ioctl(primary_fd
, TIOCPTYGNAME
, secondary_pty_name
);
290 if (res
== -1) return kInvalidFd
;
292 secondary_fd
= internal_open(secondary_pty_name
, O_RDWR
);
293 if (secondary_fd
== kInvalidFd
)
296 // File descriptor actions
297 posix_spawn_file_actions_t acts
;
298 res
= posix_spawn_file_actions_init(&acts
);
299 if (res
!= 0) return kInvalidFd
;
301 auto acts_cleanup
= at_scope_exit([&] {
302 posix_spawn_file_actions_destroy(&acts
);
305 res
= posix_spawn_file_actions_adddup2(&acts
, secondary_fd
, STDIN_FILENO
) ||
306 posix_spawn_file_actions_adddup2(&acts
, secondary_fd
, STDOUT_FILENO
) ||
307 posix_spawn_file_actions_addclose(&acts
, secondary_fd
);
308 if (res
!= 0) return kInvalidFd
;
311 posix_spawnattr_t attrs
;
312 res
= posix_spawnattr_init(&attrs
);
313 if (res
!= 0) return kInvalidFd
;
315 auto attrs_cleanup
= at_scope_exit([&] {
316 posix_spawnattr_destroy(&attrs
);
319 // In the spawned process, close all file descriptors that are not explicitly
320 // described by the file actions object. This is Darwin-specific extension.
321 res
= posix_spawnattr_setflags(&attrs
, POSIX_SPAWN_CLOEXEC_DEFAULT
);
322 if (res
!= 0) return kInvalidFd
;
325 char **argv_casted
= const_cast<char **>(argv
);
326 char **envp_casted
= const_cast<char **>(envp
);
327 res
= posix_spawn(pid
, argv
[0], &acts
, &attrs
, argv_casted
, envp_casted
);
328 if (res
!= 0) return kInvalidFd
;
330 // Disable echo in the new terminal, disable CR.
331 struct termios termflags
;
332 tcgetattr(primary_fd
, &termflags
);
333 termflags
.c_oflag
&= ~ONLCR
;
334 termflags
.c_lflag
&= ~ECHO
;
335 tcsetattr(primary_fd
, TCSANOW
, &termflags
);
337 // On success, do not close primary_fd on scope exit.
338 fd_t fd
= primary_fd
;
339 primary_fd
= kInvalidFd
;
344 fd_t
internal_spawn(const char *argv
[], const char *envp
[], pid_t
*pid
) {
345 // The client program may close its stdin and/or stdout and/or stderr thus
346 // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
347 // case the communication is broken if either the parent or the child tries to
348 // close or duplicate these descriptors. We temporarily reserve these
349 // descriptors here to prevent this.
353 for (; count
< 3; count
++) {
354 low_fds
[count
] = posix_openpt(O_RDWR
);
355 if (low_fds
[count
] >= STDERR_FILENO
)
359 fd_t fd
= internal_spawn_impl(argv
, envp
, pid
);
361 for (; count
> 0; count
--) {
362 internal_close(low_fds
[count
]);
368 uptr
internal_rename(const char *oldpath
, const char *newpath
) {
369 return rename(oldpath
, newpath
);
372 uptr
internal_ftruncate(fd_t fd
, uptr size
) {
373 return ftruncate(fd
, size
);
376 uptr
internal_execve(const char *filename
, char *const argv
[],
377 char *const envp
[]) {
378 return execve(filename
, argv
, envp
);
381 uptr
internal_waitpid(int pid
, int *status
, int options
) {
382 return waitpid(pid
, status
, options
);
385 // ----------------- sanitizer_common.h
386 bool FileExists(const char *filename
) {
387 if (ShouldMockFailureToOpen(filename
))
390 if (stat(filename
, &st
))
392 // Sanity check: filename is a regular file.
393 return S_ISREG(st
.st_mode
);
396 bool DirExists(const char *path
) {
400 return S_ISDIR(st
.st_mode
);
405 pthread_threadid_np(nullptr, &tid
);
409 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
410 uptr
*stack_bottom
) {
413 uptr stacksize
= pthread_get_stacksize_np(pthread_self());
414 // pthread_get_stacksize_np() returns an incorrect stack size for the main
415 // thread on Mavericks. See
416 // https://github.com/google/sanitizers/issues/261
417 if ((GetMacosAlignedVersion() >= MacosVersion(10, 9)) && at_initialization
&&
418 stacksize
== (1 << 19)) {
420 CHECK_EQ(getrlimit(RLIMIT_STACK
, &rl
), 0);
421 // Most often rl.rlim_cur will be the desired 8M.
422 if (rl
.rlim_cur
< kMaxThreadStackSize
) {
423 stacksize
= rl
.rlim_cur
;
425 stacksize
= kMaxThreadStackSize
;
428 void *stackaddr
= pthread_get_stackaddr_np(pthread_self());
429 *stack_top
= (uptr
)stackaddr
;
430 *stack_bottom
= *stack_top
- stacksize
;
433 char **GetEnviron() {
435 char ***env_ptr
= _NSGetEnviron();
437 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
438 "called after libSystem_initializer().\n");
441 char **environ
= *env_ptr
;
447 const char *GetEnv(const char *name
) {
448 char **env
= GetEnviron();
449 uptr name_len
= internal_strlen(name
);
451 uptr len
= internal_strlen(*env
);
452 if (len
> name_len
) {
453 const char *p
= *env
;
454 if (!internal_memcmp(p
, name
, name_len
) &&
455 p
[name_len
] == '=') { // Match.
456 return *env
+ name_len
+ 1; // String starting after =.
464 uptr
ReadBinaryName(/*out*/char *buf
, uptr buf_len
) {
465 CHECK_LE(kMaxPathLength
, buf_len
);
467 // On OS X the executable path is saved to the stack by dyld. Reading it
468 // from there is much faster than calling dladdr, especially for large
469 // binaries with symbols.
470 InternalMmapVector
<char> exe_path(kMaxPathLength
);
471 uint32_t size
= exe_path
.size();
472 if (_NSGetExecutablePath(exe_path
.data(), &size
) == 0 &&
473 realpath(exe_path
.data(), buf
) != 0) {
474 return internal_strlen(buf
);
479 uptr
ReadLongProcessName(/*out*/char *buf
, uptr buf_len
) {
480 return ReadBinaryName(buf
, buf_len
);
491 void CheckMPROTECT() {
496 return sysconf(_SC_PAGESIZE
);
499 extern "C" unsigned malloc_num_zones
;
500 extern "C" malloc_zone_t
**malloc_zones
;
501 malloc_zone_t sanitizer_zone
;
503 // We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If
504 // libmalloc tries to set up a different zone as malloc_zones[0], it will call
505 // mprotect(malloc_zones, ..., PROT_READ). This interceptor will catch that and
506 // make sure we are still the first (default) zone.
507 void MprotectMallocZones(void *addr
, int prot
) {
508 if (addr
== malloc_zones
&& prot
== PROT_READ
) {
509 if (malloc_num_zones
> 1 && malloc_zones
[0] != &sanitizer_zone
) {
510 for (unsigned i
= 1; i
< malloc_num_zones
; i
++) {
511 if (malloc_zones
[i
] == &sanitizer_zone
) {
512 // Swap malloc_zones[0] and malloc_zones[i].
513 malloc_zones
[i
] = malloc_zones
[0];
514 malloc_zones
[0] = &sanitizer_zone
;
522 void FutexWait(atomic_uint32_t
*p
, u32 cmp
) {
523 // FIXME: implement actual blocking.
527 void FutexWake(atomic_uint32_t
*p
, u32 count
) {}
531 internal_memset(&tv
, 0, sizeof(tv
));
532 gettimeofday(&tv
, 0);
533 return (u64
)tv
.tv_sec
* 1000*1000*1000 + tv
.tv_usec
* 1000;
536 // This needs to be called during initialization to avoid being racy.
537 u64
MonotonicNanoTime() {
538 static mach_timebase_info_data_t timebase_info
;
539 if (timebase_info
.denom
== 0) mach_timebase_info(&timebase_info
);
540 return (mach_absolute_time() * timebase_info
.numer
) / timebase_info
.denom
;
552 #if defined(__x86_64__)
553 asm("movq %%gs:0,%0" : "=r"(segbase
));
554 #elif defined(__i386__)
555 asm("movl %%gs:0,%0" : "=r"(segbase
));
556 #elif defined(__aarch64__)
557 asm("mrs %x0, tpidrro_el0" : "=r"(segbase
));
558 segbase
&= 0x07ul
; // clearing lower bits, cpu id stored there
563 // The size of the tls on darwin does not appear to be well documented,
564 // however the vm memory map suggests that it is 1024 uptrs in size,
565 // with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
567 #if defined(__x86_64__) || defined(__i386__)
568 return 1024 * sizeof(uptr
);
574 void GetThreadStackAndTls(bool main
, uptr
*stk_addr
, uptr
*stk_size
,
575 uptr
*tls_addr
, uptr
*tls_size
) {
577 uptr stack_top
, stack_bottom
;
578 GetThreadStackTopAndBottom(main
, &stack_top
, &stack_bottom
);
579 *stk_addr
= stack_bottom
;
580 *stk_size
= stack_top
- stack_bottom
;
581 *tls_addr
= TlsBaseAddr();
582 *tls_size
= TlsSize();
591 void ListOfModules::init() {
593 MemoryMappingLayout
memory_mapping(false);
594 memory_mapping
.DumpListOfModules(&modules_
);
597 void ListOfModules::fallbackInit() { clear(); }
599 static HandleSignalMode
GetHandleSignalModeImpl(int signum
) {
602 return common_flags()->handle_abort
;
604 return common_flags()->handle_sigill
;
606 return common_flags()->handle_sigtrap
;
608 return common_flags()->handle_sigfpe
;
610 return common_flags()->handle_segv
;
612 return common_flags()->handle_sigbus
;
614 return kHandleSignalNo
;
617 HandleSignalMode
GetHandleSignalMode(int signum
) {
618 // Handling fatal signals on watchOS and tvOS devices is disallowed.
619 if ((SANITIZER_WATCHOS
|| SANITIZER_TVOS
) && !(SANITIZER_IOSSIM
))
620 return kHandleSignalNo
;
621 HandleSignalMode result
= GetHandleSignalModeImpl(signum
);
622 if (result
== kHandleSignalYes
&& !common_flags()->allow_user_segv_handler
)
623 return kHandleSignalExclusive
;
628 // XNU 17 -- macOS 10.13 -- iOS 11 -- tvOS 11 -- watchOS 4
629 constexpr u16
GetOSMajorKernelOffset() {
630 if (TARGET_OS_OSX
) return 4;
631 if (TARGET_OS_IOS
|| TARGET_OS_TV
) return 6;
632 if (TARGET_OS_WATCH
) return 13;
635 using VersStr
= char[64];
637 static uptr
ApproximateOSVersionViaKernelVersion(VersStr vers
) {
638 u16 kernel_major
= GetDarwinKernelVersion().major
;
639 u16 offset
= GetOSMajorKernelOffset();
640 CHECK_GE(kernel_major
, offset
);
641 u16 os_major
= kernel_major
- offset
;
643 const char *format
= "%d.0";
645 if (os_major
>= 16) { // macOS 11+
647 } else { // macOS 10.15 and below
651 return internal_snprintf(vers
, sizeof(VersStr
), format
, os_major
);
654 static void GetOSVersion(VersStr vers
) {
655 uptr len
= sizeof(VersStr
);
656 if (SANITIZER_IOSSIM
) {
657 const char *vers_env
= GetEnv("SIMULATOR_RUNTIME_VERSION");
659 Report("ERROR: Running in simulator but SIMULATOR_RUNTIME_VERSION env "
660 "var is not set.\n");
663 len
= internal_strlcpy(vers
, vers_env
, len
);
666 internal_sysctlbyname("kern.osproductversion", vers
, &len
, nullptr, 0);
668 // XNU 17 (macOS 10.13) and below do not provide the sysctl
669 // `kern.osproductversion` entry (res != 0).
670 bool no_os_version
= res
!= 0;
672 // For launchd, sanitizer initialization runs before sysctl is setup
673 // (res == 0 && len != strlen(vers), vers is not a valid version). However,
674 // the kernel version `kern.osrelease` is available.
675 bool launchd
= (res
== 0 && internal_strlen(vers
) < 3);
676 if (launchd
) CHECK_EQ(internal_getpid(), 1);
678 if (no_os_version
|| launchd
) {
679 len
= ApproximateOSVersionViaKernelVersion(vers
);
682 CHECK_LT(len
, sizeof(VersStr
));
685 void ParseVersion(const char *vers
, u16
*major
, u16
*minor
) {
686 // Format: <major>.<minor>[.<patch>]\0
687 CHECK_GE(internal_strlen(vers
), 3);
688 const char *p
= vers
;
689 *major
= internal_simple_strtoll(p
, &p
, /*base=*/10);
692 *minor
= internal_simple_strtoll(p
, &p
, /*base=*/10);
695 // Aligned versions example:
696 // macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6
697 static void MapToMacos(u16
*major
, u16
*minor
) {
701 if (TARGET_OS_IOS
|| TARGET_OS_TV
)
703 else if (TARGET_OS_WATCH
)
706 UNREACHABLE("unsupported platform");
708 if (*major
>= 16) { // macOS 11+
710 } else { // macOS 10.15 and below
716 static MacosVersion
GetMacosAlignedVersionInternal() {
721 ParseVersion(vers
, &major
, &minor
);
722 MapToMacos(&major
, &minor
);
724 return MacosVersion(major
, minor
);
727 static_assert(sizeof(MacosVersion
) == sizeof(atomic_uint32_t::Type
),
728 "MacosVersion cache size");
729 static atomic_uint32_t cached_macos_version
;
731 MacosVersion
GetMacosAlignedVersion() {
732 atomic_uint32_t::Type result
=
733 atomic_load(&cached_macos_version
, memory_order_acquire
);
735 MacosVersion version
= GetMacosAlignedVersionInternal();
736 result
= *reinterpret_cast<atomic_uint32_t::Type
*>(&version
);
737 atomic_store(&cached_macos_version
, result
, memory_order_release
);
739 return *reinterpret_cast<MacosVersion
*>(&result
);
742 DarwinKernelVersion
GetDarwinKernelVersion() {
744 uptr len
= sizeof(VersStr
);
745 int res
= internal_sysctlbyname("kern.osrelease", vers
, &len
, nullptr, 0);
747 CHECK_LT(len
, sizeof(VersStr
));
750 ParseVersion(vers
, &major
, &minor
);
752 return DarwinKernelVersion(major
, minor
);
756 struct task_basic_info info
;
757 unsigned count
= TASK_BASIC_INFO_COUNT
;
758 kern_return_t result
=
759 task_info(mach_task_self(), TASK_BASIC_INFO
, (task_info_t
)&info
, &count
);
760 if (UNLIKELY(result
!= KERN_SUCCESS
)) {
761 Report("Cannot get task info. Error: %d\n", result
);
764 return info
.resident_size
;
767 void *internal_start_thread(void *(*func
)(void *arg
), void *arg
) {
768 // Start the thread with signals blocked, otherwise it can steal user signals.
769 __sanitizer_sigset_t set
, old
;
770 internal_sigfillset(&set
);
771 internal_sigprocmask(SIG_SETMASK
, &set
, &old
);
773 pthread_create(&th
, 0, func
, arg
);
774 internal_sigprocmask(SIG_SETMASK
, &old
, 0);
778 void internal_join_thread(void *th
) { pthread_join((pthread_t
)th
, 0); }
781 static Mutex syslog_lock
;
784 void WriteOneLineToSyslog(const char *s
) {
786 syslog_lock
.CheckLocked();
787 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
788 os_log_error(OS_LOG_DEFAULT
, "%{public}s", s
);
790 asl_log(nullptr, nullptr, ASL_LEVEL_ERR
, "%s", s
);
795 // buffer to store crash report application information
796 static char crashreporter_info_buff
[__sanitizer::kErrorMessageBufferSize
] = {};
797 static Mutex crashreporter_info_mutex
;
800 // Integrate with crash reporter libraries.
801 #if HAVE_CRASHREPORTERCLIENT_H
802 CRASH_REPORTER_CLIENT_HIDDEN
803 struct crashreporter_annotations_t gCRAnnotations
804 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
))) = {
805 CRASHREPORTER_ANNOTATIONS_VERSION
,
812 #if CRASHREPORTER_ANNOTATIONS_VERSION > 4
818 // fall back to old crashreporter api
819 static const char *__crashreporter_info__
__attribute__((__used__
)) =
820 &crashreporter_info_buff
[0];
821 asm(".desc ___crashreporter_info__, 0x10");
826 static void CRAppendCrashLogMessage(const char *msg
) {
827 Lock
l(&crashreporter_info_mutex
);
828 internal_strlcat(crashreporter_info_buff
, msg
,
829 sizeof(crashreporter_info_buff
));
830 #if HAVE_CRASHREPORTERCLIENT_H
831 (void)CRSetCrashLogMessage(crashreporter_info_buff
);
835 void LogMessageOnPrintf(const char *str
) {
836 // Log all printf output to CrashLog.
837 if (common_flags()->abort_on_error
)
838 CRAppendCrashLogMessage(str
);
841 void LogFullErrorReport(const char *buffer
) {
843 // Log with os_trace. This will make it into the crash log.
844 #if SANITIZER_OS_TRACE
845 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
846 // os_trace requires the message (format parameter) to be a string literal.
847 if (internal_strncmp(SanitizerToolName
, "AddressSanitizer",
848 sizeof("AddressSanitizer") - 1) == 0)
849 os_trace("Address Sanitizer reported a failure.");
850 else if (internal_strncmp(SanitizerToolName
, "UndefinedBehaviorSanitizer",
851 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
852 os_trace("Undefined Behavior Sanitizer reported a failure.");
853 else if (internal_strncmp(SanitizerToolName
, "ThreadSanitizer",
854 sizeof("ThreadSanitizer") - 1) == 0)
855 os_trace("Thread Sanitizer reported a failure.");
857 os_trace("Sanitizer tool reported a failure.");
859 if (common_flags()->log_to_syslog
)
860 os_trace("Consult syslog for more information.");
865 // The logging on OS X may call pthread_create so we need the threading
866 // environment to be fully initialized. Also, this should never be called when
867 // holding the thread registry lock since that may result in a deadlock. If
868 // the reporting thread holds the thread registry mutex, and asl_log waits
869 // for GCD to dispatch a new thread, the process will deadlock, because the
870 // pthread_create wrapper needs to acquire the lock as well.
871 Lock
l(&syslog_lock
);
872 if (common_flags()->log_to_syslog
)
873 WriteToSyslog(buffer
);
875 // The report is added to CrashLog as part of logging all of Printf output.
879 SignalContext::WriteFlag
SignalContext::GetWriteFlag() const {
880 #if defined(__x86_64__) || defined(__i386__)
881 ucontext_t
*ucontext
= static_cast<ucontext_t
*>(context
);
882 return ucontext
->uc_mcontext
->__es
.__err
& 2 /*T_PF_WRITE*/ ? Write
: Read
;
888 bool SignalContext::IsTrueFaultingAddress() const {
889 auto si
= static_cast<const siginfo_t
*>(siginfo
);
890 // "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
891 return si
->si_signo
== SIGSEGV
&& si
->si_code
!= 0;
894 #if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
895 #define AARCH64_GET_REG(r) \
896 (uptr)ptrauth_strip( \
897 (void *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0)
899 #define AARCH64_GET_REG(r) (uptr)ucontext->uc_mcontext->__ss.__##r
902 static void GetPcSpBp(void *context
, uptr
*pc
, uptr
*sp
, uptr
*bp
) {
903 ucontext_t
*ucontext
= (ucontext_t
*)context
;
904 # if defined(__aarch64__)
905 *pc
= AARCH64_GET_REG(pc
);
906 # if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
907 *bp
= AARCH64_GET_REG(fp
);
909 *bp
= AARCH64_GET_REG(lr
);
911 *sp
= AARCH64_GET_REG(sp
);
912 # elif defined(__x86_64__)
913 *pc
= ucontext
->uc_mcontext
->__ss
.__rip
;
914 *bp
= ucontext
->uc_mcontext
->__ss
.__rbp
;
915 *sp
= ucontext
->uc_mcontext
->__ss
.__rsp
;
916 # elif defined(__arm__)
917 *pc
= ucontext
->uc_mcontext
->__ss
.__pc
;
918 *bp
= ucontext
->uc_mcontext
->__ss
.__r
[7];
919 *sp
= ucontext
->uc_mcontext
->__ss
.__sp
;
920 # elif defined(__i386__)
921 *pc
= ucontext
->uc_mcontext
->__ss
.__eip
;
922 *bp
= ucontext
->uc_mcontext
->__ss
.__ebp
;
923 *sp
= ucontext
->uc_mcontext
->__ss
.__esp
;
925 # error "Unknown architecture"
929 void SignalContext::InitPcSpBp() {
930 addr
= (uptr
)ptrauth_strip((void *)addr
, 0);
931 GetPcSpBp(context
, &pc
, &sp
, &bp
);
934 // ASan/TSan use mmap in a way that creates “deallocation gaps” which triggers
935 // EXC_GUARD exceptions on macOS 10.15+ (XNU 19.0+).
936 static void DisableMmapExcGuardExceptions() {
937 using task_exc_guard_behavior_t
= uint32_t;
938 using task_set_exc_guard_behavior_t
=
939 kern_return_t(task_t task
, task_exc_guard_behavior_t behavior
);
940 auto *set_behavior
= (task_set_exc_guard_behavior_t
*)dlsym(
941 RTLD_DEFAULT
, "task_set_exc_guard_behavior");
942 if (set_behavior
== nullptr) return;
943 const task_exc_guard_behavior_t task_exc_guard_none
= 0;
944 set_behavior(mach_task_self(), task_exc_guard_none
);
947 void InitializePlatformEarly() {
948 // Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
950 #if defined(__x86_64__)
951 GetDarwinKernelVersion() >= DarwinKernelVersion(17, 5);
955 if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0))
956 DisableMmapExcGuardExceptions();
960 static const char kDyldInsertLibraries
[] = "DYLD_INSERT_LIBRARIES";
961 LowLevelAllocator allocator_for_env
;
963 // Change the value of the env var |name|, leaking the original value.
964 // If |name_value| is NULL, the variable is deleted from the environment,
965 // otherwise the corresponding "NAME=value" string is replaced with
967 void LeakyResetEnv(const char *name
, const char *name_value
) {
968 char **env
= GetEnviron();
969 uptr name_len
= internal_strlen(name
);
971 uptr len
= internal_strlen(*env
);
972 if (len
> name_len
) {
973 const char *p
= *env
;
974 if (!internal_memcmp(p
, name
, name_len
) && p
[name_len
] == '=') {
977 // Replace the old value with the new one.
978 *env
= const_cast<char*>(name_value
);
980 // Shift the subsequent pointers back.
992 SANITIZER_WEAK_CXX_DEFAULT_IMPL
993 bool ReexecDisabled() {
997 static bool DyldNeedsEnvVariable() {
998 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
999 // DYLD_INSERT_LIBRARIES is not set.
1000 return GetMacosAlignedVersion() < MacosVersion(10, 11);
1003 void MaybeReexec() {
1004 // FIXME: This should really live in some "InitializePlatform" method.
1005 MonotonicNanoTime();
1007 if (ReexecDisabled()) return;
1009 // Make sure the dynamic runtime library is preloaded so that the
1010 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
1013 RAW_CHECK(dladdr((void*)((uptr
)&__sanitizer_report_error_summary
), &info
));
1014 char *dyld_insert_libraries
=
1015 const_cast<char*>(GetEnv(kDyldInsertLibraries
));
1016 uptr old_env_len
= dyld_insert_libraries
?
1017 internal_strlen(dyld_insert_libraries
) : 0;
1018 uptr fname_len
= internal_strlen(info
.dli_fname
);
1019 const char *dylib_name
= StripModuleName(info
.dli_fname
);
1020 uptr dylib_name_len
= internal_strlen(dylib_name
);
1022 bool lib_is_in_env
= dyld_insert_libraries
&&
1023 internal_strstr(dyld_insert_libraries
, dylib_name
);
1024 if (DyldNeedsEnvVariable() && !lib_is_in_env
) {
1025 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
1027 InternalMmapVector
<char> program_name(1024);
1028 uint32_t buf_size
= program_name
.size();
1029 _NSGetExecutablePath(program_name
.data(), &buf_size
);
1030 char *new_env
= const_cast<char*>(info
.dli_fname
);
1031 if (dyld_insert_libraries
) {
1032 // Append the runtime dylib name to the existing value of
1033 // DYLD_INSERT_LIBRARIES.
1034 new_env
= (char*)allocator_for_env
.Allocate(old_env_len
+ fname_len
+ 2);
1035 internal_strncpy(new_env
, dyld_insert_libraries
, old_env_len
);
1036 new_env
[old_env_len
] = ':';
1037 // Copy fname_len and add a trailing zero.
1038 internal_strncpy(new_env
+ old_env_len
+ 1, info
.dli_fname
,
1040 // Ok to use setenv() since the wrappers don't depend on the value of
1042 setenv(kDyldInsertLibraries
, new_env
, /*overwrite*/1);
1044 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
1045 setenv(kDyldInsertLibraries
, info
.dli_fname
, /*overwrite*/0);
1047 VReport(1, "exec()-ing the program with\n");
1048 VReport(1, "%s=%s\n", kDyldInsertLibraries
, new_env
);
1049 VReport(1, "to enable wrappers.\n");
1050 execv(program_name
.data(), *_NSGetArgv());
1052 // We get here only if execv() failed.
1053 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
1054 "which is required for the sanitizer to work. We tried to set the "
1055 "environment variable and re-execute itself, but execv() failed, "
1056 "possibly because of sandbox restrictions. Make sure to launch the "
1057 "executable with:\n%s=%s\n", kDyldInsertLibraries
, new_env
);
1058 RAW_CHECK("execv failed" && 0);
1061 // Verify that interceptors really work. We'll use dlsym to locate
1062 // "puts", if interceptors are working, it should really point to
1063 // "wrap_puts" within our own dylib.
1065 void *dlopen_addr
= dlsym(RTLD_DEFAULT
, "puts");
1066 RAW_CHECK(dladdr(dlopen_addr
, &info_puts
));
1067 if (internal_strcmp(info
.dli_fname
, info_puts
.dli_fname
) != 0) {
1069 "ERROR: Interceptors are not working. This may be because %s is "
1070 "loaded too late (e.g. via dlopen). Please launch the executable "
1072 SanitizerToolName
, kDyldInsertLibraries
, info
.dli_fname
);
1073 RAW_CHECK("interceptors not installed" && 0);
1079 if (!common_flags()->strip_env
)
1082 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
1083 // the dylib from the environment variable, because interceptors are installed
1084 // and we don't want our children to inherit the variable.
1086 uptr env_name_len
= internal_strlen(kDyldInsertLibraries
);
1087 // Allocate memory to hold the previous env var name, its value, the '='
1088 // sign and the '\0' char.
1089 char *new_env
= (char*)allocator_for_env
.Allocate(
1090 old_env_len
+ 2 + env_name_len
);
1092 internal_memset(new_env
, '\0', old_env_len
+ 2 + env_name_len
);
1093 internal_strncpy(new_env
, kDyldInsertLibraries
, env_name_len
);
1094 new_env
[env_name_len
] = '=';
1095 char *new_env_pos
= new_env
+ env_name_len
+ 1;
1097 // Iterate over colon-separated pieces of |dyld_insert_libraries|.
1098 char *piece_start
= dyld_insert_libraries
;
1099 char *piece_end
= NULL
;
1100 char *old_env_end
= dyld_insert_libraries
+ old_env_len
;
1102 if (piece_start
[0] == ':') piece_start
++;
1103 piece_end
= internal_strchr(piece_start
, ':');
1104 if (!piece_end
) piece_end
= dyld_insert_libraries
+ old_env_len
;
1105 if ((uptr
)(piece_start
- dyld_insert_libraries
) > old_env_len
) break;
1106 uptr piece_len
= piece_end
- piece_start
;
1108 char *filename_start
=
1109 (char *)internal_memrchr(piece_start
, '/', piece_len
);
1110 uptr filename_len
= piece_len
;
1111 if (filename_start
) {
1112 filename_start
+= 1;
1113 filename_len
= piece_len
- (filename_start
- piece_start
);
1115 filename_start
= piece_start
;
1118 // If the current piece isn't the runtime library name,
1119 // append it to new_env.
1120 if ((dylib_name_len
!= filename_len
) ||
1121 (internal_memcmp(filename_start
, dylib_name
, dylib_name_len
) != 0)) {
1122 if (new_env_pos
!= new_env
+ env_name_len
+ 1) {
1123 new_env_pos
[0] = ':';
1126 internal_strncpy(new_env_pos
, piece_start
, piece_len
);
1127 new_env_pos
+= piece_len
;
1129 // Move on to the next piece.
1130 piece_start
= piece_end
;
1131 } while (piece_start
< old_env_end
);
1133 // Can't use setenv() here, because it requires the allocator to be
1135 // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
1136 // a separate function called after InitializeAllocator().
1137 if (new_env_pos
== new_env
+ env_name_len
+ 1) new_env
= NULL
;
1138 LeakyResetEnv(kDyldInsertLibraries
, new_env
);
1140 #endif // SANITIZER_GO
1143 return *_NSGetArgv();
1146 #if SANITIZER_IOS && !SANITIZER_IOSSIM
1147 // The task_vm_info struct is normally provided by the macOS SDK, but we need
1148 // fields only available in 10.12+. Declare the struct manually to be able to
1149 // build against older SDKs.
1150 struct __sanitizer_task_vm_info
{
1151 mach_vm_size_t virtual_size
;
1152 integer_t region_count
;
1153 integer_t page_size
;
1154 mach_vm_size_t resident_size
;
1155 mach_vm_size_t resident_size_peak
;
1156 mach_vm_size_t device
;
1157 mach_vm_size_t device_peak
;
1158 mach_vm_size_t internal
;
1159 mach_vm_size_t internal_peak
;
1160 mach_vm_size_t external
;
1161 mach_vm_size_t external_peak
;
1162 mach_vm_size_t reusable
;
1163 mach_vm_size_t reusable_peak
;
1164 mach_vm_size_t purgeable_volatile_pmap
;
1165 mach_vm_size_t purgeable_volatile_resident
;
1166 mach_vm_size_t purgeable_volatile_virtual
;
1167 mach_vm_size_t compressed
;
1168 mach_vm_size_t compressed_peak
;
1169 mach_vm_size_t compressed_lifetime
;
1170 mach_vm_size_t phys_footprint
;
1171 mach_vm_address_t min_address
;
1172 mach_vm_address_t max_address
;
1174 #define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \
1175 (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t)))
1177 static uptr
GetTaskInfoMaxAddress() {
1178 __sanitizer_task_vm_info vm_info
= {} /* zero initialize */;
1179 mach_msg_type_number_t count
= __SANITIZER_TASK_VM_INFO_COUNT
;
1180 int err
= task_info(mach_task_self(), TASK_VM_INFO
, (int *)&vm_info
, &count
);
1181 return err
? 0 : vm_info
.max_address
;
1184 uptr
GetMaxUserVirtualAddress() {
1185 static uptr max_vm
= GetTaskInfoMaxAddress();
1187 const uptr ret_value
= max_vm
- 1;
1188 CHECK_LE(ret_value
, SANITIZER_MMAP_RANGE_SIZE
);
1192 // xnu cannot provide vm address limit
1193 # if SANITIZER_WORDSIZE == 32
1194 constexpr uptr fallback_max_vm
= 0xffe00000 - 1;
1196 constexpr uptr fallback_max_vm
= 0x200000000 - 1;
1198 static_assert(fallback_max_vm
<= SANITIZER_MMAP_RANGE_SIZE
,
1199 "Max virtual address must be less than mmap range size.");
1200 return fallback_max_vm
;
1203 #else // !SANITIZER_IOS
1205 uptr
GetMaxUserVirtualAddress() {
1206 # if SANITIZER_WORDSIZE == 64
1207 constexpr uptr max_vm
= (1ULL << 47) - 1; // 0x00007fffffffffffUL;
1208 # else // SANITIZER_WORDSIZE == 32
1209 static_assert(SANITIZER_WORDSIZE
== 32, "Wrong wordsize");
1210 constexpr uptr max_vm
= (1ULL << 32) - 1; // 0xffffffff;
1212 static_assert(max_vm
<= SANITIZER_MMAP_RANGE_SIZE
,
1213 "Max virtual address must be less than mmap range size.");
1218 uptr
GetMaxVirtualAddress() {
1219 return GetMaxUserVirtualAddress();
1222 uptr
MapDynamicShadow(uptr shadow_size_bytes
, uptr shadow_scale
,
1223 uptr min_shadow_base_alignment
, uptr
&high_mem_end
) {
1224 const uptr granularity
= GetMmapGranularity();
1225 const uptr alignment
=
1226 Max
<uptr
>(granularity
<< shadow_scale
, 1ULL << min_shadow_base_alignment
);
1227 const uptr left_padding
=
1228 Max
<uptr
>(granularity
, 1ULL << min_shadow_base_alignment
);
1230 uptr space_size
= shadow_size_bytes
+ left_padding
;
1232 uptr largest_gap_found
= 0;
1233 uptr max_occupied_addr
= 0;
1234 VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size
);
1236 FindAvailableMemoryRange(space_size
, alignment
, granularity
,
1237 &largest_gap_found
, &max_occupied_addr
);
1238 // If the shadow doesn't fit, restrict the address space to make it fit.
1239 if (shadow_start
== 0) {
1242 "Shadow doesn't fit, largest_gap_found = %p, max_occupied_addr = %p\n",
1243 (void *)largest_gap_found
, (void *)max_occupied_addr
);
1244 uptr new_max_vm
= RoundDownTo(largest_gap_found
<< shadow_scale
, alignment
);
1245 if (new_max_vm
< max_occupied_addr
) {
1246 Report("Unable to find a memory range for dynamic shadow.\n");
1248 "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
1249 "new_max_vm = %p\n",
1250 (void *)space_size
, (void *)largest_gap_found
,
1251 (void *)max_occupied_addr
, (void *)new_max_vm
);
1252 CHECK(0 && "cannot place shadow");
1254 RestrictMemoryToMaxAddress(new_max_vm
);
1255 high_mem_end
= new_max_vm
- 1;
1256 space_size
= (high_mem_end
>> shadow_scale
) + left_padding
;
1257 VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size
);
1258 shadow_start
= FindAvailableMemoryRange(space_size
, alignment
, granularity
,
1260 if (shadow_start
== 0) {
1261 Report("Unable to find a memory range after restricting VM.\n");
1262 CHECK(0 && "cannot place shadow after restricting vm");
1265 CHECK_NE((uptr
)0, shadow_start
);
1266 CHECK(IsAligned(shadow_start
, alignment
));
1267 return shadow_start
;
1270 uptr
MapDynamicShadowAndAliases(uptr shadow_size
, uptr alias_size
,
1271 uptr num_aliases
, uptr ring_buffer_size
) {
1272 CHECK(false && "HWASan aliasing is unimplemented on Mac");
1276 uptr
FindAvailableMemoryRange(uptr size
, uptr alignment
, uptr left_padding
,
1277 uptr
*largest_gap_found
,
1278 uptr
*max_occupied_addr
) {
1279 typedef vm_region_submap_short_info_data_64_t RegionInfo
;
1280 enum { kRegionInfoSize
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
};
1281 // Start searching for available memory region past PAGEZERO, which is
1282 // 4KB on 32-bit and 4GB on 64-bit.
1283 mach_vm_address_t start_address
=
1284 (SANITIZER_WORDSIZE
== 32) ? 0x000000001000 : 0x000100000000;
1286 mach_vm_address_t address
= start_address
;
1287 mach_vm_address_t free_begin
= start_address
;
1288 kern_return_t kr
= KERN_SUCCESS
;
1289 if (largest_gap_found
) *largest_gap_found
= 0;
1290 if (max_occupied_addr
) *max_occupied_addr
= 0;
1291 while (kr
== KERN_SUCCESS
) {
1292 mach_vm_size_t vmsize
= 0;
1293 natural_t depth
= 0;
1295 mach_msg_type_number_t count
= kRegionInfoSize
;
1296 kr
= mach_vm_region_recurse(mach_task_self(), &address
, &vmsize
, &depth
,
1297 (vm_region_info_t
)&vminfo
, &count
);
1298 if (kr
== KERN_INVALID_ADDRESS
) {
1299 // No more regions beyond "address", consider the gap at the end of VM.
1300 address
= GetMaxVirtualAddress() + 1;
1303 if (max_occupied_addr
) *max_occupied_addr
= address
+ vmsize
;
1305 if (free_begin
!= address
) {
1306 // We found a free region [free_begin..address-1].
1307 uptr gap_start
= RoundUpTo((uptr
)free_begin
+ left_padding
, alignment
);
1308 uptr gap_end
= RoundDownTo((uptr
)address
, alignment
);
1309 uptr gap_size
= gap_end
> gap_start
? gap_end
- gap_start
: 0;
1310 if (size
< gap_size
) {
1314 if (largest_gap_found
&& *largest_gap_found
< gap_size
) {
1315 *largest_gap_found
= gap_size
;
1318 // Move to the next region.
1320 free_begin
= address
;
1323 // We looked at all free regions and could not find one large enough.
1327 // FIXME implement on this platform.
1328 void GetMemoryProfile(fill_profile_f cb
, uptr
*stats
) {}
1330 void SignalContext::DumpAllRegisters(void *context
) {
1331 Report("Register values:\n");
1333 ucontext_t
*ucontext
= (ucontext_t
*)context
;
1334 # define DUMPREG64(r) \
1335 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1336 # define DUMPREGA64(r) \
1337 Printf(" %s = 0x%016lx ", #r, AARCH64_GET_REG(r));
1338 # define DUMPREG32(r) \
1339 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1340 # define DUMPREG_(r) Printf(" "); DUMPREG(r);
1341 # define DUMPREG__(r) Printf(" "); DUMPREG(r);
1342 # define DUMPREG___(r) Printf(" "); DUMPREG(r);
1344 # if defined(__x86_64__)
1345 # define DUMPREG(r) DUMPREG64(r)
1346 DUMPREG(rax
); DUMPREG(rbx
); DUMPREG(rcx
); DUMPREG(rdx
); Printf("\n");
1347 DUMPREG(rdi
); DUMPREG(rsi
); DUMPREG(rbp
); DUMPREG(rsp
); Printf("\n");
1348 DUMPREG_(r8
); DUMPREG_(r9
); DUMPREG(r10
); DUMPREG(r11
); Printf("\n");
1349 DUMPREG(r12
); DUMPREG(r13
); DUMPREG(r14
); DUMPREG(r15
); Printf("\n");
1350 # elif defined(__i386__)
1351 # define DUMPREG(r) DUMPREG32(r)
1352 DUMPREG(eax
); DUMPREG(ebx
); DUMPREG(ecx
); DUMPREG(edx
); Printf("\n");
1353 DUMPREG(edi
); DUMPREG(esi
); DUMPREG(ebp
); DUMPREG(esp
); Printf("\n");
1354 # elif defined(__aarch64__)
1355 # define DUMPREG(r) DUMPREG64(r)
1356 DUMPREG_(x
[0]); DUMPREG_(x
[1]); DUMPREG_(x
[2]); DUMPREG_(x
[3]); Printf("\n");
1357 DUMPREG_(x
[4]); DUMPREG_(x
[5]); DUMPREG_(x
[6]); DUMPREG_(x
[7]); Printf("\n");
1358 DUMPREG_(x
[8]); DUMPREG_(x
[9]); DUMPREG(x
[10]); DUMPREG(x
[11]); Printf("\n");
1359 DUMPREG(x
[12]); DUMPREG(x
[13]); DUMPREG(x
[14]); DUMPREG(x
[15]); Printf("\n");
1360 DUMPREG(x
[16]); DUMPREG(x
[17]); DUMPREG(x
[18]); DUMPREG(x
[19]); Printf("\n");
1361 DUMPREG(x
[20]); DUMPREG(x
[21]); DUMPREG(x
[22]); DUMPREG(x
[23]); Printf("\n");
1362 DUMPREG(x
[24]); DUMPREG(x
[25]); DUMPREG(x
[26]); DUMPREG(x
[27]); Printf("\n");
1363 DUMPREG(x
[28]); DUMPREGA64(fp
); DUMPREGA64(lr
); DUMPREGA64(sp
); Printf("\n");
1364 # elif defined(__arm__)
1365 # define DUMPREG(r) DUMPREG32(r)
1366 DUMPREG_(r
[0]); DUMPREG_(r
[1]); DUMPREG_(r
[2]); DUMPREG_(r
[3]); Printf("\n");
1367 DUMPREG_(r
[4]); DUMPREG_(r
[5]); DUMPREG_(r
[6]); DUMPREG_(r
[7]); Printf("\n");
1368 DUMPREG_(r
[8]); DUMPREG_(r
[9]); DUMPREG(r
[10]); DUMPREG(r
[11]); Printf("\n");
1369 DUMPREG(r
[12]); DUMPREG___(sp
); DUMPREG___(lr
); DUMPREG___(pc
); Printf("\n");
1371 # error "Unknown architecture"
1382 static inline bool CompareBaseAddress(const LoadedModule
&a
,
1383 const LoadedModule
&b
) {
1384 return a
.base_address() < b
.base_address();
1387 void FormatUUID(char *out
, uptr size
, const u8
*uuid
) {
1388 internal_snprintf(out
, size
,
1389 "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
1390 "%02X%02X%02X%02X%02X%02X>",
1391 uuid
[0], uuid
[1], uuid
[2], uuid
[3], uuid
[4], uuid
[5],
1392 uuid
[6], uuid
[7], uuid
[8], uuid
[9], uuid
[10], uuid
[11],
1393 uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
1396 void DumpProcessMap() {
1397 Printf("Process module map:\n");
1398 MemoryMappingLayout
memory_mapping(false);
1399 InternalMmapVector
<LoadedModule
> modules
;
1400 modules
.reserve(128);
1401 memory_mapping
.DumpListOfModules(&modules
);
1402 Sort(modules
.data(), modules
.size(), CompareBaseAddress
);
1403 for (uptr i
= 0; i
< modules
.size(); ++i
) {
1405 FormatUUID(uuid_str
, sizeof(uuid_str
), modules
[i
].uuid());
1406 Printf("0x%zx-0x%zx %s (%s) %s\n", modules
[i
].base_address(),
1407 modules
[i
].max_address(), modules
[i
].full_name(),
1408 ModuleArchToString(modules
[i
].arch()), uuid_str
);
1410 Printf("End of module map.\n");
1413 void CheckNoDeepBind(const char *filename
, int flag
) {
1417 bool GetRandom(void *buffer
, uptr length
, bool blocking
) {
1418 if (!buffer
|| !length
|| length
> 256)
1420 // arc4random never fails.
1421 REAL(arc4random_buf
)(buffer
, length
);
1425 u32
GetNumberOfCPUs() {
1426 return (u32
)sysconf(_SC_NPROCESSORS_ONLN
);
1429 void InitializePlatformCommonFlags(CommonFlags
*cf
) {}
1431 } // namespace __sanitizer
1433 #endif // SANITIZER_MAC