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 // LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) thus 26 // supported for Linux only. Also, LSan doesn't like 32 bit architectures 27 // because of "small" (4 bytes) pointer size that leads to high false negative 28 // ratio on large leaks. But we still want to have it for some 32 bit arches 29 // (e.g. x86), see https://github.com/google/sanitizers/issues/403. 30 // To enable LeakSanitizer on a new architecture, one needs to implement the 31 // internal_clone function as well as (probably) adjust the TLS machinery for 32 // the new architecture inside the sanitizer library. 33 #if (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) && \ 34 (SANITIZER_WORDSIZE == 64) && \ 35 (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \ 36 defined(__powerpc64__)) 37 #define CAN_SANITIZE_LEAKS 1 38 #elif defined(__i386__) && \ 39 (SANITIZER_LINUX && !SANITIZER_ANDROID || SANITIZER_MAC) 40 #define CAN_SANITIZE_LEAKS 1 41 #elif defined(__arm__) && \ 42 SANITIZER_LINUX && !SANITIZER_ANDROID 43 #define CAN_SANITIZE_LEAKS 1 44 #else 45 #define CAN_SANITIZE_LEAKS 0 46 #endif 47 48 namespace __sanitizer { 49 class FlagParser; 50 class ThreadRegistry; 51 struct DTLS; 52 } 53 54 namespace __lsan { 55 56 // Chunk tags. 57 enum ChunkTag { 58 kDirectlyLeaked = 0, // default 59 kIndirectlyLeaked = 1, 60 kReachable = 2, 61 kIgnored = 3 62 }; 63 64 const u32 kInvalidTid = (u32) -1; 65 66 struct Flags { 67 #define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; 68 #include "lsan_flags.inc" 69 #undef LSAN_FLAG 70 71 void SetDefaults(); 72 uptr pointer_alignment() const { 73 return use_unaligned ? 1 : sizeof(uptr); 74 } 75 }; 76 77 extern Flags lsan_flags; 78 inline Flags *flags() { return &lsan_flags; } 79 void RegisterLsanFlags(FlagParser *parser, Flags *f); 80 81 struct Leak { 82 u32 id; 83 uptr hit_count; 84 uptr total_size; 85 u32 stack_trace_id; 86 bool is_directly_leaked; 87 bool is_suppressed; 88 }; 89 90 struct LeakedObject { 91 u32 leak_id; 92 uptr addr; 93 uptr size; 94 }; 95 96 // Aggregates leaks by stack trace prefix. 97 class LeakReport { 98 public: 99 LeakReport() {} 100 void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size, 101 ChunkTag tag); 102 void ReportTopLeaks(uptr max_leaks); 103 void PrintSummary(); 104 void ApplySuppressions(); 105 uptr UnsuppressedLeakCount(); 106 107 private: 108 void PrintReportForLeak(uptr index); 109 void PrintLeakedObjectsForLeak(uptr index); 110 111 u32 next_id_ = 0; 112 InternalMmapVector<Leak> leaks_; 113 InternalMmapVector<LeakedObject> leaked_objects_; 114 }; 115 116 typedef InternalMmapVector<uptr> Frontier; 117 118 // Platform-specific functions. 119 void InitializePlatformSpecificModules(); 120 void ProcessGlobalRegions(Frontier *frontier); 121 void ProcessPlatformSpecificAllocations(Frontier *frontier); 122 123 struct RootRegion { 124 uptr begin; 125 uptr size; 126 }; 127 128 InternalMmapVector<RootRegion> const *GetRootRegions(); 129 void ScanRootRegion(Frontier *frontier, RootRegion const ®ion, 130 uptr region_begin, uptr region_end, bool is_readable); 131 // Run stoptheworld while holding any platform-specific locks. 132 void DoStopTheWorld(StopTheWorldCallback callback, void* argument); 133 134 void ScanRangeForPointers(uptr begin, uptr end, 135 Frontier *frontier, 136 const char *region_type, ChunkTag tag); 137 void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier); 138 139 enum IgnoreObjectResult { 140 kIgnoreObjectSuccess, 141 kIgnoreObjectAlreadyIgnored, 142 kIgnoreObjectInvalid 143 }; 144 145 // Functions called from the parent tool. 146 const char *MaybeCallLsanDefaultOptions(); 147 void InitCommonLsan(); 148 void DoLeakCheck(); 149 void DoRecoverableLeakCheckVoid(); 150 void DisableCounterUnderflow(); 151 bool DisabledInThisThread(); 152 153 // Used to implement __lsan::ScopedDisabler. 154 void DisableInThisThread(); 155 void EnableInThisThread(); 156 // Can be used to ignore memory allocated by an intercepted 157 // function. 158 struct ScopedInterceptorDisabler { 159 ScopedInterceptorDisabler() { DisableInThisThread(); } 160 ~ScopedInterceptorDisabler() { EnableInThisThread(); } 161 }; 162 163 // According to Itanium C++ ABI array cookie is a one word containing 164 // size of allocated array. 165 static inline bool IsItaniumABIArrayCookie(uptr chunk_beg, uptr chunk_size, 166 uptr addr) { 167 return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr && 168 *reinterpret_cast<uptr *>(chunk_beg) == 0; 169 } 170 171 // According to ARM C++ ABI array cookie consists of two words: 172 // struct array_cookie { 173 // std::size_t element_size; // element_size != 0 174 // std::size_t element_count; 175 // }; 176 static inline bool IsARMABIArrayCookie(uptr chunk_beg, uptr chunk_size, 177 uptr addr) { 178 return chunk_size == 2 * sizeof(uptr) && chunk_beg + chunk_size == addr && 179 *reinterpret_cast<uptr *>(chunk_beg + sizeof(uptr)) == 0; 180 } 181 182 // Special case for "new T[0]" where T is a type with DTOR. 183 // new T[0] will allocate a cookie (one or two words) for the array size (0) 184 // and store a pointer to the end of allocated chunk. The actual cookie layout 185 // varies between platforms according to their C++ ABI implementation. 186 inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size, 187 uptr addr) { 188 #if defined(__arm__) 189 return IsARMABIArrayCookie(chunk_beg, chunk_size, addr); 190 #else 191 return IsItaniumABIArrayCookie(chunk_beg, chunk_size, addr); 192 #endif 193 } 194 195 // The following must be implemented in the parent tool. 196 197 void ForEachChunk(ForEachChunkCallback callback, void *arg); 198 // Returns the address range occupied by the global allocator object. 199 void GetAllocatorGlobalRange(uptr *begin, uptr *end); 200 // Wrappers for allocator's ForceLock()/ForceUnlock(). 201 void LockAllocator(); 202 void UnlockAllocator(); 203 // Returns true if [addr, addr + sizeof(void *)) is poisoned. 204 bool WordIsPoisoned(uptr addr); 205 // Wrappers for ThreadRegistry access. 206 void LockThreadRegistry(); 207 void UnlockThreadRegistry(); 208 ThreadRegistry *GetThreadRegistryLocked(); 209 bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, 210 uptr *tls_begin, uptr *tls_end, uptr *cache_begin, 211 uptr *cache_end, DTLS **dtls); 212 void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, 213 void *arg); 214 // If called from the main thread, updates the main thread's TID in the thread 215 // registry. We need this to handle processes that fork() without a subsequent 216 // exec(), which invalidates the recorded TID. To update it, we must call 217 // gettid() from the main thread. Our solution is to call this function before 218 // leak checking and also before every call to pthread_create() (to handle cases 219 // where leak checking is initiated from a non-main thread). 220 void EnsureMainThreadIDIsCorrect(); 221 // If p points into a chunk that has been allocated to the user, returns its 222 // user-visible address. Otherwise, returns 0. 223 uptr PointsIntoChunk(void *p); 224 // Returns address of user-visible chunk contained in this allocator chunk. 225 uptr GetUserBegin(uptr chunk); 226 // Helper for __lsan_ignore_object(). 227 IgnoreObjectResult IgnoreObjectLocked(const void *p); 228 229 // Return the linker module, if valid for the platform. 230 LoadedModule *GetLinker(); 231 232 // Return true if LSan has finished leak checking and reported leaks. 233 bool HasReportedLeaks(); 234 235 // Run platform-specific leak handlers. 236 void HandleLeaks(); 237 238 // Wrapper for chunk metadata operations. 239 class LsanMetadata { 240 public: 241 // Constructor accepts address of user-visible chunk. 242 explicit LsanMetadata(uptr chunk); 243 bool allocated() const; 244 ChunkTag tag() const; 245 void set_tag(ChunkTag value); 246 uptr requested_size() const; 247 u32 stack_trace_id() const; 248 private: 249 void *metadata_; 250 }; 251 252 } // namespace __lsan 253 254 extern "C" { 255 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 256 const char *__lsan_default_options(); 257 258 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 259 int __lsan_is_turned_off(); 260 261 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 262 const char *__lsan_default_suppressions(); 263 } // extern "C" 264 265 #endif // LSAN_COMMON_H 266