lsan_common.h revision 9fbfd96608070eb71e11fbfe42ec9e84016429ae
1ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//=-- lsan_common.h -------------------------------------------------------===// 2ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// 3ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// The LLVM Compiler Infrastructure 4ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// 5ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// This file is distributed under the University of Illinois Open Source 6ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// License. See LICENSE.TXT for details. 7ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// 8ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//===----------------------------------------------------------------------===// 9ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// 10ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// This file is a part of LeakSanitizer. 11ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Private LSan header. 12ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// 13ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//===----------------------------------------------------------------------===// 14ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 15ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#ifndef LSAN_COMMON_H 16ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#define LSAN_COMMON_H 17ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 18ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev#include "sanitizer_common/sanitizer_allocator.h" 19ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_common.h" 20ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_internal_defs.h" 219bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#include "sanitizer_common/sanitizer_platform.h" 22ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_symbolizer.h" 23ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 249bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#if SANITIZER_LINUX && defined(__x86_64__) 259bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 1 269bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#else 279bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 0 289bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#endif 299bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev 30ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevnamespace __lsan { 31ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 32ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Chunk tags. 33ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevenum ChunkTag { 34ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev kDirectlyLeaked = 0, // default 35ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev kIndirectlyLeaked = 1, 365e719a705666988781b9735d62cafc808ade60e2Sergey Matveev kReachable = 2, 37b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev kIgnored = 3 38ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 39ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 40ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Flags { 41ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr pointer_alignment() const { 42ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev return use_unaligned ? 1 : sizeof(uptr); 43ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev } 44ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 45b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev // Print addresses of leaked objects after main leak report. 46b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev bool report_objects; 47b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev // Aggregate two objects into one leak if this many stack frames match. If 48ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev // zero, the entire stack trace must match. 49ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev int resolution; 50ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev // The number of leaks reported. 51ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev int max_leaks; 52969b529914f5bc17e4810076dccbaadf563d584cSergey Matveev // If nonzero kill the process with this exit code upon finding leaks. 53969b529914f5bc17e4810076dccbaadf563d584cSergey Matveev int exitcode; 54ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 55ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // Flags controlling the root set of reachable memory. 56ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // Global variables (.data and .bss). 57ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev bool use_globals; 58ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // Thread stacks. 59ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev bool use_stacks; 60ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // Thread registers. 61ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev bool use_registers; 62ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // TLS and thread-specific storage. 63ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev bool use_tls; 64ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev 65ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev // Consider unaligned pointers valid. 66ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev bool use_unaligned; 67ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev 68cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev // User-visible verbosity. 69cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev int verbosity; 70cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev 71ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev // Debug logging. 72ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool log_pointers; 73ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool log_threads; 74ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 75ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 76ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevextern Flags lsan_flags; 77ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevinline Flags *flags() { return &lsan_flags; } 78ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 79ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Leak { 80ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr hit_count; 81ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr total_size; 82ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev u32 stack_trace_id; 83ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool is_directly_leaked; 84ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 85ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 86ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Aggregates leaks by stack trace prefix. 87ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LeakReport { 88ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public: 89ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev LeakReport() : leaks_(1) {} 90ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag); 91ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void PrintLargest(uptr max_leaks); 926c3634b1d5eeb0bffea01df10caa7168c48c8c5dSergey Matveev void PrintSummary(); 93ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool IsEmpty() { return leaks_.size() == 0; } 94ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private: 95a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov InternalMmapVector<Leak> leaks_; 96ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 97ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 98dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovtypedef InternalMmapVector<uptr> Frontier; 99dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov 100ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Platform-specific functions. 101ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid InitializePlatformSpecificModules(); 102dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessGlobalRegions(Frontier *frontier); 103dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessPlatformSpecificAllocations(Frontier *frontier); 104ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 105a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovvoid ScanRangeForPointers(uptr begin, uptr end, 106dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov Frontier *frontier, 107ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev const char *region_type, ChunkTag tag); 108ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 109cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveevenum IgnoreObjectResult { 110cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectSuccess, 111cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectAlreadyIgnored, 112cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectInvalid 113cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev}; 114cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev 115200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev// Functions called from the parent tool. 116200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid InitCommonLsan(); 117200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid DoLeakCheck(); 118200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevbool DisabledInThisThread(); 119200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev 120ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// The following must be implemented in the parent tool. 121ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 122ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevvoid ForEachChunk(ForEachChunkCallback callback, void *arg); 123ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns the address range occupied by the global allocator object. 124ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid GetAllocatorGlobalRange(uptr *begin, uptr *end); 125ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for allocator's ForceLock()/ForceUnlock(). 126ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockAllocator(); 127ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockAllocator(); 128ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for ThreadRegistry access. 129ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockThreadRegistry(); 130ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockThreadRegistry(); 131ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 132ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr *tls_begin, uptr *tls_end, 133ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr *cache_begin, uptr *cache_end); 134ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// If p points into a chunk that has been allocated to the user, returns its 135ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// user-visible address. Otherwise, returns 0. 136ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr PointsIntoChunk(void *p); 137ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns address of user-visible chunk contained in this allocator chunk. 138ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr GetUserBegin(uptr chunk); 139cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev// Helper for __lsan_ignore_object(). 140cd571e07fd1179383188c70338fa0dc1c452cb19Sergey MatveevIgnoreObjectResult IgnoreObjectLocked(const void *p); 141ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrapper for chunk metadata operations. 142ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LsanMetadata { 143ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public: 144ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev // Constructor accepts address of user-visible chunk. 145ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev explicit LsanMetadata(uptr chunk); 146ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool allocated() const; 147ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev ChunkTag tag() const; 148ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void set_tag(ChunkTag value); 149ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr requested_size() const; 150ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev u32 stack_trace_id() const; 151ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private: 152ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void *metadata_; 153ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 154ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 155ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev} // namespace __lsan 156ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 1579fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovextern "C" { 1589fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovint __lsan_is_turned_off() SANITIZER_WEAK_ATTRIBUTE 1599fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov SANITIZER_INTERFACE_ATTRIBUTE; 1609fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov} // extern "C" 1619fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov 162ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#endif // LSAN_COMMON_H 163