From 78d87d3b4b8eb0402af4d6a775fa5cf91190f847 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 5 Jan 2012 01:07:27 +0000 Subject: [PATCH] [asan] move {linux,mac}-specific code from asan_thread.cc to asan_{linux,mac}.cc; also add asan_procmaps.h which I forgot to add on previous commit. llvm-svn: 147586 --- compiler-rt/lib/asan/asan_linux.cc | 52 +++++++++++++++++++++++++ compiler-rt/lib/asan/asan_mac.cc | 10 +++++ compiler-rt/lib/asan/asan_procmaps.h | 41 ++++++++++++++++++++ compiler-rt/lib/asan/asan_thread.cc | 58 ---------------------------- 4 files changed, 103 insertions(+), 58 deletions(-) create mode 100644 compiler-rt/lib/asan/asan_procmaps.h diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index 2a529167d45f..3150f8df91b8 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -16,11 +16,15 @@ #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_procmaps.h" +#include "asan_thread.h" +#include +#include #include #include #include #include +#include #include #include @@ -150,6 +154,54 @@ bool AsanProcMaps::Next(uint64_t *start, uint64_t *end, return true; } +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. + AsanProcMaps proc_maps; + uint64_t start, end, offset; + uint64_t prev_end = 0; + while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { + if ((uintptr_t)&rl < end) + break; + prev_end = end; + } + CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); + + // Get stacksize from rlimit, but clip it so that it does not overlap + // with other mappings. + size_t stacksize = rl.rlim_cur; + if (stacksize > end - prev_end) + stacksize = end - prev_end; + if (stacksize > kMaxThreadStackSize) + stacksize = kMaxThreadStackSize; + stack_top_ = end; + stack_bottom_ = end - stacksize; + CHECK(AddrIsInStack((uintptr_t)&rl)); + return; + } + pthread_attr_t attr; + CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); + size_t stacksize = 0; + void *stackaddr = NULL; + pthread_attr_getstack(&attr, &stackaddr, &stacksize); + pthread_attr_destroy(&attr); + + stack_top_ = (uintptr_t)stackaddr + stacksize; + stack_bottom_ = (uintptr_t)stackaddr; + // 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 subrocesses with unlimited stack. + if (stacksize > kMaxThreadStackSize) { + stack_bottom_ = stack_top_ - kMaxThreadStackSize; + } + CHECK(AddrIsInStack((uintptr_t)&attr)); +} + + } // namespace __asan #endif // __linux__ diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index b202e639b511..8bedf7aaae2a 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -22,6 +22,7 @@ #include "asan_thread_registry.h" #include +#include #include #include @@ -103,6 +104,15 @@ int AsanClose(int fd) { return close(fd); } +void AsanThread::SetThreadStackTopAndBottom() { + size_t stacksize = pthread_get_stacksize_np(pthread_self()); + void *stackaddr = pthread_get_stackaddr_np(pthread_self()); + stack_top_ = (uintptr_t)stackaddr; + stack_bottom_ = stack_top_ - stacksize; + int local; + CHECK(AddrIsInStack((uintptr_t)&local)); +} + // Support for the following functions from libdispatch on Mac OS: // dispatch_async_f() // dispatch_async() diff --git a/compiler-rt/lib/asan/asan_procmaps.h b/compiler-rt/lib/asan/asan_procmaps.h new file mode 100644 index 000000000000..48ab58ae8870 --- /dev/null +++ b/compiler-rt/lib/asan/asan_procmaps.h @@ -0,0 +1,41 @@ +//===-- asan_process.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Information about the process mappings. +//===----------------------------------------------------------------------===// +#ifndef ASAN_PROCMAPS_H +#define ASAN_PROCMAPS_H + +#include "asan_internal.h" + +namespace __asan { + +class AsanProcMaps { + public: + AsanProcMaps(); + bool Next(uint64_t *start, uint64_t *end, uint64_t *offset, + char filename[], size_t filename_size); + void Reset(); + ~AsanProcMaps(); + private: +#if defined __linux__ + char *proc_self_maps_buff_; + size_t proc_self_maps_buff_mmaped_size_; + size_t proc_self_maps_buff_len_; + char *current_; +#elif defined __APPLE__ +// FIXME: Mac code goes here +#endif +}; + +} // namespace __asan + +#endif // ASAN_PROCMAPS_H diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 420c34273d92..6fa33017317d 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -18,8 +18,6 @@ #include "asan_thread_registry.h" #include "asan_mapping.h" -#include -#include #include #include #include @@ -114,60 +112,4 @@ const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { return "UNKNOWN"; } -void AsanThread::SetThreadStackTopAndBottom() { -#ifdef __APPLE__ - size_t stacksize = pthread_get_stacksize_np(pthread_self()); - void *stackaddr = pthread_get_stackaddr_np(pthread_self()); - stack_top_ = (uintptr_t)stackaddr; - stack_bottom_ = stack_top_ - stacksize; - int local; - CHECK(AddrIsInStack((uintptr_t)&local)); -#else - 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. - AsanProcMaps proc_maps; - uint64_t start, end, offset; - uint64_t prev_end = 0; - while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { - if ((uintptr_t)&rl < end) - break; - prev_end = end; - } - CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); - - // Get stacksize from rlimit, but clip it so that it does not overlap - // with other mappings. - size_t stacksize = rl.rlim_cur; - if (stacksize > end - prev_end) - stacksize = end - prev_end; - if (stacksize > kMaxThreadStackSize) - stacksize = kMaxThreadStackSize; - stack_top_ = end; - stack_bottom_ = end - stacksize; - CHECK(AddrIsInStack((uintptr_t)&rl)); - return; - } - pthread_attr_t attr; - CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); - size_t stacksize = 0; - void *stackaddr = NULL; - pthread_attr_getstack(&attr, &stackaddr, &stacksize); - pthread_attr_destroy(&attr); - - stack_top_ = (uintptr_t)stackaddr + stacksize; - stack_bottom_ = (uintptr_t)stackaddr; - // 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 subrocesses with unlimited stack. - if (stacksize > kMaxThreadStackSize) { - stack_bottom_ = stack_top_ - kMaxThreadStackSize; - } - CHECK(AddrIsInStack((uintptr_t)&attr)); -#endif -} - } // namespace __asan