summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_linux.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc81
1 files changed, 72 insertions, 9 deletions
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 89c76422c..6c83e8db4 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -14,7 +14,8 @@
#include "sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
@@ -55,7 +56,9 @@
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
+#if !SANITIZER_SOLARIS
#include <sys/ptrace.h>
+#endif
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -92,6 +95,14 @@ extern char **environ; // provided by crt1
extern struct ps_strings *__ps_strings;
#endif // SANITIZER_NETBSD
+#if SANITIZER_SOLARIS
+#include <stdlib.h>
+#include <thread.h>
+
+extern char **_environ;
+#define environ _environ
+#endif
+
#if !SANITIZER_ANDROID
#include <sys/signal.h>
#endif
@@ -146,6 +157,7 @@ namespace __sanitizer {
#endif
// --------------- sanitizer_libc.h
+#if !SANITIZER_SOLARIS
#if !SANITIZER_S390
uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
OFF_T offset) {
@@ -424,6 +436,7 @@ uptr internal_execve(const char *filename, char *const argv[],
return internal_syscall_ptr(SYSCALL(execve), (uptr)filename, (uptr)argv,
(uptr)envp);
}
+#endif // !SANITIZER_SOLARIS
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
@@ -443,11 +456,14 @@ tid_t GetTid() {
return (uptr)pthread_self();
#elif SANITIZER_NETBSD
return _lwp_self();
+#elif SANITIZER_SOLARIS
+ return (uptr)thr_self();
#else
return internal_syscall(SYSCALL(gettid));
#endif
}
+#if !SANITIZER_SOLARIS
u64 NanoTime() {
#if SANITIZER_FREEBSD || SANITIZER_NETBSD
timeval tv;
@@ -462,12 +478,13 @@ u64 NanoTime() {
uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
return internal_syscall_ptr(SYSCALL(clock_gettime), clk_id, tp);
}
+#endif // !SANITIZER_SOLARIS
// Like getenv, but reads env directly from /proc (on Linux) or parses the
-// 'environ' array (on FreeBSD) and does not use libc. This function should be
-// called first inside __asan_init.
+// 'environ' array (on some others) and does not use libc. This function
+// should be called first inside __asan_init.
const char *GetEnv(const char *name) {
-#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS
if (::environ != 0) {
uptr NameLen = internal_strlen(name);
for (char **Env = ::environ; *Env != 0; Env++) {
@@ -590,6 +607,9 @@ void ReExec() {
len = sizeof(path);
if (sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1)
pathname = path;
+#elif SANITIZER_SOLARIS
+ pathname = getexecname();
+ CHECK_NE(pathname, NULL);
#endif
GetArgsAndEnv(&argv, &envp);
@@ -600,6 +620,7 @@ void ReExec() {
Die();
}
+#if !SANITIZER_SOLARIS
enum MutexState {
MtxUnlocked = 0,
MtxLocked = 1,
@@ -619,7 +640,7 @@ void BlockingMutex::Lock() {
#if SANITIZER_FREEBSD
_umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
#elif SANITIZER_NETBSD
- sched_yield(); /* No userspace futex-like synchromization */
+ sched_yield(); /* No userspace futex-like synchronization */
#else
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
#endif
@@ -634,7 +655,7 @@ void BlockingMutex::Unlock() {
#if SANITIZER_FREEBSD
_umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
#elif SANITIZER_NETBSD
- /* No userspace futex-like synchromization */
+ /* No userspace futex-like synchronization */
#else
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
#endif
@@ -645,6 +666,7 @@ void BlockingMutex::CheckLocked() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
}
+#endif // !SANITIZER_SOLARIS
// ----------------- sanitizer_linux.h
// The actual size of this structure is specified by d_reclen.
@@ -677,6 +699,7 @@ struct linux_dirent {
};
#endif
+#if !SANITIZER_SOLARIS
// Syscall wrappers.
uptr internal_ptrace(int request, int pid, void *addr, void *data) {
#if SANITIZER_NETBSD
@@ -854,6 +877,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
return k_set->sig[idx] & (1 << bit);
}
#endif // SANITIZER_LINUX
+#endif // !SANITIZER_SOLARIS
// ThreadLister implementation.
ThreadLister::ThreadLister(int pid)
@@ -1011,6 +1035,11 @@ uptr GetPageSize() {
}
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+#if SANITIZER_SOLARIS
+ const char *default_module_name = getexecname();
+ CHECK_NE(default_module_name, NULL);
+ return internal_snprintf(buf, buf_len, "%s", default_module_name);
+#else
#if SANITIZER_FREEBSD || SANITIZER_NETBSD
#if SANITIZER_FREEBSD
const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
@@ -1028,7 +1057,7 @@ uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
default_module_name, buf, buf_len);
int readlink_error;
bool IsErr = internal_iserror(module_name_len, &readlink_error);
-#endif
+#endif // SANITIZER_SOLARIS
if (IsErr) {
// We can't read binary name for some reason, assume it's unknown.
Report("WARNING: reading executable name failed with errno %d, "
@@ -1038,6 +1067,7 @@ uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
CHECK_LT(module_name_len, buf_len);
}
return module_name_len;
+#endif
}
uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
@@ -1662,6 +1692,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
uptr err = ucontext->uc_mcontext.mc_err;
#elif SANITIZER_NETBSD
uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
+#elif SANITIZER_SOLARIS && defined(__i386__)
+# define ERR 13
+ uptr err = ucontext->uc_mcontext.gregs[ERR];
#else
uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
#endif
@@ -1675,6 +1708,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
u64 esr;
if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
return esr & ESR_ELx_WNR ? WRITE : READ;
+#elif SANITIZER_SOLARIS && defined(__sparc__)
+ // Decode the instruction to determine the access type.
+ // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
+ uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
+ u32 instr = *(u32 *)pc;
+ return (instr >> 21) & 1 ? WRITE: READ;
#else
(void)ucontext;
return UNKNOWN; // FIXME: Implement.
@@ -1732,6 +1771,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
*sp = ucontext->uc_mcontext.__gregs[_REG_ESP];
# else
ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_SOLARIS
+ /* Use the numeric values: the symbolic ones are undefined by llvm
+ include/llvm/Support/Solaris.h. */
+# ifndef REG_EIP
+# define REG_EIP 14 // REG_PC
+# endif
+# ifndef REG_EBP
+# define REG_EBP 6 // REG_FP
+# endif
+# ifndef REG_ESP
+# define REG_ESP 17 // REG_SP
+# endif
+# endif
*pc = ucontext->uc_mcontext.gregs[REG_EIP];
*bp = ucontext->uc_mcontext.gregs[REG_EBP];
*sp = ucontext->uc_mcontext.gregs[REG_ESP];
@@ -1746,7 +1798,16 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
#elif defined(__sparc__)
ucontext_t *ucontext = (ucontext_t*)context;
uptr *stk_ptr;
-# if defined (__arch64__)
+# if defined (__sparcv9)
+# ifndef MC_PC
+# define MC_PC REG_PC
+# endif
+# ifndef MC_O6
+# define MC_O6 REG_O6
+# endif
+# ifdef SANITIZER_SOLARIS
+# define mc_gregs gregs
+# endif
*pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
*sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
stk_ptr = (uptr *) (*sp + 2047);
@@ -1835,4 +1896,6 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
} // namespace __sanitizer
-#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
+ // SANITIZER_SOLARIS
+