[LSan] Rework r191522 - treat allocations with short stack traces as live
[blocksruntime.git] / lib / lsan / lsan_common.cc
blob7fa067522fe30f845179c3d96579571257c76761
1 //=-- lsan_common.cc ------------------------------------------------------===//
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 // Implementation of common leak checking functionality.
13 //===----------------------------------------------------------------------===//
15 #include "lsan_common.h"
17 #include "sanitizer_common/sanitizer_common.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_placement_new.h"
20 #include "sanitizer_common/sanitizer_stackdepot.h"
21 #include "sanitizer_common/sanitizer_stacktrace.h"
22 #include "sanitizer_common/sanitizer_stoptheworld.h"
23 #include "sanitizer_common/sanitizer_suppressions.h"
24 #include "sanitizer_common/sanitizer_report_decorator.h"
26 #if CAN_SANITIZE_LEAKS
27 namespace __lsan {
29 // This mutex is used to prevent races between DoLeakCheck and IgnoreObject.
30 BlockingMutex global_mutex(LINKER_INITIALIZED);
32 THREADLOCAL int disable_counter;
33 bool DisabledInThisThread() { return disable_counter > 0; }
35 Flags lsan_flags;
37 static void InitializeFlags() {
38 Flags *f = flags();
39 // Default values.
40 f->report_objects = false;
41 f->resolution = 0;
42 f->max_leaks = 0;
43 f->exitcode = 23;
44 f->suppressions="";
45 f->use_registers = true;
46 f->use_globals = true;
47 f->use_stacks = true;
48 f->use_tls = true;
49 f->use_unaligned = false;
50 f->verbosity = 0;
51 f->log_pointers = false;
52 f->log_threads = false;
54 const char *options = GetEnv("LSAN_OPTIONS");
55 if (options) {
56 ParseFlag(options, &f->use_registers, "use_registers");
57 ParseFlag(options, &f->use_globals, "use_globals");
58 ParseFlag(options, &f->use_stacks, "use_stacks");
59 ParseFlag(options, &f->use_tls, "use_tls");
60 ParseFlag(options, &f->use_unaligned, "use_unaligned");
61 ParseFlag(options, &f->report_objects, "report_objects");
62 ParseFlag(options, &f->resolution, "resolution");
63 CHECK_GE(&f->resolution, 0);
64 ParseFlag(options, &f->max_leaks, "max_leaks");
65 CHECK_GE(&f->max_leaks, 0);
66 ParseFlag(options, &f->verbosity, "verbosity");
67 ParseFlag(options, &f->log_pointers, "log_pointers");
68 ParseFlag(options, &f->log_threads, "log_threads");
69 ParseFlag(options, &f->exitcode, "exitcode");
70 ParseFlag(options, &f->suppressions, "suppressions");
74 SuppressionContext *suppression_ctx;
76 void InitializeSuppressions() {
77 CHECK(!suppression_ctx);
78 ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
79 suppression_ctx = new(placeholder_) SuppressionContext;
80 char *suppressions_from_file;
81 uptr buffer_size;
82 if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
83 &buffer_size, 1 << 26 /* max_len */))
84 suppression_ctx->Parse(suppressions_from_file);
85 if (flags()->suppressions[0] && !buffer_size) {
86 Printf("LeakSanitizer: failed to read suppressions file '%s'\n",
87 flags()->suppressions);
88 Die();
90 if (&__lsan_default_suppressions)
91 suppression_ctx->Parse(__lsan_default_suppressions());
94 void InitCommonLsan() {
95 InitializeFlags();
96 InitializeSuppressions();
97 InitializePlatformSpecificModules();
100 class Decorator: private __sanitizer::AnsiColorDecorator {
101 public:
102 Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
103 const char *Error() { return Red(); }
104 const char *Leak() { return Blue(); }
105 const char *End() { return Default(); }
108 static inline bool CanBeAHeapPointer(uptr p) {
109 // Since our heap is located in mmap-ed memory, we can assume a sensible lower
110 // bound on heap addresses.
111 const uptr kMinAddress = 4 * 4096;
112 if (p < kMinAddress) return false;
113 #ifdef __x86_64__
114 // Accept only canonical form user-space addresses.
115 return ((p >> 47) == 0);
116 #else
117 return true;
118 #endif
121 // Scans the memory range, looking for byte patterns that point into allocator
122 // chunks. Marks those chunks with |tag| and adds them to |frontier|.
123 // There are two usage modes for this function: finding reachable or ignored
124 // chunks (|tag| = kReachable or kIgnored) and finding indirectly leaked chunks
125 // (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
126 // so |frontier| = 0.
127 void ScanRangeForPointers(uptr begin, uptr end,
128 Frontier *frontier,
129 const char *region_type, ChunkTag tag) {
130 const uptr alignment = flags()->pointer_alignment();
131 if (flags()->log_pointers)
132 Report("Scanning %s range %p-%p.\n", region_type, begin, end);
133 uptr pp = begin;
134 if (pp % alignment)
135 pp = pp + alignment - pp % alignment;
136 for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT
137 void *p = *reinterpret_cast<void **>(pp);
138 if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
139 uptr chunk = PointsIntoChunk(p);
140 if (!chunk) continue;
141 LsanMetadata m(chunk);
142 // Reachable beats ignored beats leaked.
143 if (m.tag() == kReachable) continue;
144 if (m.tag() == kIgnored && tag != kReachable) continue;
145 m.set_tag(tag);
146 if (flags()->log_pointers)
147 Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
148 chunk, chunk + m.requested_size(), m.requested_size());
149 if (frontier)
150 frontier->push_back(chunk);
154 // Scans thread data (stacks and TLS) for heap pointers.
155 static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
156 Frontier *frontier) {
157 InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount());
158 uptr registers_begin = reinterpret_cast<uptr>(registers.data());
159 uptr registers_end = registers_begin + registers.size();
160 for (uptr i = 0; i < suspended_threads.thread_count(); i++) {
161 uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i));
162 if (flags()->log_threads) Report("Processing thread %d.\n", os_id);
163 uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
164 bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
165 &tls_begin, &tls_end,
166 &cache_begin, &cache_end);
167 if (!thread_found) {
168 // If a thread can't be found in the thread registry, it's probably in the
169 // process of destruction. Log this event and move on.
170 if (flags()->log_threads)
171 Report("Thread %d not found in registry.\n", os_id);
172 continue;
174 uptr sp;
175 bool have_registers =
176 (suspended_threads.GetRegistersAndSP(i, registers.data(), &sp) == 0);
177 if (!have_registers) {
178 Report("Unable to get registers from thread %d.\n");
179 // If unable to get SP, consider the entire stack to be reachable.
180 sp = stack_begin;
183 if (flags()->use_registers && have_registers)
184 ScanRangeForPointers(registers_begin, registers_end, frontier,
185 "REGISTERS", kReachable);
187 if (flags()->use_stacks) {
188 if (flags()->log_threads)
189 Report("Stack at %p-%p, SP = %p.\n", stack_begin, stack_end, sp);
190 if (sp < stack_begin || sp >= stack_end) {
191 // SP is outside the recorded stack range (e.g. the thread is running a
192 // signal handler on alternate stack). Again, consider the entire stack
193 // range to be reachable.
194 if (flags()->log_threads)
195 Report("WARNING: stack pointer not in stack range.\n");
196 } else {
197 // Shrink the stack range to ignore out-of-scope values.
198 stack_begin = sp;
200 ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
201 kReachable);
204 if (flags()->use_tls) {
205 if (flags()->log_threads) Report("TLS at %p-%p.\n", tls_begin, tls_end);
206 if (cache_begin == cache_end) {
207 ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
208 } else {
209 // Because LSan should not be loaded with dlopen(), we can assume
210 // that allocator cache will be part of static TLS image.
211 CHECK_LE(tls_begin, cache_begin);
212 CHECK_GE(tls_end, cache_end);
213 if (tls_begin < cache_begin)
214 ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
215 kReachable);
216 if (tls_end > cache_end)
217 ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
223 static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
224 while (frontier->size()) {
225 uptr next_chunk = frontier->back();
226 frontier->pop_back();
227 LsanMetadata m(next_chunk);
228 ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
229 "HEAP", tag);
233 // ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
234 // which are reachable from it as indirectly leaked.
235 static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
236 chunk = GetUserBegin(chunk);
237 LsanMetadata m(chunk);
238 if (m.allocated() && m.tag() != kReachable) {
239 ScanRangeForPointers(chunk, chunk + m.requested_size(),
240 /* frontier */ 0, "HEAP", kIndirectlyLeaked);
244 // ForEachChunk callback. If chunk is marked as ignored, adds its address to
245 // frontier.
246 static void CollectIgnoredCb(uptr chunk, void *arg) {
247 CHECK(arg);
248 chunk = GetUserBegin(chunk);
249 LsanMetadata m(chunk);
250 if (m.allocated() && m.tag() == kIgnored)
251 reinterpret_cast<Frontier *>(arg)->push_back(chunk);
254 // Sets the appropriate tag on each chunk.
255 static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) {
256 // Holds the flood fill frontier.
257 Frontier frontier(GetPageSizeCached());
259 if (flags()->use_globals)
260 ProcessGlobalRegions(&frontier);
261 ProcessThreads(suspended_threads, &frontier);
262 FloodFillTag(&frontier, kReachable);
263 // The check here is relatively expensive, so we do this in a separate flood
264 // fill. That way we can skip the check for chunks that are reachable
265 // otherwise.
266 ProcessPlatformSpecificAllocations(&frontier);
267 FloodFillTag(&frontier, kReachable);
269 if (flags()->log_pointers)
270 Report("Scanning ignored chunks.\n");
271 CHECK_EQ(0, frontier.size());
272 ForEachChunk(CollectIgnoredCb, &frontier);
273 FloodFillTag(&frontier, kIgnored);
275 // Iterate over leaked chunks and mark those that are reachable from other
276 // leaked chunks.
277 if (flags()->log_pointers)
278 Report("Scanning leaked chunks.\n");
279 ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */);
282 static void PrintStackTraceById(u32 stack_trace_id) {
283 CHECK(stack_trace_id);
284 uptr size = 0;
285 const uptr *trace = StackDepotGet(stack_trace_id, &size);
286 StackTrace::PrintStack(trace, size, common_flags()->symbolize,
287 common_flags()->strip_path_prefix, 0);
290 // ForEachChunk callback. Aggregates unreachable chunks into a LeakReport.
291 static void CollectLeaksCb(uptr chunk, void *arg) {
292 CHECK(arg);
293 LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
294 chunk = GetUserBegin(chunk);
295 LsanMetadata m(chunk);
296 if (!m.allocated()) return;
297 if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
298 uptr resolution = flags()->resolution;
299 if (resolution > 0) {
300 uptr size = 0;
301 const uptr *trace = StackDepotGet(m.stack_trace_id(), &size);
302 size = Min(size, resolution);
303 leak_report->Add(StackDepotPut(trace, size), m.requested_size(), m.tag());
304 } else {
305 leak_report->Add(m.stack_trace_id(), m.requested_size(), m.tag());
310 // ForEachChunkCallback. Prints addresses of unreachable chunks.
311 static void PrintLeakedCb(uptr chunk, void *arg) {
312 chunk = GetUserBegin(chunk);
313 LsanMetadata m(chunk);
314 if (!m.allocated()) return;
315 if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
316 Printf("%s leaked %zu byte object at %p.\n",
317 m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly",
318 m.requested_size(), chunk);
322 static void PrintMatchedSuppressions() {
323 InternalMmapVector<Suppression *> matched(1);
324 suppression_ctx->GetMatched(&matched);
325 if (!matched.size())
326 return;
327 const char *line = "-----------------------------------------------------";
328 Printf("%s\n", line);
329 Printf("Suppressions used:\n");
330 Printf(" count bytes template\n");
331 for (uptr i = 0; i < matched.size(); i++)
332 Printf("%7zu %10zu %s\n", static_cast<uptr>(matched[i]->hit_count),
333 matched[i]->weight, matched[i]->templ);
334 Printf("%s\n\n", line);
337 static void PrintLeaked() {
338 Printf("\n");
339 Printf("Reporting individual objects:\n");
340 ForEachChunk(PrintLeakedCb, 0 /* arg */);
343 struct DoLeakCheckParam {
344 bool success;
345 LeakReport leak_report;
348 static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
349 void *arg) {
350 DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
351 CHECK(param);
352 CHECK(!param->success);
353 CHECK(param->leak_report.IsEmpty());
354 ClassifyAllChunks(suspended_threads);
355 ForEachChunk(CollectLeaksCb, &param->leak_report);
356 if (!param->leak_report.IsEmpty() && flags()->report_objects)
357 PrintLeaked();
358 param->success = true;
361 void DoLeakCheck() {
362 EnsureMainThreadIDIsCorrect();
363 BlockingMutexLock l(&global_mutex);
364 static bool already_done;
365 if (already_done) return;
366 already_done = true;
367 if (&__lsan_is_turned_off && __lsan_is_turned_off())
368 return;
370 DoLeakCheckParam param;
371 param.success = false;
372 LockThreadRegistry();
373 LockAllocator();
374 StopTheWorld(DoLeakCheckCallback, &param);
375 UnlockAllocator();
376 UnlockThreadRegistry();
378 if (!param.success) {
379 Report("LeakSanitizer has encountered a fatal error.\n");
380 Die();
382 uptr have_unsuppressed = param.leak_report.ApplySuppressions();
383 if (have_unsuppressed) {
384 Decorator d;
385 Printf("\n"
386 "================================================================="
387 "\n");
388 Printf("%s", d.Error());
389 Report("ERROR: LeakSanitizer: detected memory leaks\n");
390 Printf("%s", d.End());
391 param.leak_report.PrintLargest(flags()->max_leaks);
393 if (have_unsuppressed || (flags()->verbosity >= 1)) {
394 PrintMatchedSuppressions();
395 param.leak_report.PrintSummary();
397 if (have_unsuppressed && flags()->exitcode)
398 internal__exit(flags()->exitcode);
401 static Suppression *GetSuppressionForAddr(uptr addr) {
402 static const uptr kMaxAddrFrames = 16;
403 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
404 for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
405 uptr addr_frames_num =
406 getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
407 for (uptr i = 0; i < addr_frames_num; i++) {
408 Suppression* s;
409 if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||
410 suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s) ||
411 suppression_ctx->Match(addr_frames[i].module, SuppressionLeak, &s))
412 return s;
414 return 0;
417 static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
418 uptr size = 0;
419 const uptr *trace = StackDepotGet(stack_trace_id, &size);
420 for (uptr i = 0; i < size; i++) {
421 Suppression *s =
422 GetSuppressionForAddr(StackTrace::GetPreviousInstructionPc(trace[i]));
423 if (s) return s;
425 return 0;
428 ///// LeakReport implementation. /////
430 // A hard limit on the number of distinct leaks, to avoid quadratic complexity
431 // in LeakReport::Add(). We don't expect to ever see this many leaks in
432 // real-world applications.
433 // FIXME: Get rid of this limit by changing the implementation of LeakReport to
434 // use a hash table.
435 const uptr kMaxLeaksConsidered = 5000;
437 void LeakReport::Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag) {
438 CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
439 bool is_directly_leaked = (tag == kDirectlyLeaked);
440 for (uptr i = 0; i < leaks_.size(); i++)
441 if (leaks_[i].stack_trace_id == stack_trace_id &&
442 leaks_[i].is_directly_leaked == is_directly_leaked) {
443 leaks_[i].hit_count++;
444 leaks_[i].total_size += leaked_size;
445 return;
447 if (leaks_.size() == kMaxLeaksConsidered) return;
448 Leak leak = { /* hit_count */ 1, leaked_size, stack_trace_id,
449 is_directly_leaked, /* is_suppressed */ false };
450 leaks_.push_back(leak);
453 static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
454 if (leak1.is_directly_leaked == leak2.is_directly_leaked)
455 return leak1.total_size > leak2.total_size;
456 else
457 return leak1.is_directly_leaked;
460 void LeakReport::PrintLargest(uptr num_leaks_to_print) {
461 CHECK(leaks_.size() <= kMaxLeaksConsidered);
462 Printf("\n");
463 if (leaks_.size() == kMaxLeaksConsidered)
464 Printf("Too many leaks! Only the first %zu leaks encountered will be "
465 "reported.\n",
466 kMaxLeaksConsidered);
468 uptr unsuppressed_count = 0;
469 for (uptr i = 0; i < leaks_.size(); i++)
470 if (!leaks_[i].is_suppressed) unsuppressed_count++;
471 if (num_leaks_to_print > 0 && num_leaks_to_print < unsuppressed_count)
472 Printf("The %zu largest leak(s):\n", num_leaks_to_print);
473 InternalSort(&leaks_, leaks_.size(), LeakComparator);
474 uptr leaks_printed = 0;
475 Decorator d;
476 for (uptr i = 0; i < leaks_.size(); i++) {
477 if (leaks_[i].is_suppressed) continue;
478 Printf("%s", d.Leak());
479 Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
480 leaks_[i].is_directly_leaked ? "Direct" : "Indirect",
481 leaks_[i].total_size, leaks_[i].hit_count);
482 Printf("%s", d.End());
483 PrintStackTraceById(leaks_[i].stack_trace_id);
484 Printf("\n");
485 leaks_printed++;
486 if (leaks_printed == num_leaks_to_print) break;
488 if (leaks_printed < unsuppressed_count) {
489 uptr remaining = unsuppressed_count - leaks_printed;
490 Printf("Omitting %zu more leak(s).\n", remaining);
494 void LeakReport::PrintSummary() {
495 CHECK(leaks_.size() <= kMaxLeaksConsidered);
496 uptr bytes = 0, allocations = 0;
497 for (uptr i = 0; i < leaks_.size(); i++) {
498 if (leaks_[i].is_suppressed) continue;
499 bytes += leaks_[i].total_size;
500 allocations += leaks_[i].hit_count;
502 const int kMaxSummaryLength = 128;
503 InternalScopedBuffer<char> summary(kMaxSummaryLength);
504 internal_snprintf(summary.data(), kMaxSummaryLength,
505 "LeakSanitizer: %zu byte(s) leaked in %zu allocation(s).",
506 bytes, allocations);
507 __sanitizer_report_error_summary(summary.data());
510 uptr LeakReport::ApplySuppressions() {
511 uptr unsuppressed_count = 0;
512 for (uptr i = 0; i < leaks_.size(); i++) {
513 Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
514 if (s) {
515 s->weight += leaks_[i].total_size;
516 s->hit_count += leaks_[i].hit_count;
517 leaks_[i].is_suppressed = true;
518 } else {
519 unsuppressed_count++;
522 return unsuppressed_count;
524 } // namespace __lsan
525 #endif // CAN_SANITIZE_LEAKS
527 using namespace __lsan; // NOLINT
529 extern "C" {
530 SANITIZER_INTERFACE_ATTRIBUTE
531 void __lsan_ignore_object(const void *p) {
532 #if CAN_SANITIZE_LEAKS
533 // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
534 // locked.
535 BlockingMutexLock l(&global_mutex);
536 IgnoreObjectResult res = IgnoreObjectLocked(p);
537 if (res == kIgnoreObjectInvalid && flags()->verbosity >= 2)
538 Report("__lsan_ignore_object(): no heap object found at %p", p);
539 if (res == kIgnoreObjectAlreadyIgnored && flags()->verbosity >= 2)
540 Report("__lsan_ignore_object(): "
541 "heap object at %p is already being ignored\n", p);
542 if (res == kIgnoreObjectSuccess && flags()->verbosity >= 3)
543 Report("__lsan_ignore_object(): ignoring heap object at %p\n", p);
544 #endif // CAN_SANITIZE_LEAKS
547 SANITIZER_INTERFACE_ATTRIBUTE
548 void __lsan_disable() {
549 #if CAN_SANITIZE_LEAKS
550 __lsan::disable_counter++;
551 #endif
554 SANITIZER_INTERFACE_ATTRIBUTE
555 void __lsan_enable() {
556 #if CAN_SANITIZE_LEAKS
557 if (!__lsan::disable_counter) {
558 Report("Unmatched call to __lsan_enable().\n");
559 Die();
561 __lsan::disable_counter--;
562 #endif
565 SANITIZER_INTERFACE_ATTRIBUTE
566 void __lsan_do_leak_check() {
567 #if CAN_SANITIZE_LEAKS
568 if (common_flags()->detect_leaks)
569 __lsan::DoLeakCheck();
570 #endif // CAN_SANITIZE_LEAKS
573 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
574 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
575 int __lsan_is_turned_off() {
576 return 0;
578 #endif
579 } // extern "C"