diff options
author | Alexey Samsonov <samsonov@google.com> | 2012-06-07 07:13:46 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2012-06-07 07:13:46 +0000 |
commit | e5931fd7d2a74fd7fb60bd8d7f644cca51a24364 (patch) | |
tree | bed59375675460fe548790ea6672c9a5ba91d641 /lib | |
parent | 6895adc39c4e09371154c8037366ad4464163ed0 (diff) | |
download | compiler-rt-e5931fd7d2a74fd7fb60bd8d7f644cca51a24364.tar.gz |
[Sanitizer] factor out GetThreadStackTopAndBottom from ASan runtime to common.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@158140 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_linux.cc | 45 | ||||
-rw-r--r-- | lib/asan/asan_mac.cc | 9 | ||||
-rw-r--r-- | lib/asan/asan_thread.cc | 7 | ||||
-rw-r--r-- | lib/asan/asan_win.cc | 11 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux.cc | 54 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_mac.cc | 20 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_win.cc | 16 |
8 files changed, 98 insertions, 69 deletions
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc index 947c17f70..b3f879b52 100644 --- a/lib/asan/asan_linux.cc +++ b/lib/asan/asan_linux.cc @@ -117,51 +117,6 @@ const char* AsanGetEnv(const char* name) { return 0; // Not found. } -void AsanThread::SetThreadStackTopAndBottom() { - if (tid() == 0) { - // This is the main thread. Libpthread may not be initialized yet. - struct rlimit rl; - CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); - - // Find the mapping that contains a stack variable. - ProcessMaps proc_maps; - uptr start, end, offset; - uptr prev_end = 0; - while (proc_maps.Next(&start, &end, &offset, 0, 0)) { - if ((uptr)&rl < end) - break; - prev_end = end; - } - CHECK((uptr)&rl >= start && (uptr)&rl < end); - - // Get stacksize from rlimit, but clip it so that it does not overlap - // with other mappings. - uptr stacksize = rl.rlim_cur; - if (stacksize > end - prev_end) - stacksize = end - prev_end; - // When running with unlimited stack size, we still want to set some limit. - // The unlimited stack size is caused by 'ulimit -s unlimited'. - // Also, for some reason, GNU make spawns subprocesses with unlimited stack. - if (stacksize > kMaxThreadStackSize) - stacksize = kMaxThreadStackSize; - stack_top_ = end; - stack_bottom_ = end - stacksize; - CHECK(AddrIsInStack((uptr)&rl)); - return; - } - pthread_attr_t attr; - CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); - uptr stacksize = 0; - void *stackaddr = 0; - pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); - pthread_attr_destroy(&attr); - - stack_top_ = (uptr)stackaddr + stacksize; - stack_bottom_ = (uptr)stackaddr; - CHECK(stacksize < kMaxThreadStackSize); // Sanity check. - CHECK(AddrIsInStack((uptr)&attr)); -} - 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 diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc index 644fbd9af..a2df818c5 100644 --- a/lib/asan/asan_mac.cc +++ b/lib/asan/asan_mac.cc @@ -132,15 +132,6 @@ const char *AsanGetEnv(const char *name) { return 0; } -void AsanThread::SetThreadStackTopAndBottom() { - uptr stacksize = pthread_get_stacksize_np(pthread_self()); - void *stackaddr = pthread_get_stackaddr_np(pthread_self()); - stack_top_ = (uptr)stackaddr; - stack_bottom_ = stack_top_ - stacksize; - int local; - CHECK(AddrIsInStack((uptr)&local)); -} - AsanLock::AsanLock(LinkerInitialized) { // We assume that OS_SPINLOCK_INIT is zero } diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc index da397bb5b..d301a4b87 100644 --- a/lib/asan/asan_thread.cc +++ b/lib/asan/asan_thread.cc @@ -18,6 +18,7 @@ #include "asan_thread.h" #include "asan_thread_registry.h" #include "asan_mapping.h" +#include "sanitizer_common/sanitizer_common.h" namespace __asan { @@ -101,6 +102,12 @@ thread_return_t AsanThread::ThreadStart() { return res; } +void AsanThread::SetThreadStackTopAndBottom() { + GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_); + int local; + CHECK(AddrIsInStack((uptr)&local)); +} + void AsanThread::ClearShadowForThreadStack() { PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); } diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 3ec75f912..ad62535fa 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -47,17 +47,6 @@ static AsanLock dbghelp_lock(LINKER_INITIALIZED); static bool dbghelp_initialized = false; #pragma comment(lib, "dbghelp.lib") -void AsanThread::SetThreadStackTopAndBottom() { - MEMORY_BASIC_INFORMATION mbi; - CHECK(VirtualQuery(&mbi /* on stack */, - &mbi, sizeof(mbi)) != 0); - // FIXME: is it possible for the stack to not be a single allocation? - // Are these values what ASan expects to get (reserved, not committed; - // including stack guard page) ? - stack_top_ = (uptr)mbi.BaseAddress + mbi.RegionSize; - stack_bottom_ = (uptr)mbi.AllocationBase; -} - void AsanStackTrace::GetStackTrace(uptr max_s, uptr pc, uptr bp) { max_size = max_s; void *tmp[kStackTraceMax]; diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 2f13814bc..817b95903 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -26,13 +26,16 @@ const uptr kWordSizeInBits = 8 * kWordSize; const uptr kPageSizeBits = 12; const uptr kPageSize = 1UL << kPageSizeBits; +// Threads int GetPid(); -void RawWrite(const char *buffer); +void GetThreadStackTopAndBottom(bool is_main_thread, uptr *stack_top, + uptr *stack_bottom); // Memory management void *MmapOrDie(uptr size, const char *mem_type); void UnmapOrDie(void *addr, uptr size); +void RawWrite(const char *buffer); void Printf(const char *format, ...); int SNPrintf(char *buffer, uptr length, const char *format, ...); void Report(const char *format, ...); diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 9cd336efe..1ece95c62 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -19,14 +19,18 @@ #include "sanitizer_procmaps.h" #include <fcntl.h> +#include <pthread.h> #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <sys/syscall.h> +#include <sys/time.h> #include <sys/types.h> #include <unistd.h> namespace __sanitizer { +// --------------- sanitizer_libc.h void *internal_mmap(void *addr, uptr length, int prot, int flags, int fd, u64 offset) { #if __WORDSIZE == 64 @@ -68,7 +72,55 @@ int internal_dup2(int oldfd, int newfd) { return syscall(__NR_dup2, oldfd, newfd); } -// ----------------- ProcessMaps implementation. +// ----------------- sanitizer_common.h +void GetThreadStackTopAndBottom(bool is_main_thread, uptr *stack_top, + uptr *stack_bottom) { + static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M + CHECK(stack_top); + CHECK(stack_bottom); + if (is_main_thread) { + // This is the main thread. Libpthread may not be initialized yet. + struct rlimit rl; + CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); + + // Find the mapping that contains a stack variable. + ProcessMaps proc_maps; + uptr start, end, offset; + uptr prev_end = 0; + while (proc_maps.Next(&start, &end, &offset, 0, 0)) { + if ((uptr)&rl < end) + break; + prev_end = end; + } + CHECK((uptr)&rl >= start && (uptr)&rl < end); + + // Get stacksize from rlimit, but clip it so that it does not overlap + // with other mappings. + uptr stacksize = rl.rlim_cur; + if (stacksize > end - prev_end) + stacksize = end - prev_end; + // When running with unlimited stack size, we still want to set some limit. + // The unlimited stack size is caused by 'ulimit -s unlimited'. + // Also, for some reason, GNU make spawns subprocesses with unlimited stack. + if (stacksize > kMaxThreadStackSize) + stacksize = kMaxThreadStackSize; + *stack_top = end; + *stack_bottom = end - stacksize; + return; + } + pthread_attr_t attr; + CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); + uptr stacksize = 0; + void *stackaddr = 0; + pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); + pthread_attr_destroy(&attr); + + *stack_top = (uptr)stackaddr + stacksize; + *stack_bottom = (uptr)stackaddr; + CHECK(stacksize < kMaxThreadStackSize); // Sanity check. +} + +// ----------------- sanitizer_procmaps.h ProcessMaps::ProcessMaps() { proc_self_maps_buff_len_ = ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_, diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 6fe0b6086..d0f334082 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -14,20 +14,24 @@ #ifdef __APPLE__ +#include "sanitizer_common.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_procmaps.h" +#include <fcntl.h> #include <mach-o/dyld.h> #include <mach-o/loader.h> +#include <pthread.h> #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <sys/types.h> -#include <fcntl.h> #include <unistd.h> namespace __sanitizer { +// ---------------------- sanitizer_libc.h void *internal_mmap(void *addr, size_t length, int prot, int flags, int fd, u64 offset) { return mmap(addr, length, prot, flags, fd, offset); @@ -65,7 +69,19 @@ int internal_dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); } -// ----------------- ProcessMaps implementation. +// ----------------- sanitizer_common.h +void GetThreadStackTopAndBottom(bool is_main_thread, uptr *stack_top, + uptr *stack_bottom) { + CHECK(stack_top); + CHECK(stack_bottom); + uptr stacksize = pthread_get_stacksize_np(pthread_self()); + void *stackaddr = pthread_get_stackaddr_np(pthread_self()); + *stack_top = (uptr)stackaddr; + *stack_bottom = stack_top_ - stacksize; +} + + +// ----------------- sanitizer_procmaps.h ProcessMaps::ProcessMaps() { Reset(); diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index db16d857d..6c8ed41ab 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -19,10 +19,25 @@ namespace __sanitizer { +// --------------------- sanitizer_common.h int GetPid() { return GetProcessId(GetCurrentProcess()); } +void GetThreadStackTopAndBottom(bool is_main_thread, uptr *stack_top, + uptr *stack_bottom) { + CHECK(stack_top); + CHECK(stack_bottom); + MEMORY_BASIC_INFORMATION mbi; + CHECK(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)) != 0); + // FIXME: is it possible for the stack to not be a single allocation? + // Are these values what ASan expects to get (reserved, not committed; + // including stack guard page) ? + *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize; + *stack_bottom = (uptr)mbi.AllocationBase; +} + + void *MmapOrDie(uptr size, const char *mem_type) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) { @@ -41,6 +56,7 @@ void UnmapOrDie(void *addr, uptr size) { } } +// ------------------ sanitizer_libc.h void *internal_mmap(void *addr, uptr length, int prot, int flags, int fd, u64 offset) { UNIMPLEMENTED(); |