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_symbolizer.h" 23 24 #if SANITIZER_LINUX && defined(__x86_64__) && (SANITIZER_WORDSIZE == 64) 25 #define CAN_SANITIZE_LEAKS 1 26 #else 27 #define CAN_SANITIZE_LEAKS 0 28 #endif 29 30 namespace __lsan { 31 32 // Chunk tags. 33 enum ChunkTag { 34 kDirectlyLeaked = 0, // default 35 kIndirectlyLeaked = 1, 36 kReachable = 2, 37 kIgnored = 3 38 }; 39 40 struct Flags { 41 uptr pointer_alignment() const { 42 return use_unaligned ? 1 : sizeof(uptr); 43 } 44 45 // Print addresses of leaked objects after main leak report. 46 bool report_objects; 47 // Aggregate two objects into one leak if this many stack frames match. If 48 // zero, the entire stack trace must match. 49 int resolution; 50 // The number of leaks reported. 51 int max_leaks; 52 // If nonzero kill the process with this exit code upon finding leaks. 53 int exitcode; 54 // Print matched suppressions after leak checking. 55 bool print_suppressions; 56 // Suppressions file name. 57 const char* suppressions; 58 59 // Flags controlling the root set of reachable memory. 60 // Global variables (.data and .bss). 61 bool use_globals; 62 // Thread stacks. 63 bool use_stacks; 64 // Thread registers. 65 bool use_registers; 66 // TLS and thread-specific storage. 67 bool use_tls; 68 // Regions added via __lsan_register_root_region(). 69 bool use_root_regions; 70 71 // Consider unaligned pointers valid. 72 bool use_unaligned; 73 // Consider pointers found in poisoned memory to be valid. 74 bool use_poisoned; 75 76 // Debug logging. 77 bool log_pointers; 78 bool log_threads; 79 }; 80 81 extern Flags lsan_flags; 82 inline Flags *flags() { return &lsan_flags; } 83 84 struct Leak { 85 u32 id; 86 uptr hit_count; 87 uptr total_size; 88 u32 stack_trace_id; 89 bool is_directly_leaked; 90 bool is_suppressed; 91 }; 92 93 struct LeakedObject { 94 u32 leak_id; 95 uptr addr; 96 uptr size; 97 }; 98 99 // Aggregates leaks by stack trace prefix. 100 class LeakReport { 101 public: 102 LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {} 103 void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size, 104 ChunkTag tag); 105 void ReportTopLeaks(uptr max_leaks); 106 void PrintSummary(); 107 void ApplySuppressions(); 108 uptr UnsuppressedLeakCount(); 109 110 111 private: 112 void PrintReportForLeak(uptr index); 113 void PrintLeakedObjectsForLeak(uptr index); 114 115 u32 next_id_; 116 InternalMmapVector<Leak> leaks_; 117 InternalMmapVector<LeakedObject> leaked_objects_; 118 }; 119 120 typedef InternalMmapVector<uptr> Frontier; 121 122 // Platform-specific functions. 123 void InitializePlatformSpecificModules(); 124 void ProcessGlobalRegions(Frontier *frontier); 125 void ProcessPlatformSpecificAllocations(Frontier *frontier); 126 127 void ScanRangeForPointers(uptr begin, uptr end, 128 Frontier *frontier, 129 const char *region_type, ChunkTag tag); 130 131 enum IgnoreObjectResult { 132 kIgnoreObjectSuccess, 133 kIgnoreObjectAlreadyIgnored, 134 kIgnoreObjectInvalid 135 }; 136 137 // Functions called from the parent tool. 138 void InitCommonLsan(); 139 void DoLeakCheck(); 140 bool DisabledInThisThread(); 141 142 // Special case for "new T[0]" where T is a type with DTOR. 143 // new T[0] will allocate one word for the array size (0) and store a pointer 144 // to the end of allocated chunk. 145 inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size, 146 uptr addr) { 147 return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr && 148 *reinterpret_cast<uptr *>(chunk_beg) == 0; 149 } 150 151 // The following must be implemented in the parent tool. 152 153 void ForEachChunk(ForEachChunkCallback callback, void *arg); 154 // Returns the address range occupied by the global allocator object. 155 void GetAllocatorGlobalRange(uptr *begin, uptr *end); 156 // Wrappers for allocator's ForceLock()/ForceUnlock(). 157 void LockAllocator(); 158 void UnlockAllocator(); 159 // Returns true if [addr, addr + sizeof(void *)) is poisoned. 160 bool WordIsPoisoned(uptr addr); 161 // Wrappers for ThreadRegistry access. 162 void LockThreadRegistry(); 163 void UnlockThreadRegistry(); 164 bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 165 uptr *tls_begin, uptr *tls_end, 166 uptr *cache_begin, uptr *cache_end); 167 void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, 168 void *arg); 169 // If called from the main thread, updates the main thread's TID in the thread 170 // registry. We need this to handle processes that fork() without a subsequent 171 // exec(), which invalidates the recorded TID. To update it, we must call 172 // gettid() from the main thread. Our solution is to call this function before 173 // leak checking and also before every call to pthread_create() (to handle cases 174 // where leak checking is initiated from a non-main thread). 175 void EnsureMainThreadIDIsCorrect(); 176 // If p points into a chunk that has been allocated to the user, returns its 177 // user-visible address. Otherwise, returns 0. 178 uptr PointsIntoChunk(void *p); 179 // Returns address of user-visible chunk contained in this allocator chunk. 180 uptr GetUserBegin(uptr chunk); 181 // Helper for __lsan_ignore_object(). 182 IgnoreObjectResult IgnoreObjectLocked(const void *p); 183 // Wrapper for chunk metadata operations. 184 class LsanMetadata { 185 public: 186 // Constructor accepts address of user-visible chunk. 187 explicit LsanMetadata(uptr chunk); 188 bool allocated() const; 189 ChunkTag tag() const; 190 void set_tag(ChunkTag value); 191 uptr requested_size() const; 192 u32 stack_trace_id() const; 193 private: 194 void *metadata_; 195 }; 196 197 } // namespace __lsan 198 199 extern "C" { 200 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 201 int __lsan_is_turned_off(); 202 203 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 204 const char *__lsan_default_suppressions(); 205 } // extern "C" 206 207 #endif // LSAN_COMMON_H 208