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