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