1ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//=-- lsan_common.h -------------------------------------------------------===//
2ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//
3ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//                     The LLVM Compiler Infrastructure
4ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//
5ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// This file is distributed under the University of Illinois Open Source
6ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// License. See LICENSE.TXT for details.
7ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//
8ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//===----------------------------------------------------------------------===//
9ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//
10ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// This file is a part of LeakSanitizer.
11ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Private LSan header.
12ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//
13ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev//===----------------------------------------------------------------------===//
14ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
15ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#ifndef LSAN_COMMON_H
16ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#define LSAN_COMMON_H
17ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
18ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev#include "sanitizer_common/sanitizer_allocator.h"
19ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_common.h"
20ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_internal_defs.h"
219bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#include "sanitizer_common/sanitizer_platform.h"
2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_stoptheworld.h"
23ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_symbolizer.h"
24ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips64)) \
2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    && (SANITIZER_WORDSIZE == 64)
279bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 1
289bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#else
299bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 0
309bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#endif
319bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __sanitizer {
3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass FlagParser;
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
36ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevnamespace __lsan {
37ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
38ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Chunk tags.
39ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevenum ChunkTag {
40ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  kDirectlyLeaked = 0,  // default
41ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  kIndirectlyLeaked = 1,
425e719a705666988781b9735d62cafc808ade60e2Sergey Matveev  kReachable = 2,
43b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev  kIgnored = 3
44ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
45ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
46ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Flags {
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "lsan_flags.inc"
4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef LSAN_FLAG
5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void SetDefaults();
52ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr pointer_alignment() const {
53ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev    return use_unaligned ? 1 : sizeof(uptr);
54ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  }
55ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
56ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
57ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevextern Flags lsan_flags;
58ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevinline Flags *flags() { return &lsan_flags; }
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid RegisterLsanFlags(FlagParser *parser, Flags *f);
60ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
61ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Leak {
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u32 id;
63ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr hit_count;
64ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr total_size;
65ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  u32 stack_trace_id;
66ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool is_directly_leaked;
67b33cfeb6004d3a93e6d35749c14db0190c6c2b4cSergey Matveev  bool is_suppressed;
68ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
69ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct LeakedObject {
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u32 leak_id;
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr addr;
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr size;
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
76ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Aggregates leaks by stack trace prefix.
77ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LeakReport {
78ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public:
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {}
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size,
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                      ChunkTag tag);
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void ReportTopLeaks(uptr max_leaks);
836c3634b1d5eeb0bffea01df10caa7168c48c8c5dSergey Matveev  void PrintSummary();
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void ApplySuppressions();
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr UnsuppressedLeakCount();
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
88ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private:
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void PrintReportForLeak(uptr index);
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void PrintLeakedObjectsForLeak(uptr index);
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u32 next_id_;
93a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov  InternalMmapVector<Leak> leaks_;
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  InternalMmapVector<LeakedObject> leaked_objects_;
95ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
96ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
97dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovtypedef InternalMmapVector<uptr> Frontier;
98dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov
99ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Platform-specific functions.
100ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid InitializePlatformSpecificModules();
101dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessGlobalRegions(Frontier *frontier);
102dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessPlatformSpecificAllocations(Frontier *frontier);
10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Run stoptheworld while holding any platform-specific locks.
10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid DoStopTheWorld(StopTheWorldCallback callback, void* argument);
105ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
106a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovvoid ScanRangeForPointers(uptr begin, uptr end,
107dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov                          Frontier *frontier,
108ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                          const char *region_type, ChunkTag tag);
109ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
110cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveevenum IgnoreObjectResult {
111cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectSuccess,
112cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectAlreadyIgnored,
113cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectInvalid
114cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev};
115cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev
116200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev// Functions called from the parent tool.
11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid InitCommonLsan();
118200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid DoLeakCheck();
119200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevbool DisabledInThisThread();
120200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Special case for "new T[0]" where T is a type with DTOR.
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// new T[0] will allocate one word for the array size (0) and store a pointer
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// to the end of allocated chunk.
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                        uptr addr) {
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines         *reinterpret_cast<uptr *>(chunk_beg) == 0;
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
130ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// The following must be implemented in the parent tool.
131ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
132ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevvoid ForEachChunk(ForEachChunkCallback callback, void *arg);
133ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns the address range occupied by the global allocator object.
134ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid GetAllocatorGlobalRange(uptr *begin, uptr *end);
135ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for allocator's ForceLock()/ForceUnlock().
136ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockAllocator();
137ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockAllocator();
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Returns true if [addr, addr + sizeof(void *)) is poisoned.
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesbool WordIsPoisoned(uptr addr);
140ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for ThreadRegistry access.
141ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockThreadRegistry();
142ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockThreadRegistry();
143ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
144ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                           uptr *tls_begin, uptr *tls_end,
145ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                           uptr *cache_begin, uptr *cache_end);
146c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveevvoid ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
147c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev                            void *arg);
148c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// If called from the main thread, updates the main thread's TID in the thread
149c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// registry. We need this to handle processes that fork() without a subsequent
150c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// exec(), which invalidates the recorded TID. To update it, we must call
151c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// gettid() from the main thread. Our solution is to call this function before
152c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// leak checking and also before every call to pthread_create() (to handle cases
153c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// where leak checking is initiated from a non-main thread).
154c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect();
155ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// If p points into a chunk that has been allocated to the user, returns its
156ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// user-visible address. Otherwise, returns 0.
157ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr PointsIntoChunk(void *p);
158ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns address of user-visible chunk contained in this allocator chunk.
159ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr GetUserBegin(uptr chunk);
160cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev// Helper for __lsan_ignore_object().
161cd571e07fd1179383188c70338fa0dc1c452cb19Sergey MatveevIgnoreObjectResult IgnoreObjectLocked(const void *p);
162ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrapper for chunk metadata operations.
163ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LsanMetadata {
164ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public:
165ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  // Constructor accepts address of user-visible chunk.
166ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  explicit LsanMetadata(uptr chunk);
167ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool allocated() const;
168ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  ChunkTag tag() const;
169ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void set_tag(ChunkTag value);
170ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr requested_size() const;
171ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  u32 stack_trace_id() const;
172ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private:
173ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void *metadata_;
174ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
175ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
176ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}  // namespace __lsan
177ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
1789fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovextern "C" {
1793c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1803c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovint __lsan_is_turned_off();
1813c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanov
1823c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1833c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovconst char *__lsan_default_suppressions();
1849fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov}  // extern "C"
1859fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov
186ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#endif  // LSAN_COMMON_H
187