summaryrefslogtreecommitdiffstats
path: root/lib/asan/asan_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asan/asan_linux.cc')
-rw-r--r--lib/asan/asan_linux.cc144
1 files changed, 94 insertions, 50 deletions
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index 26a08ae..9a3d6bd 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -13,87 +13,131 @@
//===----------------------------------------------------------------------===//
#ifdef __linux__
+#include "asan_interceptors.h"
#include "asan_internal.h"
+#include "asan_lock.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include <sys/time.h>
+#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
#include <unistd.h>
+#include <unwind.h>
-extern char _DYNAMIC[];
+#ifndef ANDROID
+// FIXME: where to get ucontext on Android?
+#include <sys/ucontext.h>
+#endif
+
+extern "C" void* _DYNAMIC;
namespace __asan {
void *AsanDoesNotSupportStaticLinkage() {
// This will fail to link with -static.
- return &_DYNAMIC;
-}
-
-static void *asan_mmap(void *addr, size_t length, int prot, int flags,
- int fd, uint64_t offset) {
-# if __WORDSIZE == 64
- return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
-# else
- return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
-# endif
+ return &_DYNAMIC; // defined in link.h
}
-void *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) {
- size = RoundUpTo(size, kPageSize);
- void *res = asan_mmap(0, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, -1, 0);
- if (res == (void*)-1) {
- OutOfMemoryMessageAndDie(mem_type, size);
- }
- return res;
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#ifdef ANDROID
+ *pc = *sp = *bp = 0;
+#elif defined(__arm__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.arm_pc;
+ *bp = ucontext->uc_mcontext.arm_fp;
+ *sp = ucontext->uc_mcontext.arm_sp;
+# elif defined(__x86_64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_RIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_RBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_RSP];
+# elif defined(__i386__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_EIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_EBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_ESP];
+#else
+# error "Unsupported arch"
+#endif
}
-void *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) {
- return asan_mmap((void*)fixed_addr, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
- 0, 0);
+bool AsanInterceptsSignal(int signum) {
+ return signum == SIGSEGV && flags()->handle_segv;
}
-void *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size) {
- return asan_mmap((void*)fixed_addr, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- 0, 0);
+void AsanPlatformThreadInit() {
+ // Nothing here for now.
}
-void *AsanMprotect(uintptr_t fixed_addr, size_t size) {
- return asan_mmap((void*)fixed_addr, size,
- PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
- 0, 0);
+AsanLock::AsanLock(LinkerInitialized) {
+ // We assume that pthread_mutex_t initialized to all zeroes is a valid
+ // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
+ // a gcc warning:
+ // extended initializer lists only available with -std=c++0x or -std=gnu++0x
}
-void AsanUnmapOrDie(void *addr, size_t size) {
- if (!addr || !size) return;
- int res = syscall(__NR_munmap, addr, size);
- if (res != 0) {
- Report("Failed to unmap\n");
- ASAN_DIE;
- }
+void AsanLock::Lock() {
+ CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
+ pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
+ CHECK(!owner_);
+ owner_ = (uptr)pthread_self();
}
-ssize_t AsanWrite(int fd, const void *buf, size_t count) {
- return (ssize_t)syscall(__NR_write, fd, buf, count);
+void AsanLock::Unlock() {
+ CHECK(owner_ == (uptr)pthread_self());
+ owner_ = 0;
+ pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
}
-int AsanOpenReadonly(const char* filename) {
- return open(filename, O_RDONLY);
+#ifdef __arm__
+#define UNWIND_STOP _URC_END_OF_STACK
+#define UNWIND_CONTINUE _URC_NO_REASON
+#else
+#define UNWIND_STOP _URC_NORMAL_STOP
+#define UNWIND_CONTINUE _URC_NO_REASON
+#endif
+
+uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
+#ifdef __arm__
+ uptr val;
+ _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
+ 15 /* r15 = PC */, _UVRSD_UINT32, &val);
+ CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
+ // Clear the Thumb bit.
+ return val & ~(uptr)1;
+#else
+ return _Unwind_GetIP(ctx);
+#endif
}
-ssize_t AsanRead(int fd, void *buf, size_t count) {
- return (ssize_t)syscall(__NR_read, fd, buf, count);
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
+ void *param) {
+ AsanStackTrace *b = (AsanStackTrace*)param;
+ CHECK(b->size < b->max_size);
+ uptr pc = Unwind_GetIP(ctx);
+ b->trace[b->size++] = pc;
+ if (b->size == b->max_size) return UNWIND_STOP;
+ return UNWIND_CONTINUE;
}
-int AsanClose(int fd) {
- return close(fd);
+void AsanStackTrace::GetStackTrace(uptr max_s, uptr pc, uptr bp) {
+ size = 0;
+ trace[0] = pc;
+ if ((max_s) > 1) {
+ max_size = max_s;
+#ifdef __arm__
+ _Unwind_Backtrace(Unwind_Trace, this);
+#else
+ FastUnwindStack(pc, bp);
+#endif
+ }
}
} // namespace __asan
OpenPOWER on IntegriCloud