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