[Sanitizer] factor out GetThreadStackTopAndBottom from ASan runtime to common.

llvm-svn: 158140
This commit is contained in:
Alexey Samsonov 2012-06-07 07:13:46 +00:00
parent 28a9895ee0
commit 4b1f1031e6
8 changed files with 98 additions and 69 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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);
}

View File

@ -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];

View File

@ -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, ...);

View File

@ -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_,

View File

@ -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();

View File

@ -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();