Home | History | Annotate | Line # | Download | only in lsan
      1   1.1       mrg //=-- lsan_common.h -------------------------------------------------------===//
      2   1.1       mrg //
      3  1.11       mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.11       mrg // See https://llvm.org/LICENSE.txt for license information.
      5  1.11       mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6   1.1       mrg //
      7   1.1       mrg //===----------------------------------------------------------------------===//
      8   1.1       mrg //
      9   1.1       mrg // This file is a part of LeakSanitizer.
     10   1.1       mrg // Private LSan header.
     11   1.1       mrg //
     12   1.1       mrg //===----------------------------------------------------------------------===//
     13   1.1       mrg 
     14   1.1       mrg #ifndef LSAN_COMMON_H
     15   1.1       mrg #define LSAN_COMMON_H
     16   1.1       mrg 
     17   1.1       mrg #include "sanitizer_common/sanitizer_allocator.h"
     18   1.1       mrg #include "sanitizer_common/sanitizer_common.h"
     19   1.1       mrg #include "sanitizer_common/sanitizer_internal_defs.h"
     20   1.1       mrg #include "sanitizer_common/sanitizer_platform.h"
     21  1.12       mrg #include "sanitizer_common/sanitizer_range.h"
     22  1.11       mrg #include "sanitizer_common/sanitizer_stackdepot.h"
     23   1.2  christos #include "sanitizer_common/sanitizer_stoptheworld.h"
     24   1.1       mrg #include "sanitizer_common/sanitizer_symbolizer.h"
     25  1.12       mrg #include "sanitizer_common/sanitizer_thread_registry.h"
     26   1.1       mrg 
     27   1.8     kamil // LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) on Linux.
     28   1.8     kamil // Also, LSan doesn't like 32 bit architectures
     29   1.6       mrg // because of "small" (4 bytes) pointer size that leads to high false negative
     30   1.6       mrg // ratio on large leaks. But we still want to have it for some 32 bit arches
     31   1.6       mrg // (e.g. x86), see https://github.com/google/sanitizers/issues/403.
     32   1.7       mrg // To enable LeakSanitizer on a new architecture, one needs to implement the
     33   1.7       mrg // internal_clone function as well as (probably) adjust the TLS machinery for
     34   1.7       mrg // the new architecture inside the sanitizer library.
     35  1.11       mrg // Exclude leak-detection on arm32 for Android because `__aeabi_read_tp`
     36  1.11       mrg // is missing. This caused a link error.
     37  1.11       mrg #if SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__))
     38  1.12       mrg #  define CAN_SANITIZE_LEAKS 0
     39  1.12       mrg #elif (SANITIZER_LINUX || SANITIZER_APPLE) && (SANITIZER_WORDSIZE == 64) && \
     40  1.11       mrg     (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) ||  \
     41  1.11       mrg      defined(__powerpc64__) || defined(__s390x__))
     42  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     43  1.12       mrg #elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_APPLE)
     44  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     45  1.11       mrg #elif defined(__arm__) && SANITIZER_LINUX
     46  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     47  1.12       mrg #elif SANITIZER_LOONGARCH64 && SANITIZER_LINUX
     48  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     49  1.11       mrg #elif SANITIZER_RISCV64 && SANITIZER_LINUX
     50  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     51  1.11       mrg #elif SANITIZER_NETBSD || SANITIZER_FUCHSIA
     52  1.12       mrg #  define CAN_SANITIZE_LEAKS 1
     53   1.1       mrg #else
     54  1.12       mrg #  define CAN_SANITIZE_LEAKS 0
     55   1.1       mrg #endif
     56   1.1       mrg 
     57   1.2  christos namespace __sanitizer {
     58   1.2  christos class FlagParser;
     59   1.7       mrg class ThreadRegistry;
     60  1.11       mrg class ThreadContextBase;
     61   1.3       mrg struct DTLS;
     62   1.2  christos }
     63   1.2  christos 
     64  1.12       mrg // This section defines function and class prototypes which must be implemented
     65  1.12       mrg // by the parent tool linking in LSan. There are implementations provided by the
     66  1.12       mrg // LSan library which will be linked in when LSan is used as a standalone tool.
     67   1.1       mrg namespace __lsan {
     68   1.1       mrg 
     69   1.1       mrg // Chunk tags.
     70   1.1       mrg enum ChunkTag {
     71   1.1       mrg   kDirectlyLeaked = 0,  // default
     72   1.1       mrg   kIndirectlyLeaked = 1,
     73   1.1       mrg   kReachable = 2,
     74   1.1       mrg   kIgnored = 3
     75   1.1       mrg };
     76   1.1       mrg 
     77  1.12       mrg enum IgnoreObjectResult {
     78  1.12       mrg   kIgnoreObjectSuccess,
     79  1.12       mrg   kIgnoreObjectAlreadyIgnored,
     80  1.12       mrg   kIgnoreObjectInvalid
     81  1.12       mrg };
     82  1.12       mrg 
     83  1.12       mrg //// --------------------------------------------------------------------------
     84  1.12       mrg //// Poisoning prototypes.
     85  1.12       mrg //// --------------------------------------------------------------------------
     86  1.12       mrg 
     87  1.12       mrg // Returns true if [addr, addr + sizeof(void *)) is poisoned.
     88  1.12       mrg bool WordIsPoisoned(uptr addr);
     89  1.12       mrg 
     90  1.12       mrg //// --------------------------------------------------------------------------
     91  1.12       mrg //// Thread prototypes.
     92  1.12       mrg //// --------------------------------------------------------------------------
     93  1.12       mrg 
     94  1.12       mrg // Wrappers for ThreadRegistry access.
     95  1.12       mrg void LockThreads() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
     96  1.12       mrg void UnlockThreads() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
     97  1.12       mrg // If called from the main thread, updates the main thread's TID in the thread
     98  1.12       mrg // registry. We need this to handle processes that fork() without a subsequent
     99  1.12       mrg // exec(), which invalidates the recorded TID. To update it, we must call
    100  1.12       mrg // gettid() from the main thread. Our solution is to call this function before
    101  1.12       mrg // leak checking and also before every call to pthread_create() (to handle cases
    102  1.12       mrg // where leak checking is initiated from a non-main thread).
    103  1.12       mrg void EnsureMainThreadIDIsCorrect();
    104  1.12       mrg 
    105  1.12       mrg bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
    106  1.12       mrg                            uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
    107  1.12       mrg                            uptr *cache_end, DTLS **dtls);
    108  1.12       mrg void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches);
    109  1.12       mrg void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges);
    110  1.12       mrg void GetThreadExtraStackRangesLocked(tid_t os_id,
    111  1.12       mrg                                      InternalMmapVector<Range> *ranges);
    112  1.12       mrg void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs);
    113  1.12       mrg void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads);
    114  1.12       mrg 
    115  1.12       mrg //// --------------------------------------------------------------------------
    116  1.12       mrg //// Allocator prototypes.
    117  1.12       mrg //// --------------------------------------------------------------------------
    118  1.12       mrg 
    119  1.12       mrg // Wrappers for allocator's ForceLock()/ForceUnlock().
    120  1.12       mrg void LockAllocator();
    121  1.12       mrg void UnlockAllocator();
    122  1.12       mrg 
    123  1.12       mrg // Returns the address range occupied by the global allocator object.
    124  1.12       mrg void GetAllocatorGlobalRange(uptr *begin, uptr *end);
    125  1.12       mrg // If p points into a chunk that has been allocated to the user, returns its
    126  1.12       mrg // user-visible address. Otherwise, returns 0.
    127  1.12       mrg uptr PointsIntoChunk(void *p);
    128  1.12       mrg // Returns address of user-visible chunk contained in this allocator chunk.
    129  1.12       mrg uptr GetUserBegin(uptr chunk);
    130  1.12       mrg // Returns user-visible address for chunk. If memory tagging is used this
    131  1.12       mrg // function will return the tagged address.
    132  1.12       mrg uptr GetUserAddr(uptr chunk);
    133  1.12       mrg 
    134  1.12       mrg // Wrapper for chunk metadata operations.
    135  1.12       mrg class LsanMetadata {
    136  1.12       mrg  public:
    137  1.12       mrg   // Constructor accepts address of user-visible chunk.
    138  1.12       mrg   explicit LsanMetadata(uptr chunk);
    139  1.12       mrg   bool allocated() const;
    140  1.12       mrg   ChunkTag tag() const;
    141  1.12       mrg   void set_tag(ChunkTag value);
    142  1.12       mrg   uptr requested_size() const;
    143  1.12       mrg   u32 stack_trace_id() const;
    144  1.12       mrg 
    145  1.12       mrg  private:
    146  1.12       mrg   void *metadata_;
    147  1.12       mrg };
    148  1.12       mrg 
    149  1.12       mrg // Iterate over all existing chunks. Allocator must be locked.
    150  1.12       mrg void ForEachChunk(ForEachChunkCallback callback, void *arg);
    151  1.12       mrg 
    152  1.12       mrg // Helper for __lsan_ignore_object().
    153  1.12       mrg IgnoreObjectResult IgnoreObject(const void *p);
    154  1.12       mrg 
    155  1.12       mrg // The rest of the LSan interface which is implemented by library.
    156  1.12       mrg 
    157  1.12       mrg struct ScopedStopTheWorldLock {
    158  1.12       mrg   ScopedStopTheWorldLock() {
    159  1.12       mrg     LockThreads();
    160  1.12       mrg     LockAllocator();
    161  1.12       mrg   }
    162  1.12       mrg 
    163  1.12       mrg   ~ScopedStopTheWorldLock() {
    164  1.12       mrg     UnlockAllocator();
    165  1.12       mrg     UnlockThreads();
    166  1.12       mrg   }
    167  1.12       mrg 
    168  1.12       mrg   ScopedStopTheWorldLock &operator=(const ScopedStopTheWorldLock &) = delete;
    169  1.12       mrg   ScopedStopTheWorldLock(const ScopedStopTheWorldLock &) = delete;
    170  1.12       mrg };
    171  1.12       mrg 
    172   1.1       mrg struct Flags {
    173   1.2  christos #define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
    174   1.2  christos #include "lsan_flags.inc"
    175   1.2  christos #undef LSAN_FLAG
    176   1.2  christos 
    177   1.2  christos   void SetDefaults();
    178   1.1       mrg   uptr pointer_alignment() const {
    179   1.1       mrg     return use_unaligned ? 1 : sizeof(uptr);
    180   1.1       mrg   }
    181   1.1       mrg };
    182   1.1       mrg 
    183   1.1       mrg extern Flags lsan_flags;
    184   1.1       mrg inline Flags *flags() { return &lsan_flags; }
    185   1.2  christos void RegisterLsanFlags(FlagParser *parser, Flags *f);
    186   1.1       mrg 
    187  1.12       mrg struct LeakedChunk {
    188  1.12       mrg   uptr chunk;
    189  1.12       mrg   u32 stack_trace_id;
    190  1.12       mrg   uptr leaked_size;
    191  1.12       mrg   ChunkTag tag;
    192  1.12       mrg };
    193  1.12       mrg 
    194  1.12       mrg using LeakedChunks = InternalMmapVector<LeakedChunk>;
    195  1.12       mrg 
    196   1.1       mrg struct Leak {
    197   1.1       mrg   u32 id;
    198   1.1       mrg   uptr hit_count;
    199   1.1       mrg   uptr total_size;
    200   1.1       mrg   u32 stack_trace_id;
    201   1.1       mrg   bool is_directly_leaked;
    202   1.1       mrg   bool is_suppressed;
    203   1.1       mrg };
    204   1.1       mrg 
    205   1.1       mrg struct LeakedObject {
    206   1.1       mrg   u32 leak_id;
    207   1.1       mrg   uptr addr;
    208   1.1       mrg   uptr size;
    209   1.1       mrg };
    210   1.1       mrg 
    211   1.1       mrg // Aggregates leaks by stack trace prefix.
    212   1.1       mrg class LeakReport {
    213   1.1       mrg  public:
    214   1.7       mrg   LeakReport() {}
    215  1.12       mrg   void AddLeakedChunks(const LeakedChunks &chunks);
    216   1.1       mrg   void ReportTopLeaks(uptr max_leaks);
    217   1.1       mrg   void PrintSummary();
    218  1.11       mrg   uptr ApplySuppressions();
    219   1.1       mrg   uptr UnsuppressedLeakCount();
    220  1.11       mrg   uptr IndirectUnsuppressedLeakCount();
    221   1.1       mrg 
    222   1.1       mrg  private:
    223   1.1       mrg   void PrintReportForLeak(uptr index);
    224   1.1       mrg   void PrintLeakedObjectsForLeak(uptr index);
    225   1.1       mrg 
    226   1.7       mrg   u32 next_id_ = 0;
    227   1.1       mrg   InternalMmapVector<Leak> leaks_;
    228   1.1       mrg   InternalMmapVector<LeakedObject> leaked_objects_;
    229   1.1       mrg };
    230   1.1       mrg 
    231   1.1       mrg typedef InternalMmapVector<uptr> Frontier;
    232   1.1       mrg 
    233   1.1       mrg // Platform-specific functions.
    234   1.1       mrg void InitializePlatformSpecificModules();
    235   1.1       mrg void ProcessGlobalRegions(Frontier *frontier);
    236   1.1       mrg void ProcessPlatformSpecificAllocations(Frontier *frontier);
    237   1.6       mrg 
    238  1.11       mrg // LockStuffAndStopTheWorld can start to use Scan* calls to collect into
    239  1.11       mrg // this Frontier vector before the StopTheWorldCallback actually runs.
    240  1.11       mrg // This is used when the OS has a unified callback API for suspending
    241  1.11       mrg // threads and enumerating roots.
    242  1.11       mrg struct CheckForLeaksParam {
    243  1.11       mrg   Frontier frontier;
    244  1.12       mrg   LeakedChunks leaks;
    245  1.12       mrg   tid_t caller_tid;
    246  1.12       mrg   uptr caller_sp;
    247  1.11       mrg   bool success = false;
    248  1.11       mrg };
    249  1.11       mrg 
    250  1.12       mrg using Region = Range;
    251  1.12       mrg 
    252  1.12       mrg bool HasRootRegions();
    253  1.12       mrg void ScanRootRegions(Frontier *frontier,
    254  1.12       mrg                      const InternalMmapVectorNoCtor<Region> &region);
    255  1.11       mrg // Run stoptheworld while holding any platform-specific locks, as well as the
    256  1.11       mrg // allocator and thread registry locks.
    257  1.11       mrg void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
    258  1.11       mrg                               CheckForLeaksParam* argument);
    259   1.1       mrg 
    260   1.1       mrg void ScanRangeForPointers(uptr begin, uptr end,
    261   1.1       mrg                           Frontier *frontier,
    262   1.1       mrg                           const char *region_type, ChunkTag tag);
    263   1.6       mrg void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier);
    264  1.12       mrg void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
    265  1.12       mrg                           Frontier *frontier);
    266   1.1       mrg 
    267   1.1       mrg // Functions called from the parent tool.
    268   1.6       mrg const char *MaybeCallLsanDefaultOptions();
    269   1.2  christos void InitCommonLsan();
    270   1.1       mrg void DoLeakCheck();
    271   1.6       mrg void DoRecoverableLeakCheckVoid();
    272   1.6       mrg void DisableCounterUnderflow();
    273   1.1       mrg bool DisabledInThisThread();
    274   1.1       mrg 
    275   1.3       mrg // Used to implement __lsan::ScopedDisabler.
    276   1.3       mrg void DisableInThisThread();
    277   1.3       mrg void EnableInThisThread();
    278   1.3       mrg // Can be used to ignore memory allocated by an intercepted
    279   1.3       mrg // function.
    280   1.3       mrg struct ScopedInterceptorDisabler {
    281   1.3       mrg   ScopedInterceptorDisabler() { DisableInThisThread(); }
    282   1.3       mrg   ~ScopedInterceptorDisabler() { EnableInThisThread(); }
    283   1.3       mrg };
    284   1.3       mrg 
    285   1.6       mrg // According to Itanium C++ ABI array cookie is a one word containing
    286   1.6       mrg // size of allocated array.
    287   1.6       mrg static inline bool IsItaniumABIArrayCookie(uptr chunk_beg, uptr chunk_size,
    288   1.6       mrg                                            uptr addr) {
    289   1.6       mrg   return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
    290   1.6       mrg          *reinterpret_cast<uptr *>(chunk_beg) == 0;
    291   1.6       mrg }
    292   1.6       mrg 
    293   1.6       mrg // According to ARM C++ ABI array cookie consists of two words:
    294   1.6       mrg // struct array_cookie {
    295   1.6       mrg //   std::size_t element_size; // element_size != 0
    296   1.6       mrg //   std::size_t element_count;
    297   1.6       mrg // };
    298   1.6       mrg static inline bool IsARMABIArrayCookie(uptr chunk_beg, uptr chunk_size,
    299   1.6       mrg                                        uptr addr) {
    300   1.6       mrg   return chunk_size == 2 * sizeof(uptr) && chunk_beg + chunk_size == addr &&
    301   1.6       mrg          *reinterpret_cast<uptr *>(chunk_beg + sizeof(uptr)) == 0;
    302   1.6       mrg }
    303   1.6       mrg 
    304   1.1       mrg // Special case for "new T[0]" where T is a type with DTOR.
    305   1.6       mrg // new T[0] will allocate a cookie (one or two words) for the array size (0)
    306   1.6       mrg // and store a pointer to the end of allocated chunk. The actual cookie layout
    307   1.6       mrg // varies between platforms according to their C++ ABI implementation.
    308   1.1       mrg inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
    309   1.1       mrg                                         uptr addr) {
    310   1.6       mrg #if defined(__arm__)
    311   1.6       mrg   return IsARMABIArrayCookie(chunk_beg, chunk_size, addr);
    312   1.6       mrg #else
    313   1.6       mrg   return IsItaniumABIArrayCookie(chunk_beg, chunk_size, addr);
    314   1.6       mrg #endif
    315   1.1       mrg }
    316   1.1       mrg 
    317   1.6       mrg // Return the linker module, if valid for the platform.
    318   1.6       mrg LoadedModule *GetLinker();
    319   1.6       mrg 
    320   1.6       mrg // Return true if LSan has finished leak checking and reported leaks.
    321   1.6       mrg bool HasReportedLeaks();
    322   1.6       mrg 
    323   1.6       mrg // Run platform-specific leak handlers.
    324   1.6       mrg void HandleLeaks();
    325   1.6       mrg 
    326   1.1       mrg }  // namespace __lsan
    327   1.1       mrg 
    328   1.1       mrg extern "C" {
    329   1.1       mrg SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    330   1.6       mrg const char *__lsan_default_options();
    331   1.6       mrg 
    332   1.6       mrg SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    333   1.1       mrg int __lsan_is_turned_off();
    334   1.1       mrg 
    335   1.1       mrg SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    336   1.1       mrg const char *__lsan_default_suppressions();
    337  1.11       mrg 
    338  1.11       mrg SANITIZER_INTERFACE_ATTRIBUTE
    339  1.11       mrg void __lsan_register_root_region(const void *p, __lsan::uptr size);
    340  1.11       mrg 
    341  1.11       mrg SANITIZER_INTERFACE_ATTRIBUTE
    342  1.11       mrg void __lsan_unregister_root_region(const void *p, __lsan::uptr size);
    343  1.11       mrg 
    344   1.1       mrg }  // extern "C"
    345   1.1       mrg 
    346   1.1       mrg #endif  // LSAN_COMMON_H
    347