1 //=-- lsan_common.h -------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of LeakSanitizer. 11 // Private LSan header. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LSAN_COMMON_H 16 #define LSAN_COMMON_H 17 18 #include "sanitizer_common/sanitizer_allocator.h" 19 #include "sanitizer_common/sanitizer_common.h" 20 #include "sanitizer_common/sanitizer_internal_defs.h" 21 #include "sanitizer_common/sanitizer_platform.h" 22 #include "sanitizer_common/sanitizer_stoptheworld.h" 23 #include "sanitizer_common/sanitizer_symbolizer.h" 24 25 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips64)) \ 26 && (SANITIZER_WORDSIZE == 64) 27 #define CAN_SANITIZE_LEAKS 1 28 #else 29 #define CAN_SANITIZE_LEAKS 0 30 #endif 31 32 namespace __sanitizer { 33 class FlagParser; 34 } 35 36 namespace __lsan { 37 38 // Chunk tags. 39 enum ChunkTag { 40 kDirectlyLeaked = 0, // default 41 kIndirectlyLeaked = 1, 42 kReachable = 2, 43 kIgnored = 3 44 }; 45 46 struct Flags { 47 #define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; 48 #include "lsan_flags.inc" 49 #undef LSAN_FLAG 50 51 void SetDefaults(); 52 uptr pointer_alignment() const { 53 return use_unaligned ? 1 : sizeof(uptr); 54 } 55 }; 56 57 extern Flags lsan_flags; 58 inline Flags *flags() { return &lsan_flags; } 59 void RegisterLsanFlags(FlagParser *parser, Flags *f); 60 61 struct Leak { 62 u32 id; 63 uptr hit_count; 64 uptr total_size; 65 u32 stack_trace_id; 66 bool is_directly_leaked; 67 bool is_suppressed; 68 }; 69 70 struct LeakedObject { 71 u32 leak_id; 72 uptr addr; 73 uptr size; 74 }; 75 76 // Aggregates leaks by stack trace prefix. 77 class LeakReport { 78 public: 79 LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {} 80 void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size, 81 ChunkTag tag); 82 void ReportTopLeaks(uptr max_leaks); 83 void PrintSummary(); 84 void ApplySuppressions(); 85 uptr UnsuppressedLeakCount(); 86 87 88 private: 89 void PrintReportForLeak(uptr index); 90 void PrintLeakedObjectsForLeak(uptr index); 91 92 u32 next_id_; 93 InternalMmapVector<Leak> leaks_; 94 InternalMmapVector<LeakedObject> leaked_objects_; 95 }; 96 97 typedef InternalMmapVector<uptr> Frontier; 98 99 // Platform-specific functions. 100 void InitializePlatformSpecificModules(); 101 void ProcessGlobalRegions(Frontier *frontier); 102 void ProcessPlatformSpecificAllocations(Frontier *frontier); 103 // Run stoptheworld while holding any platform-specific locks. 104 void DoStopTheWorld(StopTheWorldCallback callback, void* argument); 105 106 void ScanRangeForPointers(uptr begin, uptr end, 107 Frontier *frontier, 108 const char *region_type, ChunkTag tag); 109 110 enum IgnoreObjectResult { 111 kIgnoreObjectSuccess, 112 kIgnoreObjectAlreadyIgnored, 113 kIgnoreObjectInvalid 114 }; 115 116 // Functions called from the parent tool. 117 void InitCommonLsan(); 118 void DoLeakCheck(); 119 bool DisabledInThisThread(); 120 121 // Special case for "new T[0]" where T is a type with DTOR. 122 // new T[0] will allocate one word for the array size (0) and store a pointer 123 // to the end of allocated chunk. 124 inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size, 125 uptr addr) { 126 return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr && 127 *reinterpret_cast<uptr *>(chunk_beg) == 0; 128 } 129 130 // The following must be implemented in the parent tool. 131 132 void ForEachChunk(ForEachChunkCallback callback, void *arg); 133 // Returns the address range occupied by the global allocator object. 134 void GetAllocatorGlobalRange(uptr *begin, uptr *end); 135 // Wrappers for allocator's ForceLock()/ForceUnlock(). 136 void LockAllocator(); 137 void UnlockAllocator(); 138 // Returns true if [addr, addr + sizeof(void *)) is poisoned. 139 bool WordIsPoisoned(uptr addr); 140 // Wrappers for ThreadRegistry access. 141 void LockThreadRegistry(); 142 void UnlockThreadRegistry(); 143 bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 144 uptr *tls_begin, uptr *tls_end, 145 uptr *cache_begin, uptr *cache_end); 146 void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, 147 void *arg); 148 // If called from the main thread, updates the main thread's TID in the thread 149 // registry. We need this to handle processes that fork() without a subsequent 150 // exec(), which invalidates the recorded TID. To update it, we must call 151 // gettid() from the main thread. Our solution is to call this function before 152 // leak checking and also before every call to pthread_create() (to handle cases 153 // where leak checking is initiated from a non-main thread). 154 void EnsureMainThreadIDIsCorrect(); 155 // If p points into a chunk that has been allocated to the user, returns its 156 // user-visible address. Otherwise, returns 0. 157 uptr PointsIntoChunk(void *p); 158 // Returns address of user-visible chunk contained in this allocator chunk. 159 uptr GetUserBegin(uptr chunk); 160 // Helper for __lsan_ignore_object(). 161 IgnoreObjectResult IgnoreObjectLocked(const void *p); 162 // Wrapper for chunk metadata operations. 163 class LsanMetadata { 164 public: 165 // Constructor accepts address of user-visible chunk. 166 explicit LsanMetadata(uptr chunk); 167 bool allocated() const; 168 ChunkTag tag() const; 169 void set_tag(ChunkTag value); 170 uptr requested_size() const; 171 u32 stack_trace_id() const; 172 private: 173 void *metadata_; 174 }; 175 176 } // namespace __lsan 177 178 extern "C" { 179 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 180 int __lsan_is_turned_off(); 181 182 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 183 const char *__lsan_default_suppressions(); 184 } // extern "C" 185 186 #endif // LSAN_COMMON_H 187