xref: /openbsd-src/gnu/llvm/compiler-rt/lib/lsan/lsan_common.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //=-- lsan_common.h -------------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of LeakSanitizer.
103cab2bb3Spatrick // Private LSan header.
113cab2bb3Spatrick //
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick 
143cab2bb3Spatrick #ifndef LSAN_COMMON_H
153cab2bb3Spatrick #define LSAN_COMMON_H
163cab2bb3Spatrick 
173cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator.h"
183cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
193cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
203cab2bb3Spatrick #include "sanitizer_common/sanitizer_platform.h"
21*810390e3Srobert #include "sanitizer_common/sanitizer_stackdepot.h"
223cab2bb3Spatrick #include "sanitizer_common/sanitizer_stoptheworld.h"
233cab2bb3Spatrick #include "sanitizer_common/sanitizer_symbolizer.h"
24*810390e3Srobert #include "sanitizer_common/sanitizer_thread_registry.h"
253cab2bb3Spatrick 
263cab2bb3Spatrick // LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) on Linux.
273cab2bb3Spatrick // Also, LSan doesn't like 32 bit architectures
283cab2bb3Spatrick // because of "small" (4 bytes) pointer size that leads to high false negative
293cab2bb3Spatrick // ratio on large leaks. But we still want to have it for some 32 bit arches
303cab2bb3Spatrick // (e.g. x86), see https://github.com/google/sanitizers/issues/403.
313cab2bb3Spatrick // To enable LeakSanitizer on a new architecture, one needs to implement the
323cab2bb3Spatrick // internal_clone function as well as (probably) adjust the TLS machinery for
333cab2bb3Spatrick // the new architecture inside the sanitizer library.
34d89ec533Spatrick // Exclude leak-detection on arm32 for Android because `__aeabi_read_tp`
35d89ec533Spatrick // is missing. This caused a link error.
36d89ec533Spatrick #if SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__))
37d89ec533Spatrick #  define CAN_SANITIZE_LEAKS 0
38*810390e3Srobert #elif (SANITIZER_LINUX || SANITIZER_APPLE) && (SANITIZER_WORDSIZE == 64) && \
393cab2bb3Spatrick     (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) ||  \
401f9cb04fSpatrick      defined(__powerpc64__) || defined(__s390x__))
413cab2bb3Spatrick #  define CAN_SANITIZE_LEAKS 1
42*810390e3Srobert #elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_APPLE)
433cab2bb3Spatrick #  define CAN_SANITIZE_LEAKS 1
44d89ec533Spatrick #elif defined(__arm__) && SANITIZER_LINUX
45d89ec533Spatrick #  define CAN_SANITIZE_LEAKS 1
46*810390e3Srobert #elif SANITIZER_LOONGARCH64 && SANITIZER_LINUX
47*810390e3Srobert #  define CAN_SANITIZE_LEAKS 1
48d89ec533Spatrick #elif SANITIZER_RISCV64 && SANITIZER_LINUX
493cab2bb3Spatrick #  define CAN_SANITIZE_LEAKS 1
501f9cb04fSpatrick #elif SANITIZER_NETBSD || SANITIZER_FUCHSIA
513cab2bb3Spatrick #  define CAN_SANITIZE_LEAKS 1
523cab2bb3Spatrick #else
533cab2bb3Spatrick #  define CAN_SANITIZE_LEAKS 0
543cab2bb3Spatrick #endif
553cab2bb3Spatrick 
563cab2bb3Spatrick namespace __sanitizer {
573cab2bb3Spatrick class FlagParser;
583cab2bb3Spatrick class ThreadRegistry;
59d89ec533Spatrick class ThreadContextBase;
603cab2bb3Spatrick struct DTLS;
613cab2bb3Spatrick }
623cab2bb3Spatrick 
63*810390e3Srobert // This section defines function and class prototypes which must be implemented
64*810390e3Srobert // by the parent tool linking in LSan. There are implementations provided by the
65*810390e3Srobert // LSan library which will be linked in when LSan is used as a standalone tool.
663cab2bb3Spatrick namespace __lsan {
673cab2bb3Spatrick 
683cab2bb3Spatrick // Chunk tags.
693cab2bb3Spatrick enum ChunkTag {
703cab2bb3Spatrick   kDirectlyLeaked = 0,  // default
713cab2bb3Spatrick   kIndirectlyLeaked = 1,
723cab2bb3Spatrick   kReachable = 2,
733cab2bb3Spatrick   kIgnored = 3
743cab2bb3Spatrick };
753cab2bb3Spatrick 
76*810390e3Srobert enum IgnoreObjectResult {
77*810390e3Srobert   kIgnoreObjectSuccess,
78*810390e3Srobert   kIgnoreObjectAlreadyIgnored,
79*810390e3Srobert   kIgnoreObjectInvalid
80*810390e3Srobert };
81*810390e3Srobert 
82*810390e3Srobert struct Range {
83*810390e3Srobert   uptr begin;
84*810390e3Srobert   uptr end;
85*810390e3Srobert };
86*810390e3Srobert 
87*810390e3Srobert //// --------------------------------------------------------------------------
88*810390e3Srobert //// Poisoning prototypes.
89*810390e3Srobert //// --------------------------------------------------------------------------
90*810390e3Srobert 
91*810390e3Srobert // Returns true if [addr, addr + sizeof(void *)) is poisoned.
92*810390e3Srobert bool WordIsPoisoned(uptr addr);
93*810390e3Srobert 
94*810390e3Srobert //// --------------------------------------------------------------------------
95*810390e3Srobert //// Thread prototypes.
96*810390e3Srobert //// --------------------------------------------------------------------------
97*810390e3Srobert 
98*810390e3Srobert // Wrappers for ThreadRegistry access.
99*810390e3Srobert void LockThreadRegistry() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
100*810390e3Srobert void UnlockThreadRegistry() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
101*810390e3Srobert // If called from the main thread, updates the main thread's TID in the thread
102*810390e3Srobert // registry. We need this to handle processes that fork() without a subsequent
103*810390e3Srobert // exec(), which invalidates the recorded TID. To update it, we must call
104*810390e3Srobert // gettid() from the main thread. Our solution is to call this function before
105*810390e3Srobert // leak checking and also before every call to pthread_create() (to handle cases
106*810390e3Srobert // where leak checking is initiated from a non-main thread).
107*810390e3Srobert void EnsureMainThreadIDIsCorrect();
108*810390e3Srobert 
109*810390e3Srobert bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
110*810390e3Srobert                            uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
111*810390e3Srobert                            uptr *cache_end, DTLS **dtls);
112*810390e3Srobert void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches);
113*810390e3Srobert void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges);
114*810390e3Srobert void GetThreadExtraStackRangesLocked(tid_t os_id,
115*810390e3Srobert                                      InternalMmapVector<Range> *ranges);
116*810390e3Srobert void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs);
117*810390e3Srobert void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads);
118*810390e3Srobert 
119*810390e3Srobert //// --------------------------------------------------------------------------
120*810390e3Srobert //// Allocator prototypes.
121*810390e3Srobert //// --------------------------------------------------------------------------
122*810390e3Srobert 
123*810390e3Srobert // Wrappers for allocator's ForceLock()/ForceUnlock().
124*810390e3Srobert void LockAllocator();
125*810390e3Srobert void UnlockAllocator();
126*810390e3Srobert 
127*810390e3Srobert // Returns the address range occupied by the global allocator object.
128*810390e3Srobert void GetAllocatorGlobalRange(uptr *begin, uptr *end);
129*810390e3Srobert // If p points into a chunk that has been allocated to the user, returns its
130*810390e3Srobert // user-visible address. Otherwise, returns 0.
131*810390e3Srobert uptr PointsIntoChunk(void *p);
132*810390e3Srobert // Returns address of user-visible chunk contained in this allocator chunk.
133*810390e3Srobert uptr GetUserBegin(uptr chunk);
134*810390e3Srobert 
135*810390e3Srobert // Wrapper for chunk metadata operations.
136*810390e3Srobert class LsanMetadata {
137*810390e3Srobert  public:
138*810390e3Srobert   // Constructor accepts address of user-visible chunk.
139*810390e3Srobert   explicit LsanMetadata(uptr chunk);
140*810390e3Srobert   bool allocated() const;
141*810390e3Srobert   ChunkTag tag() const;
142*810390e3Srobert   void set_tag(ChunkTag value);
143*810390e3Srobert   uptr requested_size() const;
144*810390e3Srobert   u32 stack_trace_id() const;
145*810390e3Srobert 
146*810390e3Srobert  private:
147*810390e3Srobert   void *metadata_;
148*810390e3Srobert };
149*810390e3Srobert 
150*810390e3Srobert // Iterate over all existing chunks. Allocator must be locked.
151*810390e3Srobert void ForEachChunk(ForEachChunkCallback callback, void *arg);
152*810390e3Srobert 
153*810390e3Srobert // Helper for __lsan_ignore_object().
154*810390e3Srobert IgnoreObjectResult IgnoreObjectLocked(const void *p);
155*810390e3Srobert 
156*810390e3Srobert // The rest of the LSan interface which is implemented by library.
157*810390e3Srobert 
158*810390e3Srobert struct ScopedStopTheWorldLock {
ScopedStopTheWorldLockScopedStopTheWorldLock159*810390e3Srobert   ScopedStopTheWorldLock() {
160*810390e3Srobert     LockThreadRegistry();
161*810390e3Srobert     LockAllocator();
162*810390e3Srobert   }
163*810390e3Srobert 
~ScopedStopTheWorldLockScopedStopTheWorldLock164*810390e3Srobert   ~ScopedStopTheWorldLock() {
165*810390e3Srobert     UnlockAllocator();
166*810390e3Srobert     UnlockThreadRegistry();
167*810390e3Srobert   }
168*810390e3Srobert 
169*810390e3Srobert   ScopedStopTheWorldLock &operator=(const ScopedStopTheWorldLock &) = delete;
170*810390e3Srobert   ScopedStopTheWorldLock(const ScopedStopTheWorldLock &) = delete;
171*810390e3Srobert };
172*810390e3Srobert 
1733cab2bb3Spatrick struct Flags {
1743cab2bb3Spatrick #define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
1753cab2bb3Spatrick #include "lsan_flags.inc"
1763cab2bb3Spatrick #undef LSAN_FLAG
1773cab2bb3Spatrick 
1783cab2bb3Spatrick   void SetDefaults();
pointer_alignmentFlags1793cab2bb3Spatrick   uptr pointer_alignment() const {
1803cab2bb3Spatrick     return use_unaligned ? 1 : sizeof(uptr);
1813cab2bb3Spatrick   }
1823cab2bb3Spatrick };
1833cab2bb3Spatrick 
1843cab2bb3Spatrick extern Flags lsan_flags;
flags()1853cab2bb3Spatrick inline Flags *flags() { return &lsan_flags; }
1863cab2bb3Spatrick void RegisterLsanFlags(FlagParser *parser, Flags *f);
1873cab2bb3Spatrick 
188*810390e3Srobert struct LeakedChunk {
189*810390e3Srobert   uptr chunk;
190*810390e3Srobert   u32 stack_trace_id;
191*810390e3Srobert   uptr leaked_size;
192*810390e3Srobert   ChunkTag tag;
193*810390e3Srobert };
194*810390e3Srobert 
195*810390e3Srobert using LeakedChunks = InternalMmapVector<LeakedChunk>;
196*810390e3Srobert 
1973cab2bb3Spatrick struct Leak {
1983cab2bb3Spatrick   u32 id;
1993cab2bb3Spatrick   uptr hit_count;
2003cab2bb3Spatrick   uptr total_size;
2013cab2bb3Spatrick   u32 stack_trace_id;
2023cab2bb3Spatrick   bool is_directly_leaked;
2033cab2bb3Spatrick   bool is_suppressed;
2043cab2bb3Spatrick };
2053cab2bb3Spatrick 
2063cab2bb3Spatrick struct LeakedObject {
2073cab2bb3Spatrick   u32 leak_id;
2083cab2bb3Spatrick   uptr addr;
2093cab2bb3Spatrick   uptr size;
2103cab2bb3Spatrick };
2113cab2bb3Spatrick 
2123cab2bb3Spatrick // Aggregates leaks by stack trace prefix.
2133cab2bb3Spatrick class LeakReport {
2143cab2bb3Spatrick  public:
LeakReport()2153cab2bb3Spatrick   LeakReport() {}
216*810390e3Srobert   void AddLeakedChunks(const LeakedChunks &chunks);
2173cab2bb3Spatrick   void ReportTopLeaks(uptr max_leaks);
2183cab2bb3Spatrick   void PrintSummary();
219d89ec533Spatrick   uptr ApplySuppressions();
2203cab2bb3Spatrick   uptr UnsuppressedLeakCount();
221d89ec533Spatrick   uptr IndirectUnsuppressedLeakCount();
2223cab2bb3Spatrick 
2233cab2bb3Spatrick  private:
2243cab2bb3Spatrick   void PrintReportForLeak(uptr index);
2253cab2bb3Spatrick   void PrintLeakedObjectsForLeak(uptr index);
2263cab2bb3Spatrick 
2273cab2bb3Spatrick   u32 next_id_ = 0;
2283cab2bb3Spatrick   InternalMmapVector<Leak> leaks_;
2293cab2bb3Spatrick   InternalMmapVector<LeakedObject> leaked_objects_;
2303cab2bb3Spatrick };
2313cab2bb3Spatrick 
2323cab2bb3Spatrick typedef InternalMmapVector<uptr> Frontier;
2333cab2bb3Spatrick 
2343cab2bb3Spatrick // Platform-specific functions.
2353cab2bb3Spatrick void InitializePlatformSpecificModules();
2363cab2bb3Spatrick void ProcessGlobalRegions(Frontier *frontier);
2373cab2bb3Spatrick void ProcessPlatformSpecificAllocations(Frontier *frontier);
2383cab2bb3Spatrick 
2393cab2bb3Spatrick struct RootRegion {
2403cab2bb3Spatrick   uptr begin;
2413cab2bb3Spatrick   uptr size;
2423cab2bb3Spatrick };
2433cab2bb3Spatrick 
2441f9cb04fSpatrick // LockStuffAndStopTheWorld can start to use Scan* calls to collect into
2451f9cb04fSpatrick // this Frontier vector before the StopTheWorldCallback actually runs.
2461f9cb04fSpatrick // This is used when the OS has a unified callback API for suspending
2471f9cb04fSpatrick // threads and enumerating roots.
2481f9cb04fSpatrick struct CheckForLeaksParam {
2491f9cb04fSpatrick   Frontier frontier;
250*810390e3Srobert   LeakedChunks leaks;
251*810390e3Srobert   tid_t caller_tid;
252*810390e3Srobert   uptr caller_sp;
2531f9cb04fSpatrick   bool success = false;
2541f9cb04fSpatrick };
2551f9cb04fSpatrick 
256*810390e3Srobert InternalMmapVectorNoCtor<RootRegion> const *GetRootRegions();
2573cab2bb3Spatrick void ScanRootRegion(Frontier *frontier, RootRegion const &region,
2583cab2bb3Spatrick                     uptr region_begin, uptr region_end, bool is_readable);
2593cab2bb3Spatrick // Run stoptheworld while holding any platform-specific locks, as well as the
2603cab2bb3Spatrick // allocator and thread registry locks.
2611f9cb04fSpatrick void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
2621f9cb04fSpatrick                               CheckForLeaksParam* argument);
2633cab2bb3Spatrick 
2643cab2bb3Spatrick void ScanRangeForPointers(uptr begin, uptr end,
2653cab2bb3Spatrick                           Frontier *frontier,
2663cab2bb3Spatrick                           const char *region_type, ChunkTag tag);
2673cab2bb3Spatrick void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier);
268*810390e3Srobert void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
269*810390e3Srobert                           Frontier *frontier);
2703cab2bb3Spatrick 
2713cab2bb3Spatrick // Functions called from the parent tool.
2723cab2bb3Spatrick const char *MaybeCallLsanDefaultOptions();
2733cab2bb3Spatrick void InitCommonLsan();
2743cab2bb3Spatrick void DoLeakCheck();
2753cab2bb3Spatrick void DoRecoverableLeakCheckVoid();
2763cab2bb3Spatrick void DisableCounterUnderflow();
2773cab2bb3Spatrick bool DisabledInThisThread();
2783cab2bb3Spatrick 
2793cab2bb3Spatrick // Used to implement __lsan::ScopedDisabler.
2803cab2bb3Spatrick void DisableInThisThread();
2813cab2bb3Spatrick void EnableInThisThread();
2823cab2bb3Spatrick // Can be used to ignore memory allocated by an intercepted
2833cab2bb3Spatrick // function.
2843cab2bb3Spatrick struct ScopedInterceptorDisabler {
ScopedInterceptorDisablerScopedInterceptorDisabler2853cab2bb3Spatrick   ScopedInterceptorDisabler() { DisableInThisThread(); }
~ScopedInterceptorDisablerScopedInterceptorDisabler2863cab2bb3Spatrick   ~ScopedInterceptorDisabler() { EnableInThisThread(); }
2873cab2bb3Spatrick };
2883cab2bb3Spatrick 
2893cab2bb3Spatrick // According to Itanium C++ ABI array cookie is a one word containing
2903cab2bb3Spatrick // size of allocated array.
IsItaniumABIArrayCookie(uptr chunk_beg,uptr chunk_size,uptr addr)2913cab2bb3Spatrick static inline bool IsItaniumABIArrayCookie(uptr chunk_beg, uptr chunk_size,
2923cab2bb3Spatrick                                            uptr addr) {
2933cab2bb3Spatrick   return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
2943cab2bb3Spatrick          *reinterpret_cast<uptr *>(chunk_beg) == 0;
2953cab2bb3Spatrick }
2963cab2bb3Spatrick 
2973cab2bb3Spatrick // According to ARM C++ ABI array cookie consists of two words:
2983cab2bb3Spatrick // struct array_cookie {
2993cab2bb3Spatrick //   std::size_t element_size; // element_size != 0
3003cab2bb3Spatrick //   std::size_t element_count;
3013cab2bb3Spatrick // };
IsARMABIArrayCookie(uptr chunk_beg,uptr chunk_size,uptr addr)3023cab2bb3Spatrick static inline bool IsARMABIArrayCookie(uptr chunk_beg, uptr chunk_size,
3033cab2bb3Spatrick                                        uptr addr) {
3043cab2bb3Spatrick   return chunk_size == 2 * sizeof(uptr) && chunk_beg + chunk_size == addr &&
3053cab2bb3Spatrick          *reinterpret_cast<uptr *>(chunk_beg + sizeof(uptr)) == 0;
3063cab2bb3Spatrick }
3073cab2bb3Spatrick 
3083cab2bb3Spatrick // Special case for "new T[0]" where T is a type with DTOR.
3093cab2bb3Spatrick // new T[0] will allocate a cookie (one or two words) for the array size (0)
3103cab2bb3Spatrick // and store a pointer to the end of allocated chunk. The actual cookie layout
3113cab2bb3Spatrick // varies between platforms according to their C++ ABI implementation.
IsSpecialCaseOfOperatorNew0(uptr chunk_beg,uptr chunk_size,uptr addr)3123cab2bb3Spatrick inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
3133cab2bb3Spatrick                                         uptr addr) {
3143cab2bb3Spatrick #if defined(__arm__)
3153cab2bb3Spatrick   return IsARMABIArrayCookie(chunk_beg, chunk_size, addr);
3163cab2bb3Spatrick #else
3173cab2bb3Spatrick   return IsItaniumABIArrayCookie(chunk_beg, chunk_size, addr);
3183cab2bb3Spatrick #endif
3193cab2bb3Spatrick }
3203cab2bb3Spatrick 
3213cab2bb3Spatrick // Return the linker module, if valid for the platform.
3223cab2bb3Spatrick LoadedModule *GetLinker();
3233cab2bb3Spatrick 
3243cab2bb3Spatrick // Return true if LSan has finished leak checking and reported leaks.
3253cab2bb3Spatrick bool HasReportedLeaks();
3263cab2bb3Spatrick 
3273cab2bb3Spatrick // Run platform-specific leak handlers.
3283cab2bb3Spatrick void HandleLeaks();
3293cab2bb3Spatrick 
3303cab2bb3Spatrick }  // namespace __lsan
3313cab2bb3Spatrick 
3323cab2bb3Spatrick extern "C" {
3333cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
3343cab2bb3Spatrick const char *__lsan_default_options();
3353cab2bb3Spatrick 
3363cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
3373cab2bb3Spatrick int __lsan_is_turned_off();
3383cab2bb3Spatrick 
3393cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
3403cab2bb3Spatrick const char *__lsan_default_suppressions();
341*810390e3Srobert 
342*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE
343*810390e3Srobert void __lsan_register_root_region(const void *p, __lsan::uptr size);
344*810390e3Srobert 
345*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE
346*810390e3Srobert void __lsan_unregister_root_region(const void *p, __lsan::uptr size);
347*810390e3Srobert 
3483cab2bb3Spatrick }  // extern "C"
3493cab2bb3Spatrick 
3503cab2bb3Spatrick #endif  // LSAN_COMMON_H
351