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 30namespace __lsan { 31 32// Chunk tags. 33enum ChunkTag { 34 kDirectlyLeaked = 0, // default 35 kIndirectlyLeaked = 1, 36 kReachable = 2, 37 kIgnored = 3 38}; 39 40struct 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 81extern Flags lsan_flags; 82inline Flags *flags() { return &lsan_flags; } 83 84struct 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 93struct LeakedObject { 94 u32 leak_id; 95 uptr addr; 96 uptr size; 97}; 98 99// Aggregates leaks by stack trace prefix. 100class 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 120typedef InternalMmapVector<uptr> Frontier; 121 122// Platform-specific functions. 123void InitializePlatformSpecificModules(); 124void ProcessGlobalRegions(Frontier *frontier); 125void ProcessPlatformSpecificAllocations(Frontier *frontier); 126 127void ScanRangeForPointers(uptr begin, uptr end, 128 Frontier *frontier, 129 const char *region_type, ChunkTag tag); 130 131enum IgnoreObjectResult { 132 kIgnoreObjectSuccess, 133 kIgnoreObjectAlreadyIgnored, 134 kIgnoreObjectInvalid 135}; 136 137// Functions called from the parent tool. 138void InitCommonLsan(); 139void DoLeakCheck(); 140bool 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. 145inline 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 153void ForEachChunk(ForEachChunkCallback callback, void *arg); 154// Returns the address range occupied by the global allocator object. 155void GetAllocatorGlobalRange(uptr *begin, uptr *end); 156// Wrappers for allocator's ForceLock()/ForceUnlock(). 157void LockAllocator(); 158void UnlockAllocator(); 159// Returns true if [addr, addr + sizeof(void *)) is poisoned. 160bool WordIsPoisoned(uptr addr); 161// Wrappers for ThreadRegistry access. 162void LockThreadRegistry(); 163void UnlockThreadRegistry(); 164bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 165 uptr *tls_begin, uptr *tls_end, 166 uptr *cache_begin, uptr *cache_end); 167void 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). 175void EnsureMainThreadIDIsCorrect(); 176// If p points into a chunk that has been allocated to the user, returns its 177// user-visible address. Otherwise, returns 0. 178uptr PointsIntoChunk(void *p); 179// Returns address of user-visible chunk contained in this allocator chunk. 180uptr GetUserBegin(uptr chunk); 181// Helper for __lsan_ignore_object(). 182IgnoreObjectResult IgnoreObjectLocked(const void *p); 183// Wrapper for chunk metadata operations. 184class 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 199extern "C" { 200SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 201int __lsan_is_turned_off(); 202 203SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 204const char *__lsan_default_suppressions(); 205} // extern "C" 206 207#endif // LSAN_COMMON_H 208