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