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 28namespace __lsan { 29 30// Chunk tags. 31enum ChunkTag { 32 kDirectlyLeaked = 0, // default 33 kIndirectlyLeaked = 1, 34 kReachable = 2, 35 kIgnored = 3 36}; 37 38struct 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 75extern Flags lsan_flags; 76inline Flags *flags() { return &lsan_flags; } 77 78struct 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 87struct LeakedObject { 88 u32 leak_id; 89 uptr addr; 90 uptr size; 91}; 92 93// Aggregates leaks by stack trace prefix. 94class 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 114typedef InternalMmapVector<uptr> Frontier; 115 116// Platform-specific functions. 117void InitializePlatformSpecificModules(); 118void ProcessGlobalRegions(Frontier *frontier); 119void ProcessPlatformSpecificAllocations(Frontier *frontier); 120 121void ScanRangeForPointers(uptr begin, uptr end, 122 Frontier *frontier, 123 const char *region_type, ChunkTag tag); 124 125enum IgnoreObjectResult { 126 kIgnoreObjectSuccess, 127 kIgnoreObjectAlreadyIgnored, 128 kIgnoreObjectInvalid 129}; 130 131// Functions called from the parent tool. 132void InitCommonLsan(bool standalone); 133void DoLeakCheck(); 134bool 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. 139inline 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 147void ForEachChunk(ForEachChunkCallback callback, void *arg); 148// Returns the address range occupied by the global allocator object. 149void GetAllocatorGlobalRange(uptr *begin, uptr *end); 150// Wrappers for allocator's ForceLock()/ForceUnlock(). 151void LockAllocator(); 152void UnlockAllocator(); 153// Returns true if [addr, addr + sizeof(void *)) is poisoned. 154bool WordIsPoisoned(uptr addr); 155// Wrappers for ThreadRegistry access. 156void LockThreadRegistry(); 157void UnlockThreadRegistry(); 158bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 159 uptr *tls_begin, uptr *tls_end, 160 uptr *cache_begin, uptr *cache_end); 161void 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). 169void EnsureMainThreadIDIsCorrect(); 170// If p points into a chunk that has been allocated to the user, returns its 171// user-visible address. Otherwise, returns 0. 172uptr PointsIntoChunk(void *p); 173// Returns address of user-visible chunk contained in this allocator chunk. 174uptr GetUserBegin(uptr chunk); 175// Helper for __lsan_ignore_object(). 176IgnoreObjectResult IgnoreObjectLocked(const void *p); 177// Wrapper for chunk metadata operations. 178class 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 193extern "C" { 194SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 195int __lsan_is_turned_off(); 196 197SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 198const char *__lsan_default_suppressions(); 199} // extern "C" 200 201#endif // LSAN_COMMON_H 202