2012-06-04 22:27:50 +08:00
|
|
|
//===-- sanitizer_mac.cc --------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2014-02-03 23:32:19 +08:00
|
|
|
// This file is shared between various sanitizers' runtime libraries and
|
|
|
|
// implements OSX-specific functions.
|
2012-06-04 22:27:50 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-03-19 22:33:38 +08:00
|
|
|
#include "sanitizer_platform.h"
|
|
|
|
#if SANITIZER_MAC
|
2015-11-21 02:42:01 +08:00
|
|
|
#include "sanitizer_mac.h"
|
2013-03-19 22:33:38 +08:00
|
|
|
|
2013-02-06 22:41:15 +08:00
|
|
|
// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
|
|
|
|
// the clients will most certainly use 64-bit ones as well.
|
|
|
|
#ifndef _DARWIN_USE_64_BIT_INODE
|
|
|
|
#define _DARWIN_USE_64_BIT_INODE 1
|
|
|
|
#endif
|
|
|
|
#include <stdio.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2012-06-07 15:13:46 +08:00
|
|
|
#include "sanitizer_common.h"
|
2014-01-31 21:10:07 +08:00
|
|
|
#include "sanitizer_flags.h"
|
2012-06-05 22:25:27 +08:00
|
|
|
#include "sanitizer_internal_defs.h"
|
2012-06-04 22:27:50 +08:00
|
|
|
#include "sanitizer_libc.h"
|
2013-09-10 22:36:16 +08:00
|
|
|
#include "sanitizer_placement_new.h"
|
2015-05-13 05:30:16 +08:00
|
|
|
#include "sanitizer_platform_limits_posix.h"
|
2012-06-07 14:15:12 +08:00
|
|
|
#include "sanitizer_procmaps.h"
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2015-06-24 05:39:49 +08:00
|
|
|
#if !SANITIZER_IOS
|
2012-06-14 22:07:21 +08:00
|
|
|
#include <crt_externs.h> // for _NSGetEnviron
|
2015-06-24 05:39:49 +08:00
|
|
|
#else
|
|
|
|
extern char **environ;
|
|
|
|
#endif
|
|
|
|
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
#if defined(__has_include) && __has_include(<os/trace.h>)
|
|
|
|
#define SANITIZER_OS_TRACE 1
|
|
|
|
#include <os/trace.h>
|
|
|
|
#else
|
|
|
|
#define SANITIZER_OS_TRACE 0
|
|
|
|
#endif
|
|
|
|
|
2015-12-03 18:39:43 +08:00
|
|
|
#if !SANITIZER_IOS
|
|
|
|
#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
|
|
|
|
#else
|
|
|
|
extern "C" {
|
|
|
|
extern char ***_NSGetArgv(void);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
#include <asl.h>
|
2015-12-03 18:39:43 +08:00
|
|
|
#include <dlfcn.h> // for dladdr()
|
2015-05-13 04:47:21 +08:00
|
|
|
#include <errno.h>
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <fcntl.h>
|
2015-05-13 04:47:21 +08:00
|
|
|
#include <libkern/OSAtomic.h>
|
2015-02-27 11:12:19 +08:00
|
|
|
#include <mach-o/dyld.h>
|
2015-05-13 04:47:21 +08:00
|
|
|
#include <mach/mach.h>
|
2015-10-28 04:12:53 +08:00
|
|
|
#include <mach/vm_statistics.h>
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <pthread.h>
|
2012-06-18 16:44:30 +08:00
|
|
|
#include <sched.h>
|
2014-01-31 21:10:07 +08:00
|
|
|
#include <signal.h>
|
2015-02-27 11:12:19 +08:00
|
|
|
#include <stdlib.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
#include <sys/mman.h>
|
2012-06-07 15:13:46 +08:00
|
|
|
#include <sys/resource.h>
|
2012-06-05 15:05:10 +08:00
|
|
|
#include <sys/stat.h>
|
2014-02-03 23:32:19 +08:00
|
|
|
#include <sys/sysctl.h>
|
2012-06-05 15:05:10 +08:00
|
|
|
#include <sys/types.h>
|
2016-01-27 06:53:52 +08:00
|
|
|
#include <sys/wait.h>
|
2012-06-05 16:32:53 +08:00
|
|
|
#include <unistd.h>
|
2015-11-20 22:28:33 +08:00
|
|
|
#include <util.h>
|
2012-06-04 22:27:50 +08:00
|
|
|
|
2016-10-06 04:33:59 +08:00
|
|
|
// From <crt_externs.h>, but we don't have that file on iOS.
|
2016-02-02 10:01:17 +08:00
|
|
|
extern "C" {
|
|
|
|
extern char ***_NSGetArgv(void);
|
|
|
|
extern char ***_NSGetEnviron(void);
|
|
|
|
}
|
|
|
|
|
2016-10-06 04:33:59 +08:00
|
|
|
// From <mach/mach_vm.h>, but we don't have that file on iOS.
|
|
|
|
extern "C" {
|
2016-10-06 04:45:34 +08:00
|
|
|
extern kern_return_t mach_vm_region_recurse(
|
2016-10-06 04:33:59 +08:00
|
|
|
vm_map_t target_task,
|
|
|
|
mach_vm_address_t *address,
|
|
|
|
mach_vm_size_t *size,
|
|
|
|
natural_t *nesting_depth,
|
|
|
|
vm_region_recurse_info_t info,
|
|
|
|
mach_msg_type_number_t *infoCnt);
|
|
|
|
}
|
|
|
|
|
2012-06-04 22:27:50 +08:00
|
|
|
namespace __sanitizer {
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
#include "sanitizer_syscall_generic.inc"
|
|
|
|
|
2017-02-03 14:58:14 +08:00
|
|
|
// Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
|
2016-03-24 19:50:21 +08:00
|
|
|
extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes,
|
2017-02-03 14:58:14 +08:00
|
|
|
off_t off) SANITIZER_WEAK_ATTRIBUTE;
|
|
|
|
extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
|
2016-03-24 19:50:21 +08:00
|
|
|
|
2012-06-07 15:13:46 +08:00
|
|
|
// ---------------------- sanitizer_libc.h
|
2013-05-08 23:07:12 +08:00
|
|
|
uptr internal_mmap(void *addr, size_t length, int prot, int flags,
|
|
|
|
int fd, u64 offset) {
|
2015-10-28 04:12:53 +08:00
|
|
|
if (fd == -1) fd = VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL);
|
2017-03-24 11:57:27 +08:00
|
|
|
if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset);
|
2017-02-03 14:58:14 +08:00
|
|
|
return (uptr)mmap(addr, length, prot, flags, fd, offset);
|
2012-06-04 22:27:50 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 23:07:12 +08:00
|
|
|
uptr internal_munmap(void *addr, uptr length) {
|
2017-03-24 11:57:27 +08:00
|
|
|
if (&__munmap) return __munmap(addr, length);
|
2017-02-03 14:58:14 +08:00
|
|
|
return munmap(addr, length);
|
2012-06-05 17:49:25 +08:00
|
|
|
}
|
|
|
|
|
2015-04-10 23:02:19 +08:00
|
|
|
int internal_mprotect(void *addr, uptr length, int prot) {
|
|
|
|
return mprotect(addr, length, prot);
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_close(fd_t fd) {
|
2012-06-05 16:32:53 +08:00
|
|
|
return close(fd);
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_open(const char *filename, int flags) {
|
2013-02-01 23:58:46 +08:00
|
|
|
return open(filename, flags);
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_open(const char *filename, int flags, u32 mode) {
|
2013-02-01 23:58:46 +08:00
|
|
|
return open(filename, flags, mode);
|
|
|
|
}
|
|
|
|
|
2012-06-05 16:32:53 +08:00
|
|
|
uptr internal_read(fd_t fd, void *buf, uptr count) {
|
|
|
|
return read(fd, buf, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
uptr internal_write(fd_t fd, const void *buf, uptr count) {
|
|
|
|
return write(fd, buf, count);
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_stat(const char *path, void *buf) {
|
2013-02-04 18:31:39 +08:00
|
|
|
return stat(path, (struct stat *)buf);
|
2013-02-04 18:16:50 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_lstat(const char *path, void *buf) {
|
2013-02-04 18:31:39 +08:00
|
|
|
return lstat(path, (struct stat *)buf);
|
2013-02-04 18:16:50 +08:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_fstat(fd_t fd, void *buf) {
|
2013-02-04 18:31:39 +08:00
|
|
|
return fstat(fd, (struct stat *)buf);
|
2013-02-04 18:16:50 +08:00
|
|
|
}
|
|
|
|
|
2012-06-06 15:30:33 +08:00
|
|
|
uptr internal_filesize(fd_t fd) {
|
2012-08-02 18:09:31 +08:00
|
|
|
struct stat st;
|
2013-02-04 18:16:50 +08:00
|
|
|
if (internal_fstat(fd, &st))
|
2012-06-06 15:30:33 +08:00
|
|
|
return -1;
|
|
|
|
return (uptr)st.st_size;
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_dup2(int oldfd, int newfd) {
|
2012-06-06 15:30:33 +08:00
|
|
|
return dup2(oldfd, newfd);
|
|
|
|
}
|
|
|
|
|
2012-09-05 22:48:24 +08:00
|
|
|
uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
|
|
|
|
return readlink(path, buf, bufsize);
|
|
|
|
}
|
|
|
|
|
2014-12-29 10:18:59 +08:00
|
|
|
uptr internal_unlink(const char *path) {
|
|
|
|
return unlink(path);
|
|
|
|
}
|
|
|
|
|
2013-05-08 22:43:49 +08:00
|
|
|
uptr internal_sched_yield() {
|
2012-06-18 16:44:30 +08:00
|
|
|
return sched_yield();
|
|
|
|
}
|
|
|
|
|
2013-02-20 21:54:32 +08:00
|
|
|
void internal__exit(int exitcode) {
|
|
|
|
_exit(exitcode);
|
|
|
|
}
|
|
|
|
|
2016-05-12 22:08:56 +08:00
|
|
|
unsigned int internal_sleep(unsigned int seconds) {
|
2016-05-13 00:58:19 +08:00
|
|
|
return sleep(seconds);
|
2016-05-12 22:08:56 +08:00
|
|
|
}
|
|
|
|
|
2013-05-18 00:56:53 +08:00
|
|
|
uptr internal_getpid() {
|
|
|
|
return getpid();
|
|
|
|
}
|
|
|
|
|
2014-01-31 21:10:07 +08:00
|
|
|
int internal_sigaction(int signum, const void *act, void *oldact) {
|
|
|
|
return sigaction(signum,
|
|
|
|
(struct sigaction *)act, (struct sigaction *)oldact);
|
|
|
|
}
|
|
|
|
|
2015-05-13 04:56:44 +08:00
|
|
|
void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); }
|
|
|
|
|
|
|
|
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
|
|
|
|
__sanitizer_sigset_t *oldset) {
|
|
|
|
return sigprocmask(how, set, oldset);
|
|
|
|
}
|
|
|
|
|
2017-02-03 14:58:14 +08:00
|
|
|
// Doesn't call pthread_atfork() handlers (but not available on 10.6).
|
|
|
|
extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE;
|
2015-11-20 22:28:33 +08:00
|
|
|
|
2014-05-14 00:17:54 +08:00
|
|
|
int internal_fork() {
|
2017-03-24 11:57:27 +08:00
|
|
|
if (&__fork)
|
2017-02-03 14:58:14 +08:00
|
|
|
return __fork();
|
|
|
|
return fork();
|
2015-11-20 22:28:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int internal_forkpty(int *amaster) {
|
|
|
|
int master, slave;
|
|
|
|
if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1;
|
2017-02-03 14:58:14 +08:00
|
|
|
int pid = internal_fork();
|
2015-11-20 22:28:33 +08:00
|
|
|
if (pid == -1) {
|
|
|
|
close(master);
|
|
|
|
close(slave);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (pid == 0) {
|
|
|
|
close(master);
|
2016-05-12 20:53:43 +08:00
|
|
|
if (login_tty(slave) != 0) {
|
|
|
|
// We already forked, there's not much we can do. Let's quit.
|
|
|
|
Report("login_tty failed (errno %d)\n", errno);
|
|
|
|
internal__exit(1);
|
|
|
|
}
|
2015-11-20 22:28:33 +08:00
|
|
|
} else {
|
|
|
|
*amaster = master;
|
|
|
|
close(slave);
|
|
|
|
}
|
|
|
|
return pid;
|
2014-05-14 00:17:54 +08:00
|
|
|
}
|
|
|
|
|
2014-05-27 20:37:52 +08:00
|
|
|
uptr internal_rename(const char *oldpath, const char *newpath) {
|
|
|
|
return rename(oldpath, newpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
uptr internal_ftruncate(fd_t fd, uptr size) {
|
|
|
|
return ftruncate(fd, size);
|
|
|
|
}
|
|
|
|
|
2016-01-27 06:53:52 +08:00
|
|
|
uptr internal_execve(const char *filename, char *const argv[],
|
|
|
|
char *const envp[]) {
|
|
|
|
return execve(filename, argv, envp);
|
|
|
|
}
|
|
|
|
|
|
|
|
uptr internal_waitpid(int pid, int *status, int options) {
|
|
|
|
return waitpid(pid, status, options);
|
|
|
|
}
|
|
|
|
|
2012-06-07 15:13:46 +08:00
|
|
|
// ----------------- sanitizer_common.h
|
2012-11-09 22:45:30 +08:00
|
|
|
bool FileExists(const char *filename) {
|
|
|
|
struct stat st;
|
|
|
|
if (stat(filename, &st))
|
|
|
|
return false;
|
|
|
|
// Sanity check: filename is a regular file.
|
|
|
|
return S_ISREG(st.st_mode);
|
|
|
|
}
|
|
|
|
|
2017-04-18 02:17:38 +08:00
|
|
|
tid_t GetTid() {
|
|
|
|
tid_t tid;
|
2016-04-21 22:38:41 +08:00
|
|
|
pthread_threadid_np(nullptr, &tid);
|
|
|
|
return tid;
|
2012-10-02 20:58:14 +08:00
|
|
|
}
|
|
|
|
|
2012-06-07 15:32:00 +08:00
|
|
|
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
|
2012-06-07 15:13:46 +08:00
|
|
|
uptr *stack_bottom) {
|
|
|
|
CHECK(stack_top);
|
|
|
|
CHECK(stack_bottom);
|
|
|
|
uptr stacksize = pthread_get_stacksize_np(pthread_self());
|
2014-02-04 00:42:29 +08:00
|
|
|
// pthread_get_stacksize_np() returns an incorrect stack size for the main
|
|
|
|
// thread on Mavericks. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/261
|
2014-11-06 02:55:38 +08:00
|
|
|
if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
|
2014-02-04 00:42:29 +08:00
|
|
|
stacksize == (1 << 19)) {
|
|
|
|
struct rlimit rl;
|
|
|
|
CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
|
|
|
|
// Most often rl.rlim_cur will be the desired 8M.
|
|
|
|
if (rl.rlim_cur < kMaxThreadStackSize) {
|
|
|
|
stacksize = rl.rlim_cur;
|
|
|
|
} else {
|
|
|
|
stacksize = kMaxThreadStackSize;
|
|
|
|
}
|
|
|
|
}
|
2012-06-07 15:13:46 +08:00
|
|
|
void *stackaddr = pthread_get_stackaddr_np(pthread_self());
|
|
|
|
*stack_top = (uptr)stackaddr;
|
2012-06-07 15:32:00 +08:00
|
|
|
*stack_bottom = *stack_top - stacksize;
|
2012-06-07 15:13:46 +08:00
|
|
|
}
|
|
|
|
|
2015-06-24 05:39:49 +08:00
|
|
|
char **GetEnviron() {
|
|
|
|
#if !SANITIZER_IOS
|
2012-06-14 22:07:21 +08:00
|
|
|
char ***env_ptr = _NSGetEnviron();
|
2013-11-13 21:34:53 +08:00
|
|
|
if (!env_ptr) {
|
|
|
|
Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
|
|
|
|
"called after libSystem_initializer().\n");
|
|
|
|
CHECK(env_ptr);
|
|
|
|
}
|
2012-06-14 22:07:21 +08:00
|
|
|
char **environ = *env_ptr;
|
2015-06-24 05:39:49 +08:00
|
|
|
#endif
|
2012-06-14 22:07:21 +08:00
|
|
|
CHECK(environ);
|
2015-06-24 05:39:49 +08:00
|
|
|
return environ;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *GetEnv(const char *name) {
|
|
|
|
char **env = GetEnviron();
|
2012-06-14 22:07:21 +08:00
|
|
|
uptr name_len = internal_strlen(name);
|
2015-06-24 05:39:49 +08:00
|
|
|
while (*env != 0) {
|
|
|
|
uptr len = internal_strlen(*env);
|
2012-06-14 22:07:21 +08:00
|
|
|
if (len > name_len) {
|
2015-06-24 05:39:49 +08:00
|
|
|
const char *p = *env;
|
2012-06-14 22:07:21 +08:00
|
|
|
if (!internal_memcmp(p, name, name_len) &&
|
|
|
|
p[name_len] == '=') { // Match.
|
2015-06-24 05:39:49 +08:00
|
|
|
return *env + name_len + 1; // String starting after =.
|
2012-06-14 22:07:21 +08:00
|
|
|
}
|
|
|
|
}
|
2015-06-24 05:39:49 +08:00
|
|
|
env++;
|
2012-06-14 22:07:21 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-06-07 15:13:46 +08:00
|
|
|
|
2015-02-27 11:12:19 +08:00
|
|
|
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
|
|
|
CHECK_LE(kMaxPathLength, buf_len);
|
|
|
|
|
|
|
|
// On OS X the executable path is saved to the stack by dyld. Reading it
|
|
|
|
// from there is much faster than calling dladdr, especially for large
|
|
|
|
// binaries with symbols.
|
|
|
|
InternalScopedString exe_path(kMaxPathLength);
|
|
|
|
uint32_t size = exe_path.size();
|
|
|
|
if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
|
|
|
|
realpath(exe_path.data(), buf) != 0) {
|
|
|
|
return internal_strlen(buf);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-29 05:01:42 +08:00
|
|
|
uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
|
|
|
|
return ReadBinaryName(buf, buf_len);
|
|
|
|
}
|
|
|
|
|
2012-09-17 17:12:39 +08:00
|
|
|
void ReExec() {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
|
|
|
|
2013-05-21 01:05:29 +08:00
|
|
|
uptr GetPageSize() {
|
|
|
|
return sysconf(_SC_PAGESIZE);
|
|
|
|
}
|
|
|
|
|
2013-03-14 21:30:56 +08:00
|
|
|
BlockingMutex::BlockingMutex() {
|
|
|
|
internal_memset(this, 0, sizeof(*this));
|
|
|
|
}
|
|
|
|
|
2013-01-14 15:51:39 +08:00
|
|
|
void BlockingMutex::Lock() {
|
|
|
|
CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
|
2013-02-26 20:59:06 +08:00
|
|
|
CHECK_EQ(OS_SPINLOCK_INIT, 0);
|
2017-02-10 03:29:11 +08:00
|
|
|
CHECK_EQ(owner_, 0);
|
2013-01-14 15:51:39 +08:00
|
|
|
OSSpinLockLock((OSSpinLock*)&opaque_storage_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockingMutex::Unlock() {
|
|
|
|
OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
|
|
|
|
}
|
|
|
|
|
2013-03-11 23:45:20 +08:00
|
|
|
void BlockingMutex::CheckLocked() {
|
2017-02-10 03:29:11 +08:00
|
|
|
CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0);
|
2013-03-11 23:45:20 +08:00
|
|
|
}
|
|
|
|
|
2013-06-06 21:00:32 +08:00
|
|
|
u64 NanoTime() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-13 16:19:53 +08:00
|
|
|
uptr GetTlsSize() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitTlsSize() {
|
|
|
|
}
|
|
|
|
|
Implement tls scanning for darwin LSan
Summary:
This required for any users who call exit() after creating
thread-specific data, as tls destructors are only called when
pthread_exit() or pthread_cancel() are used. This should also
match tls behavior on linux.
Getting the base address of the tls section is straightforward,
as it's stored as a section offset in %gs. The size is a bit trickier
to work out, as there doesn't appear to be any official documentation
or source code referring to it. The size used in this patch was determined
by taking the difference between the base address and the address of the
subsequent memory region returned by vm_region_recurse_64, which was
1024 * sizeof(uptr) on all threads except the main thread, where it was
larger. Since the section must be the same size on all of the threads,
1024 * sizeof(uptr) seemed to be a reasonable size to use, barring
a more programtic way to get the size.
1024 seems like a reasonable number, given that PTHREAD_KEYS_MAX
is 512 on darwin, so pthread keys will fit inside the region while
leaving space for other tls data. A larger size would overflow the
memory region returned by vm_region_recurse_64, and a smaller size
wouldn't leave room for all the pthread keys. In addition, the
stress test added here passes, which means that we are scanning at
least the full set of possible pthread keys, and probably
the full tls section.
Reviewers: alekseyshl, kubamracek
Subscribers: krytarowski, llvm-commits
Differential Revision: https://reviews.llvm.org/D33215
llvm-svn: 303887
2017-05-26 01:41:13 +08:00
|
|
|
uptr TlsBaseAddr() {
|
|
|
|
uptr segbase = 0;
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
asm("movq %%gs:0,%0" : "=r"(segbase));
|
|
|
|
#elif defined(__i386__)
|
|
|
|
asm("movl %%gs:0,%0" : "=r"(segbase));
|
|
|
|
#endif
|
|
|
|
return segbase;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The size of the tls on darwin does not appear to be well documented,
|
|
|
|
// however the vm memory map suggests that it is 1024 uptrs in size,
|
|
|
|
// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
|
|
|
|
uptr TlsSize() {
|
|
|
|
#if defined(__x86_64__) || defined(__i386__)
|
|
|
|
return 1024 * sizeof(uptr);
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-05-07 22:41:43 +08:00
|
|
|
void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
|
|
|
|
uptr *tls_addr, uptr *tls_size) {
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
2013-05-07 22:41:43 +08:00
|
|
|
uptr stack_top, stack_bottom;
|
|
|
|
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
|
|
|
|
*stk_addr = stack_bottom;
|
|
|
|
*stk_size = stack_top - stack_bottom;
|
Implement tls scanning for darwin LSan
Summary:
This required for any users who call exit() after creating
thread-specific data, as tls destructors are only called when
pthread_exit() or pthread_cancel() are used. This should also
match tls behavior on linux.
Getting the base address of the tls section is straightforward,
as it's stored as a section offset in %gs. The size is a bit trickier
to work out, as there doesn't appear to be any official documentation
or source code referring to it. The size used in this patch was determined
by taking the difference between the base address and the address of the
subsequent memory region returned by vm_region_recurse_64, which was
1024 * sizeof(uptr) on all threads except the main thread, where it was
larger. Since the section must be the same size on all of the threads,
1024 * sizeof(uptr) seemed to be a reasonable size to use, barring
a more programtic way to get the size.
1024 seems like a reasonable number, given that PTHREAD_KEYS_MAX
is 512 on darwin, so pthread keys will fit inside the region while
leaving space for other tls data. A larger size would overflow the
memory region returned by vm_region_recurse_64, and a smaller size
wouldn't leave room for all the pthread keys. In addition, the
stress test added here passes, which means that we are scanning at
least the full set of possible pthread keys, and probably
the full tls section.
Reviewers: alekseyshl, kubamracek
Subscribers: krytarowski, llvm-commits
Differential Revision: https://reviews.llvm.org/D33215
llvm-svn: 303887
2017-05-26 01:41:13 +08:00
|
|
|
*tls_addr = TlsBaseAddr();
|
|
|
|
*tls_size = TlsSize();
|
2013-06-06 21:20:40 +08:00
|
|
|
#else
|
|
|
|
*stk_addr = 0;
|
|
|
|
*stk_size = 0;
|
|
|
|
*tls_addr = 0;
|
|
|
|
*tls_size = 0;
|
|
|
|
#endif
|
2013-05-07 22:41:43 +08:00
|
|
|
}
|
|
|
|
|
2016-02-23 02:52:51 +08:00
|
|
|
void ListOfModules::init() {
|
|
|
|
clear();
|
2013-09-10 22:36:16 +08:00
|
|
|
MemoryMappingLayout memory_mapping(false);
|
2016-02-23 02:52:51 +08:00
|
|
|
memory_mapping.DumpListOfModules(&modules_);
|
2013-09-10 22:36:16 +08:00
|
|
|
}
|
|
|
|
|
2017-06-15 08:19:13 +08:00
|
|
|
static HandleSignalMode GetHandleSignalModeImpl(int signum) {
|
2017-05-19 07:13:22 +08:00
|
|
|
switch (signum) {
|
|
|
|
case SIGABRT:
|
|
|
|
return common_flags()->handle_abort;
|
|
|
|
case SIGILL:
|
|
|
|
return common_flags()->handle_sigill;
|
|
|
|
case SIGFPE:
|
|
|
|
return common_flags()->handle_sigfpe;
|
|
|
|
case SIGSEGV:
|
|
|
|
return common_flags()->handle_segv;
|
|
|
|
case SIGBUS:
|
|
|
|
return common_flags()->handle_sigbus;
|
|
|
|
}
|
2017-05-26 07:42:33 +08:00
|
|
|
return kHandleSignalNo;
|
2014-01-31 21:10:07 +08:00
|
|
|
}
|
|
|
|
|
2017-06-15 08:19:13 +08:00
|
|
|
HandleSignalMode GetHandleSignalMode(int signum) {
|
|
|
|
// Handling fatal signals on watchOS and tvOS devices is disallowed.
|
|
|
|
if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM))
|
|
|
|
return kHandleSignalNo;
|
|
|
|
HandleSignalMode result = GetHandleSignalModeImpl(signum);
|
|
|
|
if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
|
|
|
|
return kHandleSignalExclusive;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-02-03 23:32:19 +08:00
|
|
|
MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
|
|
|
|
|
|
|
|
MacosVersion GetMacosVersionInternal() {
|
|
|
|
int mib[2] = { CTL_KERN, KERN_OSRELEASE };
|
|
|
|
char version[100];
|
|
|
|
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_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;
|
2014-11-06 02:53:22 +08:00
|
|
|
case '4': return MACOS_VERSION_YOSEMITE;
|
2014-12-16 12:46:15 +08:00
|
|
|
default:
|
|
|
|
if (IsDigit(version[1]))
|
|
|
|
return MACOS_VERSION_UNKNOWN_NEWER;
|
|
|
|
else
|
|
|
|
return MACOS_VERSION_UNKNOWN;
|
2014-02-03 23:32:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
default: return MACOS_VERSION_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MacosVersion GetMacosVersion() {
|
|
|
|
atomic_uint32_t *cache =
|
|
|
|
reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
|
|
|
|
MacosVersion result =
|
|
|
|
static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
|
|
|
|
if (result == MACOS_VERSION_UNINITIALIZED) {
|
|
|
|
result = GetMacosVersionInternal();
|
|
|
|
atomic_store(cache, result, memory_order_release);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-12-28 05:13:11 +08:00
|
|
|
bool PlatformHasDifferentMemcpyAndMemmove() {
|
|
|
|
// On OS X 10.7 memcpy() and memmove() are both resolved
|
|
|
|
// into memmove$VARIANT$sse42.
|
|
|
|
// See also https://github.com/google/sanitizers/issues/34.
|
|
|
|
// TODO(glider): need to check dynamically that memcpy() and memmove() are
|
|
|
|
// actually the same function.
|
|
|
|
return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
|
|
|
|
}
|
|
|
|
|
2014-12-09 09:22:59 +08:00
|
|
|
uptr GetRSS() {
|
2015-05-13 04:47:21 +08:00
|
|
|
struct task_basic_info info;
|
|
|
|
unsigned count = TASK_BASIC_INFO_COUNT;
|
|
|
|
kern_return_t result =
|
|
|
|
task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
|
|
|
|
if (UNLIKELY(result != KERN_SUCCESS)) {
|
|
|
|
Report("Cannot get task info. Error: %d\n", result);
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
return info.resident_size;
|
2014-12-09 09:22:59 +08:00
|
|
|
}
|
|
|
|
|
2015-11-11 10:44:19 +08:00
|
|
|
void *internal_start_thread(void(*func)(void *arg), void *arg) {
|
|
|
|
// Start the thread with signals blocked, otherwise it can steal user signals.
|
|
|
|
__sanitizer_sigset_t set, old;
|
|
|
|
internal_sigfillset(&set);
|
|
|
|
internal_sigprocmask(SIG_SETMASK, &set, &old);
|
|
|
|
pthread_t th;
|
|
|
|
pthread_create(&th, 0, (void*(*)(void *arg))func, arg);
|
|
|
|
internal_sigprocmask(SIG_SETMASK, &old, 0);
|
|
|
|
return th;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
|
2014-12-17 03:13:01 +08:00
|
|
|
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
static BlockingMutex syslog_lock(LINKER_INITIALIZED);
|
2016-04-27 20:56:16 +08:00
|
|
|
#endif
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
|
|
|
|
void WriteOneLineToSyslog(const char *s) {
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
syslog_lock.CheckLocked();
|
|
|
|
asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
|
2016-04-27 20:56:16 +08:00
|
|
|
#endif
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
}
|
|
|
|
|
2016-01-07 07:15:01 +08:00
|
|
|
void LogMessageOnPrintf(const char *str) {
|
|
|
|
// Log all printf output to CrashLog.
|
|
|
|
if (common_flags()->abort_on_error)
|
|
|
|
CRAppendCrashLogMessage(str);
|
|
|
|
}
|
|
|
|
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
void LogFullErrorReport(const char *buffer) {
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
// Log with os_trace. This will make it into the crash log.
|
|
|
|
#if SANITIZER_OS_TRACE
|
|
|
|
if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) {
|
|
|
|
// os_trace requires the message (format parameter) to be a string literal.
|
|
|
|
if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
|
|
|
|
sizeof("AddressSanitizer") - 1) == 0)
|
|
|
|
os_trace("Address Sanitizer reported a failure.");
|
|
|
|
else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
|
|
|
|
sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
|
|
|
|
os_trace("Undefined Behavior Sanitizer reported a failure.");
|
|
|
|
else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
|
|
|
|
sizeof("ThreadSanitizer") - 1) == 0)
|
|
|
|
os_trace("Thread Sanitizer reported a failure.");
|
|
|
|
else
|
|
|
|
os_trace("Sanitizer tool reported a failure.");
|
|
|
|
|
|
|
|
if (common_flags()->log_to_syslog)
|
|
|
|
os_trace("Consult syslog for more information.");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Log to syslog.
|
|
|
|
// The logging on OS X may call pthread_create so we need the threading
|
|
|
|
// environment to be fully initialized. Also, this should never be called when
|
|
|
|
// holding the thread registry lock since that may result in a deadlock. If
|
|
|
|
// the reporting thread holds the thread registry mutex, and asl_log waits
|
|
|
|
// for GCD to dispatch a new thread, the process will deadlock, because the
|
|
|
|
// pthread_create wrapper needs to acquire the lock as well.
|
|
|
|
BlockingMutexLock l(&syslog_lock);
|
|
|
|
if (common_flags()->log_to_syslog)
|
|
|
|
WriteToSyslog(buffer);
|
2015-11-21 02:42:07 +08:00
|
|
|
|
2016-01-07 07:15:01 +08:00
|
|
|
// The report is added to CrashLog as part of logging all of Printf output.
|
2016-04-27 22:28:42 +08:00
|
|
|
#endif
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
}
|
|
|
|
|
2016-02-09 06:50:25 +08:00
|
|
|
SignalContext::WriteFlag SignalContext::GetWriteFlag(void *context) {
|
2016-04-28 02:02:21 +08:00
|
|
|
#if defined(__x86_64__) || defined(__i386__)
|
|
|
|
ucontext_t *ucontext = static_cast<ucontext_t*>(context);
|
|
|
|
return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ;
|
|
|
|
#else
|
|
|
|
return UNKNOWN;
|
|
|
|
#endif
|
2016-02-04 10:02:09 +08:00
|
|
|
}
|
|
|
|
|
2015-03-03 01:36:02 +08:00
|
|
|
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
2015-06-24 05:39:49 +08:00
|
|
|
# if defined(__aarch64__)
|
|
|
|
*pc = ucontext->uc_mcontext->__ss.__pc;
|
|
|
|
# if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
|
|
|
|
*bp = ucontext->uc_mcontext->__ss.__fp;
|
|
|
|
# else
|
|
|
|
*bp = ucontext->uc_mcontext->__ss.__lr;
|
|
|
|
# endif
|
|
|
|
*sp = ucontext->uc_mcontext->__ss.__sp;
|
|
|
|
# elif defined(__x86_64__)
|
2015-03-03 01:36:02 +08:00
|
|
|
*pc = ucontext->uc_mcontext->__ss.__rip;
|
|
|
|
*bp = ucontext->uc_mcontext->__ss.__rbp;
|
|
|
|
*sp = ucontext->uc_mcontext->__ss.__rsp;
|
2015-06-24 05:39:49 +08:00
|
|
|
# elif defined(__arm__)
|
|
|
|
*pc = ucontext->uc_mcontext->__ss.__pc;
|
|
|
|
*bp = ucontext->uc_mcontext->__ss.__r[7];
|
|
|
|
*sp = ucontext->uc_mcontext->__ss.__sp;
|
|
|
|
# elif defined(__i386__)
|
2015-03-03 01:36:02 +08:00
|
|
|
*pc = ucontext->uc_mcontext->__ss.__eip;
|
|
|
|
*bp = ucontext->uc_mcontext->__ss.__ebp;
|
|
|
|
*sp = ucontext->uc_mcontext->__ss.__esp;
|
2015-06-24 05:39:49 +08:00
|
|
|
# else
|
|
|
|
# error "Unknown architecture"
|
|
|
|
# endif
|
2015-03-03 01:36:02 +08:00
|
|
|
}
|
|
|
|
|
2016-10-29 04:14:18 +08:00
|
|
|
#if !SANITIZER_GO
|
2015-12-03 18:39:43 +08:00
|
|
|
static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
|
|
|
|
LowLevelAllocator allocator_for_env;
|
|
|
|
|
|
|
|
// Change the value of the env var |name|, leaking the original value.
|
|
|
|
// If |name_value| is NULL, the variable is deleted from the environment,
|
|
|
|
// otherwise the corresponding "NAME=value" string is replaced with
|
|
|
|
// |name_value|.
|
|
|
|
void LeakyResetEnv(const char *name, const char *name_value) {
|
|
|
|
char **env = GetEnviron();
|
|
|
|
uptr name_len = internal_strlen(name);
|
|
|
|
while (*env != 0) {
|
|
|
|
uptr len = internal_strlen(*env);
|
|
|
|
if (len > name_len) {
|
|
|
|
const char *p = *env;
|
|
|
|
if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
|
|
|
|
// Match.
|
|
|
|
if (name_value) {
|
|
|
|
// Replace the old value with the new one.
|
|
|
|
*env = const_cast<char*>(name_value);
|
|
|
|
} else {
|
|
|
|
// Shift the subsequent pointers back.
|
|
|
|
char **del = env;
|
|
|
|
do {
|
|
|
|
del[0] = del[1];
|
|
|
|
} while (*del++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
env++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[sanitizer] On OS X, verify that interceptors work and abort if not, take 2
On OS X 10.11+, we have "automatic interceptors", so we don't need to use DYLD_INSERT_LIBRARIES when launching instrumented programs. However, non-instrumented programs that load TSan late (e.g. via dlopen) are currently broken, as TSan will still try to initialize, but the program will crash/hang at random places (because the interceptors don't work). This patch adds an explicit check that interceptors are working, and if not, it aborts and prints out an error message suggesting to explicitly use DYLD_INSERT_LIBRARIES.
TSan unit tests run with a statically linked runtime, where interceptors don't work. To avoid aborting the process in this case, the patch replaces `DisableReexec()` with a weak `ReexecDisabled()` function which is defined to return true in unit tests.
Differential Revision: http://reviews.llvm.org/D18212
llvm-svn: 263695
2016-03-17 16:37:25 +08:00
|
|
|
SANITIZER_WEAK_CXX_DEFAULT_IMPL
|
|
|
|
bool ReexecDisabled() {
|
|
|
|
return false;
|
2015-12-03 18:39:43 +08:00
|
|
|
}
|
|
|
|
|
2016-04-20 18:22:37 +08:00
|
|
|
extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber;
|
2015-12-03 18:39:43 +08:00
|
|
|
static const double kMinDyldVersionWithAutoInterposition = 360.0;
|
|
|
|
|
|
|
|
bool DyldNeedsEnvVariable() {
|
2016-04-20 18:22:37 +08:00
|
|
|
// Although sanitizer support was added to LLVM on OS X 10.7+, GCC users
|
|
|
|
// still may want use them on older systems. On older Darwin platforms, dyld
|
|
|
|
// doesn't export dyldVersionNumber symbol and we simply return true.
|
|
|
|
if (!&dyldVersionNumber) return true;
|
2015-12-03 18:39:43 +08:00
|
|
|
// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
|
|
|
|
// DYLD_INSERT_LIBRARIES is not set. However, checking OS version via
|
|
|
|
// GetMacosVersion() doesn't work for the simulator. Let's instead check
|
|
|
|
// `dyldVersionNumber`, which is exported by dyld, against a known version
|
|
|
|
// number from the first OS release where this appeared.
|
|
|
|
return dyldVersionNumber < kMinDyldVersionWithAutoInterposition;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MaybeReexec() {
|
[sanitizer] On OS X, verify that interceptors work and abort if not, take 2
On OS X 10.11+, we have "automatic interceptors", so we don't need to use DYLD_INSERT_LIBRARIES when launching instrumented programs. However, non-instrumented programs that load TSan late (e.g. via dlopen) are currently broken, as TSan will still try to initialize, but the program will crash/hang at random places (because the interceptors don't work). This patch adds an explicit check that interceptors are working, and if not, it aborts and prints out an error message suggesting to explicitly use DYLD_INSERT_LIBRARIES.
TSan unit tests run with a statically linked runtime, where interceptors don't work. To avoid aborting the process in this case, the patch replaces `DisableReexec()` with a weak `ReexecDisabled()` function which is defined to return true in unit tests.
Differential Revision: http://reviews.llvm.org/D18212
llvm-svn: 263695
2016-03-17 16:37:25 +08:00
|
|
|
if (ReexecDisabled()) return;
|
2015-12-03 18:39:43 +08:00
|
|
|
|
|
|
|
// Make sure the dynamic runtime library is preloaded so that the
|
|
|
|
// wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
|
|
|
|
// ourselves.
|
|
|
|
Dl_info info;
|
2016-04-28 17:26:30 +08:00
|
|
|
RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
|
2015-12-03 18:39:43 +08:00
|
|
|
char *dyld_insert_libraries =
|
|
|
|
const_cast<char*>(GetEnv(kDyldInsertLibraries));
|
|
|
|
uptr old_env_len = dyld_insert_libraries ?
|
|
|
|
internal_strlen(dyld_insert_libraries) : 0;
|
|
|
|
uptr fname_len = internal_strlen(info.dli_fname);
|
|
|
|
const char *dylib_name = StripModuleName(info.dli_fname);
|
|
|
|
uptr dylib_name_len = internal_strlen(dylib_name);
|
|
|
|
|
|
|
|
bool lib_is_in_env = dyld_insert_libraries &&
|
|
|
|
internal_strstr(dyld_insert_libraries, dylib_name);
|
|
|
|
if (DyldNeedsEnvVariable() && !lib_is_in_env) {
|
|
|
|
// DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
|
|
|
|
// library.
|
2015-12-04 01:05:43 +08:00
|
|
|
InternalScopedString program_name(1024);
|
|
|
|
uint32_t buf_size = program_name.size();
|
|
|
|
_NSGetExecutablePath(program_name.data(), &buf_size);
|
2015-12-03 18:39:43 +08:00
|
|
|
char *new_env = const_cast<char*>(info.dli_fname);
|
|
|
|
if (dyld_insert_libraries) {
|
|
|
|
// Append the runtime dylib name to the existing value of
|
|
|
|
// DYLD_INSERT_LIBRARIES.
|
|
|
|
new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
|
|
|
|
internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
|
|
|
|
new_env[old_env_len] = ':';
|
|
|
|
// Copy fname_len and add a trailing zero.
|
|
|
|
internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
|
|
|
|
fname_len + 1);
|
|
|
|
// Ok to use setenv() since the wrappers don't depend on the value of
|
|
|
|
// asan_inited.
|
|
|
|
setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
|
|
|
|
} else {
|
|
|
|
// Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
|
|
|
|
setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
|
|
|
|
}
|
|
|
|
VReport(1, "exec()-ing the program with\n");
|
|
|
|
VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
|
|
|
|
VReport(1, "to enable wrappers.\n");
|
2015-12-04 01:05:43 +08:00
|
|
|
execv(program_name.data(), *_NSGetArgv());
|
2015-12-03 18:39:43 +08:00
|
|
|
|
|
|
|
// We get here only if execv() failed.
|
|
|
|
Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
|
|
|
|
"which is required for the sanitizer to work. We tried to set the "
|
|
|
|
"environment variable and re-execute itself, but execv() failed, "
|
|
|
|
"possibly because of sandbox restrictions. Make sure to launch the "
|
|
|
|
"executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
|
2016-04-28 17:26:30 +08:00
|
|
|
RAW_CHECK("execv failed" && 0);
|
2015-12-03 18:39:43 +08:00
|
|
|
}
|
|
|
|
|
[sanitizer] On OS X, verify that interceptors work and abort if not, take 2
On OS X 10.11+, we have "automatic interceptors", so we don't need to use DYLD_INSERT_LIBRARIES when launching instrumented programs. However, non-instrumented programs that load TSan late (e.g. via dlopen) are currently broken, as TSan will still try to initialize, but the program will crash/hang at random places (because the interceptors don't work). This patch adds an explicit check that interceptors are working, and if not, it aborts and prints out an error message suggesting to explicitly use DYLD_INSERT_LIBRARIES.
TSan unit tests run with a statically linked runtime, where interceptors don't work. To avoid aborting the process in this case, the patch replaces `DisableReexec()` with a weak `ReexecDisabled()` function which is defined to return true in unit tests.
Differential Revision: http://reviews.llvm.org/D18212
llvm-svn: 263695
2016-03-17 16:37:25 +08:00
|
|
|
// Verify that interceptors really work. We'll use dlsym to locate
|
|
|
|
// "pthread_create", if interceptors are working, it should really point to
|
|
|
|
// "wrap_pthread_create" within our own dylib.
|
|
|
|
Dl_info info_pthread_create;
|
|
|
|
void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create");
|
2016-04-28 17:26:30 +08:00
|
|
|
RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create));
|
[sanitizer] On OS X, verify that interceptors work and abort if not, take 2
On OS X 10.11+, we have "automatic interceptors", so we don't need to use DYLD_INSERT_LIBRARIES when launching instrumented programs. However, non-instrumented programs that load TSan late (e.g. via dlopen) are currently broken, as TSan will still try to initialize, but the program will crash/hang at random places (because the interceptors don't work). This patch adds an explicit check that interceptors are working, and if not, it aborts and prints out an error message suggesting to explicitly use DYLD_INSERT_LIBRARIES.
TSan unit tests run with a statically linked runtime, where interceptors don't work. To avoid aborting the process in this case, the patch replaces `DisableReexec()` with a weak `ReexecDisabled()` function which is defined to return true in unit tests.
Differential Revision: http://reviews.llvm.org/D18212
llvm-svn: 263695
2016-03-17 16:37:25 +08:00
|
|
|
if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) {
|
|
|
|
Report(
|
|
|
|
"ERROR: Interceptors are not working. This may be because %s is "
|
|
|
|
"loaded too late (e.g. via dlopen). Please launch the executable "
|
|
|
|
"with:\n%s=%s\n",
|
|
|
|
SanitizerToolName, kDyldInsertLibraries, info.dli_fname);
|
2016-04-28 17:26:30 +08:00
|
|
|
RAW_CHECK("interceptors not installed" && 0);
|
[sanitizer] On OS X, verify that interceptors work and abort if not, take 2
On OS X 10.11+, we have "automatic interceptors", so we don't need to use DYLD_INSERT_LIBRARIES when launching instrumented programs. However, non-instrumented programs that load TSan late (e.g. via dlopen) are currently broken, as TSan will still try to initialize, but the program will crash/hang at random places (because the interceptors don't work). This patch adds an explicit check that interceptors are working, and if not, it aborts and prints out an error message suggesting to explicitly use DYLD_INSERT_LIBRARIES.
TSan unit tests run with a statically linked runtime, where interceptors don't work. To avoid aborting the process in this case, the patch replaces `DisableReexec()` with a weak `ReexecDisabled()` function which is defined to return true in unit tests.
Differential Revision: http://reviews.llvm.org/D18212
llvm-svn: 263695
2016-03-17 16:37:25 +08:00
|
|
|
}
|
|
|
|
|
2015-12-03 18:39:43 +08:00
|
|
|
if (!lib_is_in_env)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
|
|
|
|
// the dylib from the environment variable, because interceptors are installed
|
|
|
|
// and we don't want our children to inherit the variable.
|
|
|
|
|
|
|
|
uptr env_name_len = internal_strlen(kDyldInsertLibraries);
|
|
|
|
// Allocate memory to hold the previous env var name, its value, the '='
|
|
|
|
// sign and the '\0' char.
|
|
|
|
char *new_env = (char*)allocator_for_env.Allocate(
|
|
|
|
old_env_len + 2 + env_name_len);
|
2016-04-28 17:26:30 +08:00
|
|
|
RAW_CHECK(new_env);
|
2015-12-03 18:39:43 +08:00
|
|
|
internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
|
|
|
|
internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
|
|
|
|
new_env[env_name_len] = '=';
|
|
|
|
char *new_env_pos = new_env + env_name_len + 1;
|
|
|
|
|
|
|
|
// Iterate over colon-separated pieces of |dyld_insert_libraries|.
|
|
|
|
char *piece_start = dyld_insert_libraries;
|
|
|
|
char *piece_end = NULL;
|
|
|
|
char *old_env_end = dyld_insert_libraries + old_env_len;
|
|
|
|
do {
|
|
|
|
if (piece_start[0] == ':') piece_start++;
|
|
|
|
piece_end = internal_strchr(piece_start, ':');
|
|
|
|
if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
|
|
|
|
if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
|
|
|
|
uptr piece_len = piece_end - piece_start;
|
|
|
|
|
|
|
|
char *filename_start =
|
|
|
|
(char *)internal_memrchr(piece_start, '/', piece_len);
|
|
|
|
uptr filename_len = piece_len;
|
|
|
|
if (filename_start) {
|
|
|
|
filename_start += 1;
|
|
|
|
filename_len = piece_len - (filename_start - piece_start);
|
|
|
|
} else {
|
|
|
|
filename_start = piece_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the current piece isn't the runtime library name,
|
|
|
|
// append it to new_env.
|
|
|
|
if ((dylib_name_len != filename_len) ||
|
|
|
|
(internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
|
|
|
|
if (new_env_pos != new_env + env_name_len + 1) {
|
|
|
|
new_env_pos[0] = ':';
|
|
|
|
new_env_pos++;
|
|
|
|
}
|
|
|
|
internal_strncpy(new_env_pos, piece_start, piece_len);
|
|
|
|
new_env_pos += piece_len;
|
|
|
|
}
|
|
|
|
// Move on to the next piece.
|
|
|
|
piece_start = piece_end;
|
|
|
|
} while (piece_start < old_env_end);
|
|
|
|
|
|
|
|
// Can't use setenv() here, because it requires the allocator to be
|
|
|
|
// initialized.
|
|
|
|
// FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
|
|
|
|
// a separate function called after InitializeAllocator().
|
|
|
|
if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
|
|
|
|
LeakyResetEnv(kDyldInsertLibraries, new_env);
|
|
|
|
}
|
2016-04-27 20:56:16 +08:00
|
|
|
#endif // SANITIZER_GO
|
2015-12-03 18:39:43 +08:00
|
|
|
|
2016-01-18 15:55:12 +08:00
|
|
|
char **GetArgv() {
|
|
|
|
return *_NSGetArgv();
|
|
|
|
}
|
|
|
|
|
2016-10-06 04:33:59 +08:00
|
|
|
uptr FindAvailableMemoryRange(uptr shadow_size,
|
|
|
|
uptr alignment,
|
|
|
|
uptr left_padding) {
|
|
|
|
typedef vm_region_submap_short_info_data_64_t RegionInfo;
|
|
|
|
enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
|
|
|
|
// Start searching for available memory region past PAGEZERO, which is
|
|
|
|
// 4KB on 32-bit and 4GB on 64-bit.
|
|
|
|
mach_vm_address_t start_address =
|
|
|
|
(SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
|
|
|
|
|
|
|
|
mach_vm_address_t address = start_address;
|
|
|
|
mach_vm_address_t free_begin = start_address;
|
|
|
|
kern_return_t kr = KERN_SUCCESS;
|
|
|
|
while (kr == KERN_SUCCESS) {
|
|
|
|
mach_vm_size_t vmsize = 0;
|
|
|
|
natural_t depth = 0;
|
|
|
|
RegionInfo vminfo;
|
|
|
|
mach_msg_type_number_t count = kRegionInfoSize;
|
|
|
|
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
|
|
|
|
(vm_region_info_t)&vminfo, &count);
|
|
|
|
if (free_begin != address) {
|
|
|
|
// We found a free region [free_begin..address-1].
|
|
|
|
uptr shadow_address = RoundUpTo((uptr)free_begin + left_padding,
|
|
|
|
alignment);
|
|
|
|
if (shadow_address + shadow_size < (uptr)address) {
|
|
|
|
return shadow_address;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Move to the next region.
|
|
|
|
address += vmsize;
|
|
|
|
free_begin = address;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We looked at all free regions and could not find one large enough.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-22 06:18:36 +08:00
|
|
|
// FIXME implement on this platform.
|
|
|
|
void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
|
|
|
|
|
2016-11-26 08:50:08 +08:00
|
|
|
void SignalContext::DumpAllRegisters(void *context) {
|
|
|
|
Report("Register values:\n");
|
|
|
|
|
|
|
|
ucontext_t *ucontext = (ucontext_t*)context;
|
|
|
|
# define DUMPREG64(r) \
|
|
|
|
Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
|
|
|
|
# define DUMPREG32(r) \
|
|
|
|
Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
|
|
|
|
# define DUMPREG_(r) Printf(" "); DUMPREG(r);
|
|
|
|
# define DUMPREG__(r) Printf(" "); DUMPREG(r);
|
|
|
|
# define DUMPREG___(r) Printf(" "); DUMPREG(r);
|
|
|
|
|
|
|
|
# if defined(__x86_64__)
|
|
|
|
# define DUMPREG(r) DUMPREG64(r)
|
|
|
|
DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
|
|
|
|
DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
|
|
|
|
DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
|
|
|
|
DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
|
|
|
|
# elif defined(__i386__)
|
|
|
|
# define DUMPREG(r) DUMPREG32(r)
|
|
|
|
DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
|
|
|
|
DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
|
|
|
|
# elif defined(__aarch64__)
|
|
|
|
# define DUMPREG(r) DUMPREG64(r)
|
|
|
|
DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
|
|
|
|
DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
|
|
|
|
DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
|
|
|
|
DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
|
|
|
|
DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
|
|
|
|
DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
|
|
|
|
DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
|
|
|
|
DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); Printf("\n");
|
|
|
|
# elif defined(__arm__)
|
|
|
|
# define DUMPREG(r) DUMPREG32(r)
|
|
|
|
DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
|
|
|
|
DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
|
|
|
|
DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
|
|
|
|
DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
|
|
|
|
# else
|
|
|
|
# error "Unknown architecture"
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# undef DUMPREG64
|
|
|
|
# undef DUMPREG32
|
|
|
|
# undef DUMPREG_
|
|
|
|
# undef DUMPREG__
|
|
|
|
# undef DUMPREG___
|
|
|
|
# undef DUMPREG
|
|
|
|
}
|
|
|
|
|
2017-01-07 04:57:47 +08:00
|
|
|
static inline bool CompareBaseAddress(const LoadedModule &a,
|
|
|
|
const LoadedModule &b) {
|
|
|
|
return a.base_address() < b.base_address();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FormatUUID(char *out, uptr size, const u8 *uuid) {
|
|
|
|
internal_snprintf(out, size,
|
|
|
|
"<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
|
|
|
|
"%02X%02X%02X%02X%02X%02X>",
|
|
|
|
uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
|
|
|
|
uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
|
|
|
|
uuid[12], uuid[13], uuid[14], uuid[15]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintModuleMap() {
|
|
|
|
Printf("Process module map:\n");
|
|
|
|
MemoryMappingLayout memory_mapping(false);
|
|
|
|
InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128);
|
|
|
|
memory_mapping.DumpListOfModules(&modules);
|
|
|
|
InternalSort(&modules, modules.size(), CompareBaseAddress);
|
|
|
|
for (uptr i = 0; i < modules.size(); ++i) {
|
|
|
|
char uuid_str[128];
|
|
|
|
FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
|
|
|
|
Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
|
|
|
|
modules[i].max_executable_address(), modules[i].full_name(),
|
|
|
|
ModuleArchToString(modules[i].arch()), uuid_str);
|
|
|
|
}
|
|
|
|
Printf("End of module map.\n");
|
|
|
|
}
|
|
|
|
|
2017-03-09 18:47:38 +08:00
|
|
|
void CheckNoDeepBind(const char *filename, int flag) {
|
|
|
|
// Do nothing.
|
|
|
|
}
|
|
|
|
|
2012-06-04 22:27:50 +08:00
|
|
|
} // namespace __sanitizer
|
|
|
|
|
2013-04-03 15:24:35 +08:00
|
|
|
#endif // SANITIZER_MAC
|