Home | History | Annotate | Download | only in lsan
      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 #if (SANITIZER_LINUX && !SANITIZER_ANDROID) && (SANITIZER_WORDSIZE == 64) \
     26      && (defined(__x86_64__) ||  defined(__mips64) ||  defined(__aarch64__))
     27 #define CAN_SANITIZE_LEAKS 1
     28 #else
     29 #define CAN_SANITIZE_LEAKS 0
     30 #endif
     31 
     32 namespace __sanitizer {
     33 class FlagParser;
     34 struct DTLS;
     35 }
     36 
     37 namespace __lsan {
     38 
     39 // Chunk tags.
     40 enum ChunkTag {
     41   kDirectlyLeaked = 0,  // default
     42   kIndirectlyLeaked = 1,
     43   kReachable = 2,
     44   kIgnored = 3
     45 };
     46 
     47 struct Flags {
     48 #define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
     49 #include "lsan_flags.inc"
     50 #undef LSAN_FLAG
     51 
     52   void SetDefaults();
     53   uptr pointer_alignment() const {
     54     return use_unaligned ? 1 : sizeof(uptr);
     55   }
     56 };
     57 
     58 extern Flags lsan_flags;
     59 inline Flags *flags() { return &lsan_flags; }
     60 void RegisterLsanFlags(FlagParser *parser, Flags *f);
     61 
     62 struct Leak {
     63   u32 id;
     64   uptr hit_count;
     65   uptr total_size;
     66   u32 stack_trace_id;
     67   bool is_directly_leaked;
     68   bool is_suppressed;
     69 };
     70 
     71 struct LeakedObject {
     72   u32 leak_id;
     73   uptr addr;
     74   uptr size;
     75 };
     76 
     77 // Aggregates leaks by stack trace prefix.
     78 class LeakReport {
     79  public:
     80   LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {}
     81   void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size,
     82                       ChunkTag tag);
     83   void ReportTopLeaks(uptr max_leaks);
     84   void PrintSummary();
     85   void ApplySuppressions();
     86   uptr UnsuppressedLeakCount();
     87 
     88 
     89  private:
     90   void PrintReportForLeak(uptr index);
     91   void PrintLeakedObjectsForLeak(uptr index);
     92 
     93   u32 next_id_;
     94   InternalMmapVector<Leak> leaks_;
     95   InternalMmapVector<LeakedObject> leaked_objects_;
     96 };
     97 
     98 typedef InternalMmapVector<uptr> Frontier;
     99 
    100 // Platform-specific functions.
    101 void InitializePlatformSpecificModules();
    102 void ProcessGlobalRegions(Frontier *frontier);
    103 void ProcessPlatformSpecificAllocations(Frontier *frontier);
    104 // Run stoptheworld while holding any platform-specific locks.
    105 void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
    106 
    107 void ScanRangeForPointers(uptr begin, uptr end,
    108                           Frontier *frontier,
    109                           const char *region_type, ChunkTag tag);
    110 
    111 enum IgnoreObjectResult {
    112   kIgnoreObjectSuccess,
    113   kIgnoreObjectAlreadyIgnored,
    114   kIgnoreObjectInvalid
    115 };
    116 
    117 // Functions called from the parent tool.
    118 void InitCommonLsan();
    119 void DoLeakCheck();
    120 bool DisabledInThisThread();
    121 
    122 // Used to implement __lsan::ScopedDisabler.
    123 void DisableInThisThread();
    124 void EnableInThisThread();
    125 // Can be used to ignore memory allocated by an intercepted
    126 // function.
    127 struct ScopedInterceptorDisabler {
    128   ScopedInterceptorDisabler() { DisableInThisThread(); }
    129   ~ScopedInterceptorDisabler() { EnableInThisThread(); }
    130 };
    131 
    132 // Special case for "new T[0]" where T is a type with DTOR.
    133 // new T[0] will allocate one word for the array size (0) and store a pointer
    134 // to the end of allocated chunk.
    135 inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
    136                                         uptr addr) {
    137   return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
    138          *reinterpret_cast<uptr *>(chunk_beg) == 0;
    139 }
    140 
    141 // The following must be implemented in the parent tool.
    142 
    143 void ForEachChunk(ForEachChunkCallback callback, void *arg);
    144 // Returns the address range occupied by the global allocator object.
    145 void GetAllocatorGlobalRange(uptr *begin, uptr *end);
    146 // Wrappers for allocator's ForceLock()/ForceUnlock().
    147 void LockAllocator();
    148 void UnlockAllocator();
    149 // Returns true if [addr, addr + sizeof(void *)) is poisoned.
    150 bool WordIsPoisoned(uptr addr);
    151 // Wrappers for ThreadRegistry access.
    152 void LockThreadRegistry();
    153 void UnlockThreadRegistry();
    154 bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
    155                            uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
    156                            uptr *cache_end, DTLS **dtls);
    157 void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
    158                             void *arg);
    159 // If called from the main thread, updates the main thread's TID in the thread
    160 // registry. We need this to handle processes that fork() without a subsequent
    161 // exec(), which invalidates the recorded TID. To update it, we must call
    162 // gettid() from the main thread. Our solution is to call this function before
    163 // leak checking and also before every call to pthread_create() (to handle cases
    164 // where leak checking is initiated from a non-main thread).
    165 void EnsureMainThreadIDIsCorrect();
    166 // If p points into a chunk that has been allocated to the user, returns its
    167 // user-visible address. Otherwise, returns 0.
    168 uptr PointsIntoChunk(void *p);
    169 // Returns address of user-visible chunk contained in this allocator chunk.
    170 uptr GetUserBegin(uptr chunk);
    171 // Helper for __lsan_ignore_object().
    172 IgnoreObjectResult IgnoreObjectLocked(const void *p);
    173 // Wrapper for chunk metadata operations.
    174 class LsanMetadata {
    175  public:
    176   // Constructor accepts address of user-visible chunk.
    177   explicit LsanMetadata(uptr chunk);
    178   bool allocated() const;
    179   ChunkTag tag() const;
    180   void set_tag(ChunkTag value);
    181   uptr requested_size() const;
    182   u32 stack_trace_id() const;
    183  private:
    184   void *metadata_;
    185 };
    186 
    187 }  // namespace __lsan
    188 
    189 extern "C" {
    190 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    191 int __lsan_is_turned_off();
    192 
    193 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    194 const char *__lsan_default_suppressions();
    195 }  // extern "C"
    196 
    197 #endif  // LSAN_COMMON_H
    198