diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:53 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:53 +0000 |
commit | ab0bf875a5f328a6710f4e48258979ae1bc8da1c (patch) | |
tree | 66903cf9f73151825893dcc216b04c0930317a10 /lib/lsan/lsan_common_mac.cc | |
parent | abacad30a54c59ad437ccf54ec5236a8dd7f3ba9 (diff) |
Notes
Diffstat (limited to 'lib/lsan/lsan_common_mac.cc')
-rw-r--r-- | lib/lsan/lsan_common_mac.cc | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/lib/lsan/lsan_common_mac.cc b/lib/lsan/lsan_common_mac.cc new file mode 100644 index 0000000000000..022e73937895f --- /dev/null +++ b/lib/lsan/lsan_common_mac.cc @@ -0,0 +1,126 @@ +//=-- lsan_common_mac.cc --------------------------------------------------===// +// +// 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 LeakSanitizer. +// Implementation of common leak checking functionality. Darwin-specific code. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#include "lsan_common.h" + +#if CAN_SANITIZE_LEAKS && SANITIZER_MAC + +#include "sanitizer_common/sanitizer_allocator_internal.h" +#include "lsan_allocator.h" + +#include <pthread.h> + +namespace __lsan { + +typedef struct { + int disable_counter; + u32 current_thread_id; + AllocatorCache cache; +} thread_local_data_t; + +static pthread_key_t key; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; + +// The main thread destructor requires the current thread id, +// so we can't destroy it until it's been used and reset to invalid tid +void restore_tid_data(void *ptr) { + thread_local_data_t *data = (thread_local_data_t *)ptr; + if (data->current_thread_id != kInvalidTid) + pthread_setspecific(key, data); +} + +static void make_tls_key() { + CHECK_EQ(pthread_key_create(&key, restore_tid_data), 0); +} + +static thread_local_data_t *get_tls_val(bool alloc) { + pthread_once(&key_once, make_tls_key); + + thread_local_data_t *ptr = (thread_local_data_t *)pthread_getspecific(key); + if (ptr == NULL && alloc) { + ptr = (thread_local_data_t *)InternalAlloc(sizeof(*ptr)); + ptr->disable_counter = 0; + ptr->current_thread_id = kInvalidTid; + ptr->cache = AllocatorCache(); + pthread_setspecific(key, ptr); + } + + return ptr; +} + +bool DisabledInThisThread() { + thread_local_data_t *data = get_tls_val(false); + return data ? data->disable_counter > 0 : false; +} + +void DisableInThisThread() { ++get_tls_val(true)->disable_counter; } + +void EnableInThisThread() { + int *disable_counter = &get_tls_val(true)->disable_counter; + if (*disable_counter == 0) { + DisableCounterUnderflow(); + } + --*disable_counter; +} + +u32 GetCurrentThread() { + thread_local_data_t *data = get_tls_val(false); + CHECK(data); + return data->current_thread_id; +} + +void SetCurrentThread(u32 tid) { get_tls_val(true)->current_thread_id = tid; } + +AllocatorCache *GetAllocatorCache() { return &get_tls_val(true)->cache; } + +// Required on Linux for initialization of TLS behavior, but should not be +// required on Darwin. +void InitializePlatformSpecificModules() { + if (flags()->use_tls) { + Report("use_tls=1 is not supported on Darwin.\n"); + Die(); + } +} + +// Scans global variables for heap pointers. +void ProcessGlobalRegions(Frontier *frontier) { + MemoryMappingLayout memory_mapping(false); + InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128); + memory_mapping.DumpListOfModules(&modules); + for (uptr i = 0; i < modules.size(); ++i) { + // Even when global scanning is disabled, we still need to scan + // system libraries for stashed pointers + if (!flags()->use_globals && modules[i].instrumented()) continue; + + for (const __sanitizer::LoadedModule::AddressRange &range : + modules[i].ranges()) { + if (range.executable) continue; + + ScanGlobalRange(range.beg, range.end, frontier); + } + } +} + +void ProcessPlatformSpecificAllocations(Frontier *frontier) { + CHECK(0 && "unimplemented"); +} + +void DoStopTheWorld(StopTheWorldCallback callback, void *argument) { + CHECK(0 && "unimplemented"); +} + +} // namespace __lsan + +#endif // CAN_SANITIZE_LEAKS && SANITIZER_MAC |