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" 2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_stoptheworld.h" 23ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_symbolizer.h" 24ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips64)) \ 2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines && (SANITIZER_WORDSIZE == 64) 279bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 1 289bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#else 299bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 0 309bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#endif 319bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev 3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __sanitizer { 3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass FlagParser; 3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 36ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevnamespace __lsan { 37ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 38ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Chunk tags. 39ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevenum ChunkTag { 40ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev kDirectlyLeaked = 0, // default 41ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev kIndirectlyLeaked = 1, 425e719a705666988781b9735d62cafc808ade60e2Sergey Matveev kReachable = 2, 43b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev kIgnored = 3 44ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 45ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 46ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Flags { 4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; 4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "lsan_flags.inc" 4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef LSAN_FLAG 5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void SetDefaults(); 52ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr pointer_alignment() const { 53ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev return use_unaligned ? 1 : sizeof(uptr); 54ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev } 55ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 56ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 57ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevextern Flags lsan_flags; 58ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevinline Flags *flags() { return &lsan_flags; } 5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid RegisterLsanFlags(FlagParser *parser, Flags *f); 60ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 61ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Leak { 622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u32 id; 63ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr hit_count; 64ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr total_size; 65ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev u32 stack_trace_id; 66ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool is_directly_leaked; 67b33cfeb6004d3a93e6d35749c14db0190c6c2b4cSergey Matveev bool is_suppressed; 68ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 69ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct LeakedObject { 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u32 leak_id; 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr addr; 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr size; 742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 76ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Aggregates leaks by stack trace prefix. 77ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LeakReport { 78ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public: 792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {} 802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size, 812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ChunkTag tag); 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void ReportTopLeaks(uptr max_leaks); 836c3634b1d5eeb0bffea01df10caa7168c48c8c5dSergey Matveev void PrintSummary(); 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void ApplySuppressions(); 852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr UnsuppressedLeakCount(); 862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 88ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private: 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void PrintReportForLeak(uptr index); 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void PrintLeakedObjectsForLeak(uptr index); 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines u32 next_id_; 93a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov InternalMmapVector<Leak> leaks_; 942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InternalMmapVector<LeakedObject> leaked_objects_; 95ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 96ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 97dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovtypedef InternalMmapVector<uptr> Frontier; 98dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov 99ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Platform-specific functions. 100ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid InitializePlatformSpecificModules(); 101dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessGlobalRegions(Frontier *frontier); 102dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessPlatformSpecificAllocations(Frontier *frontier); 10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Run stoptheworld while holding any platform-specific locks. 10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid DoStopTheWorld(StopTheWorldCallback callback, void* argument); 105ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 106a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovvoid ScanRangeForPointers(uptr begin, uptr end, 107dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov Frontier *frontier, 108ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev const char *region_type, ChunkTag tag); 109ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 110cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveevenum IgnoreObjectResult { 111cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectSuccess, 112cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectAlreadyIgnored, 113cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev kIgnoreObjectInvalid 114cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev}; 115cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev 116200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev// Functions called from the parent tool. 11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid InitCommonLsan(); 118200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid DoLeakCheck(); 119200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevbool DisabledInThisThread(); 120200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Special case for "new T[0]" where T is a type with DTOR. 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// new T[0] will allocate one word for the array size (0) and store a pointer 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to the end of allocated chunk. 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size, 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr addr) { 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr && 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *reinterpret_cast<uptr *>(chunk_beg) == 0; 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 130ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// The following must be implemented in the parent tool. 131ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 132ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevvoid ForEachChunk(ForEachChunkCallback callback, void *arg); 133ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns the address range occupied by the global allocator object. 134ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid GetAllocatorGlobalRange(uptr *begin, uptr *end); 135ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for allocator's ForceLock()/ForceUnlock(). 136ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockAllocator(); 137ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockAllocator(); 1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Returns true if [addr, addr + sizeof(void *)) is poisoned. 1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool WordIsPoisoned(uptr addr); 140ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for ThreadRegistry access. 141ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockThreadRegistry(); 142ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockThreadRegistry(); 143ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 144ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr *tls_begin, uptr *tls_end, 145ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr *cache_begin, uptr *cache_end); 146c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveevvoid ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, 147c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev void *arg); 148c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// If called from the main thread, updates the main thread's TID in the thread 149c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// registry. We need this to handle processes that fork() without a subsequent 150c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// exec(), which invalidates the recorded TID. To update it, we must call 151c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// gettid() from the main thread. Our solution is to call this function before 152c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// leak checking and also before every call to pthread_create() (to handle cases 153c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// where leak checking is initiated from a non-main thread). 154c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect(); 155ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// If p points into a chunk that has been allocated to the user, returns its 156ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// user-visible address. Otherwise, returns 0. 157ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr PointsIntoChunk(void *p); 158ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns address of user-visible chunk contained in this allocator chunk. 159ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr GetUserBegin(uptr chunk); 160cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev// Helper for __lsan_ignore_object(). 161cd571e07fd1179383188c70338fa0dc1c452cb19Sergey MatveevIgnoreObjectResult IgnoreObjectLocked(const void *p); 162ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrapper for chunk metadata operations. 163ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LsanMetadata { 164ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public: 165ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev // Constructor accepts address of user-visible chunk. 166ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev explicit LsanMetadata(uptr chunk); 167ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev bool allocated() const; 168ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev ChunkTag tag() const; 169ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void set_tag(ChunkTag value); 170ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev uptr requested_size() const; 171ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev u32 stack_trace_id() const; 172ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private: 173ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev void *metadata_; 174ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}; 175ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 176ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev} // namespace __lsan 177ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev 1789fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovextern "C" { 1793c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 1803c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovint __lsan_is_turned_off(); 1813c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov 1823c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 1833c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovconst char *__lsan_default_suppressions(); 1849fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov} // extern "C" 1859fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov 186ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#endif // LSAN_COMMON_H 187