lsan_common.h revision 9fbfd96608070eb71e11fbfe42ec9e84016429ae
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"
22ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#include "sanitizer_common/sanitizer_symbolizer.h"
23ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
249bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#if SANITIZER_LINUX && defined(__x86_64__)
259bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 1
269bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#else
279bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#define CAN_SANITIZE_LEAKS 0
289bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev#endif
299bdf7802d403b53baee3433ddddc220f457e039cSergey Matveev
30ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevnamespace __lsan {
31ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
32ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Chunk tags.
33ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevenum ChunkTag {
34ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  kDirectlyLeaked = 0,  // default
35ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  kIndirectlyLeaked = 1,
365e719a705666988781b9735d62cafc808ade60e2Sergey Matveev  kReachable = 2,
37b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev  kIgnored = 3
38ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
39ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
40ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Flags {
41ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr pointer_alignment() const {
42ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev    return use_unaligned ? 1 : sizeof(uptr);
43ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  }
44ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
45b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev  // Print addresses of leaked objects after main leak report.
46b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev  bool report_objects;
47b3b46dad13a2111a51fb1a67f36c8b633410e9b7Sergey Matveev  // Aggregate two objects into one leak if this many stack frames match. If
48ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  // zero, the entire stack trace must match.
49ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  int resolution;
50ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  // The number of leaks reported.
51ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  int max_leaks;
52969b529914f5bc17e4810076dccbaadf563d584cSergey Matveev  // If nonzero kill the process with this exit code upon finding leaks.
53969b529914f5bc17e4810076dccbaadf563d584cSergey Matveev  int exitcode;
54ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
55ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // Flags controlling the root set of reachable memory.
56ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // Global variables (.data and .bss).
57ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  bool use_globals;
58ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // Thread stacks.
59ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  bool use_stacks;
60ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // Thread registers.
61ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  bool use_registers;
62ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // TLS and thread-specific storage.
63ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  bool use_tls;
64ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev
65ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  // Consider unaligned pointers valid.
66ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev  bool use_unaligned;
67ebe3a3608be122e799e264931f9cecf4cbc84eddSergey Matveev
68cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  // User-visible verbosity.
69cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  int verbosity;
70cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev
71ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  // Debug logging.
72ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool log_pointers;
73ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool log_threads;
74ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
75ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
76ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevextern Flags lsan_flags;
77ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevinline Flags *flags() { return &lsan_flags; }
78ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
79ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevstruct Leak {
80ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr hit_count;
81ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr total_size;
82ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  u32 stack_trace_id;
83ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool is_directly_leaked;
84ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
85ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
86ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Aggregates leaks by stack trace prefix.
87ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LeakReport {
88ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public:
89ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  LeakReport() : leaks_(1) {}
90ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag);
91ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void PrintLargest(uptr max_leaks);
926c3634b1d5eeb0bffea01df10caa7168c48c8c5dSergey Matveev  void PrintSummary();
93ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool IsEmpty() { return leaks_.size() == 0; }
94ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private:
95a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonov  InternalMmapVector<Leak> leaks_;
96ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
97ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
98dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovtypedef InternalMmapVector<uptr> Frontier;
99dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov
100ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Platform-specific functions.
101ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid InitializePlatformSpecificModules();
102dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessGlobalRegions(Frontier *frontier);
103dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonovvoid ProcessPlatformSpecificAllocations(Frontier *frontier);
104ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
105a64d4359902f1f64992aedfe10d8882ae7c66f40Alexey Samsonovvoid ScanRangeForPointers(uptr begin, uptr end,
106dbeb48d34bb6447c33a0ef99aaf9ba36f7f4b852Alexey Samsonov                          Frontier *frontier,
107ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                          const char *region_type, ChunkTag tag);
108ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
109cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveevenum IgnoreObjectResult {
110cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectSuccess,
111cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectAlreadyIgnored,
112cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev  kIgnoreObjectInvalid
113cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev};
114cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev
115200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev// Functions called from the parent tool.
116200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid InitCommonLsan();
117200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevvoid DoLeakCheck();
118200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveevbool DisabledInThisThread();
119200afbd8ba4904241c1ebcef4fa79d739ca01f73Sergey Matveev
120ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// The following must be implemented in the parent tool.
121ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
122ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevvoid ForEachChunk(ForEachChunkCallback callback, void *arg);
123ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns the address range occupied by the global allocator object.
124ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid GetAllocatorGlobalRange(uptr *begin, uptr *end);
125ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for allocator's ForceLock()/ForceUnlock().
126ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockAllocator();
127ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockAllocator();
128ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrappers for ThreadRegistry access.
129ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid LockThreadRegistry();
130ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevvoid UnlockThreadRegistry();
131ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
132ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                           uptr *tls_begin, uptr *tls_end,
133ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev                           uptr *cache_begin, uptr *cache_end);
134ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// If p points into a chunk that has been allocated to the user, returns its
135ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// user-visible address. Otherwise, returns 0.
136ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr PointsIntoChunk(void *p);
137ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev// Returns address of user-visible chunk contained in this allocator chunk.
138ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevuptr GetUserBegin(uptr chunk);
139cd571e07fd1179383188c70338fa0dc1c452cb19Sergey Matveev// Helper for __lsan_ignore_object().
140cd571e07fd1179383188c70338fa0dc1c452cb19Sergey MatveevIgnoreObjectResult IgnoreObjectLocked(const void *p);
141ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev// Wrapper for chunk metadata operations.
142ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveevclass LsanMetadata {
143ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev public:
144ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  // Constructor accepts address of user-visible chunk.
145ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  explicit LsanMetadata(uptr chunk);
146ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  bool allocated() const;
147ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  ChunkTag tag() const;
148ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void set_tag(ChunkTag value);
149ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  uptr requested_size() const;
150ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  u32 stack_trace_id() const;
151ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev private:
152ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev  void *metadata_;
153ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev};
154ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
155ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev}  // namespace __lsan
156ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev
1579fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovextern "C" {
1589fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonovint __lsan_is_turned_off() SANITIZER_WEAK_ATTRIBUTE
1599fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov    SANITIZER_INTERFACE_ATTRIBUTE;
1609fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov}  // extern "C"
1619fbfd96608070eb71e11fbfe42ec9e84016429aeAlexey Samsonov
162ab0f74438abd73342a9d09e1d8b687461cf18da1Sergey Matveev#endif  // LSAN_COMMON_H
163