blob: 4f9d24fb3ab9594827d1aa2aa1e2827fea56dc91 [file] [log] [blame]
Sergey Matveevab0f7442013-05-20 11:06:50 +00001//=-- lsan_common.h -------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of LeakSanitizer.
11// Private LSan header.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LSAN_COMMON_H
16#define LSAN_COMMON_H
17
Sergey Matveevac78d002013-06-24 08:34:50 +000018#include "sanitizer_common/sanitizer_allocator.h"
Sergey Matveevab0f7442013-05-20 11:06:50 +000019#include "sanitizer_common/sanitizer_common.h"
20#include "sanitizer_common/sanitizer_internal_defs.h"
Sergey Matveev9bdf7802013-05-21 14:12:11 +000021#include "sanitizer_common/sanitizer_platform.h"
Stephen Hines86277eb2015-03-23 12:06:32 -070022#include "sanitizer_common/sanitizer_stoptheworld.h"
Sergey Matveevab0f7442013-05-20 11:06:50 +000023#include "sanitizer_common/sanitizer_symbolizer.h"
24
Stephen Hines86277eb2015-03-23 12:06:32 -070025#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips64)) \
26 && (SANITIZER_WORDSIZE == 64)
Sergey Matveev9bdf7802013-05-21 14:12:11 +000027#define CAN_SANITIZE_LEAKS 1
28#else
29#define CAN_SANITIZE_LEAKS 0
30#endif
31
Stephen Hines86277eb2015-03-23 12:06:32 -070032namespace __sanitizer {
33class FlagParser;
34}
35
Sergey Matveevab0f7442013-05-20 11:06:50 +000036namespace __lsan {
37
38// Chunk tags.
39enum ChunkTag {
40 kDirectlyLeaked = 0, // default
41 kIndirectlyLeaked = 1,
Sergey Matveev5e719a72013-06-03 11:21:34 +000042 kReachable = 2,
Sergey Matveevb3b46da2013-06-11 15:26:20 +000043 kIgnored = 3
Sergey Matveevab0f7442013-05-20 11:06:50 +000044};
45
Sergey Matveevab0f7442013-05-20 11:06:50 +000046struct Flags {
Stephen Hines86277eb2015-03-23 12:06:32 -070047#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
48#include "lsan_flags.inc"
49#undef LSAN_FLAG
50
51 void SetDefaults();
Sergey Matveevab0f7442013-05-20 11:06:50 +000052 uptr pointer_alignment() const {
Sergey Matveevebe3a362013-05-27 11:41:46 +000053 return use_unaligned ? 1 : sizeof(uptr);
Sergey Matveevab0f7442013-05-20 11:06:50 +000054 }
Sergey Matveevab0f7442013-05-20 11:06:50 +000055};
56
57extern Flags lsan_flags;
58inline Flags *flags() { return &lsan_flags; }
Stephen Hines86277eb2015-03-23 12:06:32 -070059void RegisterLsanFlags(FlagParser *parser, Flags *f);
Sergey Matveevab0f7442013-05-20 11:06:50 +000060
Sergey Matveevab0f7442013-05-20 11:06:50 +000061struct Leak {
Stephen Hines2d1fdb22014-05-28 23:58:16 -070062 u32 id;
Sergey Matveevab0f7442013-05-20 11:06:50 +000063 uptr hit_count;
64 uptr total_size;
65 u32 stack_trace_id;
66 bool is_directly_leaked;
Sergey Matveevb33cfeb2013-06-28 14:38:31 +000067 bool is_suppressed;
Sergey Matveevab0f7442013-05-20 11:06:50 +000068};
69
Stephen Hines2d1fdb22014-05-28 23:58:16 -070070struct LeakedObject {
71 u32 leak_id;
72 uptr addr;
73 uptr size;
74};
75
Sergey Matveevab0f7442013-05-20 11:06:50 +000076// Aggregates leaks by stack trace prefix.
77class LeakReport {
78 public:
Stephen Hines2d1fdb22014-05-28 23:58:16 -070079 LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {}
80 void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size,
81 ChunkTag tag);
82 void ReportTopLeaks(uptr max_leaks);
Sergey Matveev6c3634b2013-05-24 14:49:13 +000083 void PrintSummary();
Stephen Hines2d1fdb22014-05-28 23:58:16 -070084 void ApplySuppressions();
85 uptr UnsuppressedLeakCount();
86
87
Sergey Matveevab0f7442013-05-20 11:06:50 +000088 private:
Stephen Hines2d1fdb22014-05-28 23:58:16 -070089 void PrintReportForLeak(uptr index);
90 void PrintLeakedObjectsForLeak(uptr index);
91
92 u32 next_id_;
Alexey Samsonova64d4352013-06-14 09:59:40 +000093 InternalMmapVector<Leak> leaks_;
Stephen Hines2d1fdb22014-05-28 23:58:16 -070094 InternalMmapVector<LeakedObject> leaked_objects_;
Sergey Matveevab0f7442013-05-20 11:06:50 +000095};
96
Alexey Samsonovdbeb48d2013-06-14 10:07:56 +000097typedef InternalMmapVector<uptr> Frontier;
98
Sergey Matveevab0f7442013-05-20 11:06:50 +000099// Platform-specific functions.
100void InitializePlatformSpecificModules();
Alexey Samsonovdbeb48d2013-06-14 10:07:56 +0000101void ProcessGlobalRegions(Frontier *frontier);
102void ProcessPlatformSpecificAllocations(Frontier *frontier);
Stephen Hines86277eb2015-03-23 12:06:32 -0700103// Run stoptheworld while holding any platform-specific locks.
104void DoStopTheWorld(StopTheWorldCallback callback, void* argument);
Sergey Matveevab0f7442013-05-20 11:06:50 +0000105
Alexey Samsonova64d4352013-06-14 09:59:40 +0000106void ScanRangeForPointers(uptr begin, uptr end,
Alexey Samsonovdbeb48d2013-06-14 10:07:56 +0000107 Frontier *frontier,
Sergey Matveevab0f7442013-05-20 11:06:50 +0000108 const char *region_type, ChunkTag tag);
109
Sergey Matveevcd571e02013-06-06 14:17:56 +0000110enum IgnoreObjectResult {
111 kIgnoreObjectSuccess,
112 kIgnoreObjectAlreadyIgnored,
113 kIgnoreObjectInvalid
114};
115
Sergey Matveev200afbd2013-06-21 14:51:52 +0000116// Functions called from the parent tool.
Stephen Hines86277eb2015-03-23 12:06:32 -0700117void InitCommonLsan();
Sergey Matveev200afbd2013-06-21 14:51:52 +0000118void DoLeakCheck();
119bool DisabledInThisThread();
120
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700121// Special case for "new T[0]" where T is a type with DTOR.
122// new T[0] will allocate one word for the array size (0) and store a pointer
123// to the end of allocated chunk.
124inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
125 uptr addr) {
126 return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
127 *reinterpret_cast<uptr *>(chunk_beg) == 0;
128}
129
Sergey Matveevab0f7442013-05-20 11:06:50 +0000130// The following must be implemented in the parent tool.
131
Sergey Matveevac78d002013-06-24 08:34:50 +0000132void ForEachChunk(ForEachChunkCallback callback, void *arg);
133// Returns the address range occupied by the global allocator object.
Sergey Matveevab0f7442013-05-20 11:06:50 +0000134void GetAllocatorGlobalRange(uptr *begin, uptr *end);
135// Wrappers for allocator's ForceLock()/ForceUnlock().
136void LockAllocator();
137void UnlockAllocator();
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700138// Returns true if [addr, addr + sizeof(void *)) is poisoned.
139bool WordIsPoisoned(uptr addr);
Sergey Matveevab0f7442013-05-20 11:06:50 +0000140// Wrappers for ThreadRegistry access.
141void LockThreadRegistry();
142void UnlockThreadRegistry();
143bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
144 uptr *tls_begin, uptr *tls_end,
145 uptr *cache_begin, uptr *cache_end);
Sergey Matveevc5193352013-10-14 14:04:50 +0000146void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
147 void *arg);
Sergey Matveevc6ac98d2013-07-08 12:57:24 +0000148// If called from the main thread, updates the main thread's TID in the thread
149// registry. We need this to handle processes that fork() without a subsequent
150// exec(), which invalidates the recorded TID. To update it, we must call
151// gettid() from the main thread. Our solution is to call this function before
152// leak checking and also before every call to pthread_create() (to handle cases
153// where leak checking is initiated from a non-main thread).
154void EnsureMainThreadIDIsCorrect();
Sergey Matveevac78d002013-06-24 08:34:50 +0000155// If p points into a chunk that has been allocated to the user, returns its
156// user-visible address. Otherwise, returns 0.
157uptr PointsIntoChunk(void *p);
158// Returns address of user-visible chunk contained in this allocator chunk.
159uptr GetUserBegin(uptr chunk);
Sergey Matveevcd571e02013-06-06 14:17:56 +0000160// Helper for __lsan_ignore_object().
161IgnoreObjectResult IgnoreObjectLocked(const void *p);
Sergey Matveevab0f7442013-05-20 11:06:50 +0000162// Wrapper for chunk metadata operations.
163class LsanMetadata {
164 public:
Sergey Matveevac78d002013-06-24 08:34:50 +0000165 // Constructor accepts address of user-visible chunk.
166 explicit LsanMetadata(uptr chunk);
Sergey Matveevab0f7442013-05-20 11:06:50 +0000167 bool allocated() const;
168 ChunkTag tag() const;
169 void set_tag(ChunkTag value);
170 uptr requested_size() const;
171 u32 stack_trace_id() const;
172 private:
173 void *metadata_;
174};
175
176} // namespace __lsan
177
Alexey Samsonov9fbfd962013-06-27 09:35:50 +0000178extern "C" {
Timur Iskhodzhanov3c80c6c2013-08-13 11:42:45 +0000179SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
180int __lsan_is_turned_off();
181
182SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
183const char *__lsan_default_suppressions();
Alexey Samsonov9fbfd962013-06-27 09:35:50 +0000184} // extern "C"
185
Sergey Matveevab0f7442013-05-20 11:06:50 +0000186#endif // LSAN_COMMON_H