1 //=-- lsan_common.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of LeakSanitizer.
10 // Implementation of common leak checking functionality.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "lsan_common.h"
15 
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_flag_parser.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_placement_new.h"
20 #include "sanitizer_common/sanitizer_procmaps.h"
21 #include "sanitizer_common/sanitizer_report_decorator.h"
22 #include "sanitizer_common/sanitizer_stackdepot.h"
23 #include "sanitizer_common/sanitizer_stacktrace.h"
24 #include "sanitizer_common/sanitizer_suppressions.h"
25 #include "sanitizer_common/sanitizer_thread_registry.h"
26 #include "sanitizer_common/sanitizer_tls_get_addr.h"
27 
28 #if CAN_SANITIZE_LEAKS
29 namespace __lsan {
30 
31 // This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
32 // also to protect the global list of root regions.
33 BlockingMutex global_mutex(LINKER_INITIALIZED);
34 
35 Flags lsan_flags;
36 
37 
38 void DisableCounterUnderflow() {
39   if (common_flags()->detect_leaks) {
40     Report("Unmatched call to __lsan_enable().\n");
41     Die();
42   }
43 }
44 
45 void Flags::SetDefaults() {
46 #define LSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
47 #include "lsan_flags.inc"
48 #undef LSAN_FLAG
49 }
50 
51 void RegisterLsanFlags(FlagParser *parser, Flags *f) {
52 #define LSAN_FLAG(Type, Name, DefaultValue, Description) \
53   RegisterFlag(parser, #Name, Description, &f->Name);
54 #include "lsan_flags.inc"
55 #undef LSAN_FLAG
56 }
57 
58 #define LOG_POINTERS(...)                           \
59   do {                                              \
60     if (flags()->log_pointers) Report(__VA_ARGS__); \
61   } while (0)
62 
63 #define LOG_THREADS(...)                           \
64   do {                                             \
65     if (flags()->log_threads) Report(__VA_ARGS__); \
66   } while (0)
67 
68 ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
69 static SuppressionContext *suppression_ctx = nullptr;
70 static const char kSuppressionLeak[] = "leak";
71 static const char *kSuppressionTypes[] = { kSuppressionLeak };
72 static const char kStdSuppressions[] =
73 #if SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
74   // For more details refer to the SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
75   // definition.
76   "leak:*pthread_exit*\n"
77 #endif  // SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
78 #if SANITIZER_MAC
79   // For Darwin and os_log/os_trace: https://reviews.llvm.org/D35173
80   "leak:*_os_trace*\n"
81 #endif
82   // TLS leak in some glibc versions, described in
83   // https://sourceware.org/bugzilla/show_bug.cgi?id=12650.
84   "leak:*tls_get_addr*\n";
85 
86 void InitializeSuppressions() {
87   CHECK_EQ(nullptr, suppression_ctx);
88   suppression_ctx = new (suppression_placeholder)
89       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
90   suppression_ctx->ParseFromFile(flags()->suppressions);
91   if (&__lsan_default_suppressions)
92     suppression_ctx->Parse(__lsan_default_suppressions());
93   suppression_ctx->Parse(kStdSuppressions);
94 }
95 
96 static SuppressionContext *GetSuppressionContext() {
97   CHECK(suppression_ctx);
98   return suppression_ctx;
99 }
100 
101 static InternalMmapVector<RootRegion> *root_regions;
102 
103 InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
104 
105 void InitializeRootRegions() {
106   CHECK(!root_regions);
107   ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
108   root_regions = new (placeholder) InternalMmapVector<RootRegion>();
109 }
110 
111 void InitCommonLsan() {
112   InitializeRootRegions();
113   if (common_flags()->detect_leaks) {
114     // Initialization which can fail or print warnings should only be done if
115     // LSan is actually enabled.
116     InitializeSuppressions();
117     InitializePlatformSpecificModules();
118   }
119 }
120 
121 class Decorator: public __sanitizer::SanitizerCommonDecorator {
122  public:
123   Decorator() : SanitizerCommonDecorator() { }
124   const char *Error() { return Red(); }
125   const char *Leak() { return Blue(); }
126 };
127 
128 static inline bool CanBeAHeapPointer(uptr p) {
129   // Since our heap is located in mmap-ed memory, we can assume a sensible lower
130   // bound on heap addresses.
131   const uptr kMinAddress = 4 * 4096;
132   if (p < kMinAddress) return false;
133 #if defined(__x86_64__)
134   // Accept only canonical form user-space addresses.
135   return ((p >> 47) == 0);
136 #elif defined(__mips64)
137   return ((p >> 40) == 0);
138 #elif defined(__aarch64__)
139   unsigned runtimeVMA =
140     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
141   return ((p >> runtimeVMA) == 0);
142 #else
143   return true;
144 #endif
145 }
146 
147 // Scans the memory range, looking for byte patterns that point into allocator
148 // chunks. Marks those chunks with |tag| and adds them to |frontier|.
149 // There are two usage modes for this function: finding reachable chunks
150 // (|tag| = kReachable) and finding indirectly leaked chunks
151 // (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
152 // so |frontier| = 0.
153 void ScanRangeForPointers(uptr begin, uptr end,
154                           Frontier *frontier,
155                           const char *region_type, ChunkTag tag) {
156   CHECK(tag == kReachable || tag == kIndirectlyLeaked);
157   const uptr alignment = flags()->pointer_alignment();
158   LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, begin, end);
159   uptr pp = begin;
160   if (pp % alignment)
161     pp = pp + alignment - pp % alignment;
162   for (; pp + sizeof(void *) <= end; pp += alignment) {
163     void *p = *reinterpret_cast<void **>(pp);
164     if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
165     uptr chunk = PointsIntoChunk(p);
166     if (!chunk) continue;
167     // Pointers to self don't count. This matters when tag == kIndirectlyLeaked.
168     if (chunk == begin) continue;
169     LsanMetadata m(chunk);
170     if (m.tag() == kReachable || m.tag() == kIgnored) continue;
171 
172     // Do this check relatively late so we can log only the interesting cases.
173     if (!flags()->use_poisoned && WordIsPoisoned(pp)) {
174       LOG_POINTERS(
175           "%p is poisoned: ignoring %p pointing into chunk %p-%p of size "
176           "%zu.\n",
177           pp, p, chunk, chunk + m.requested_size(), m.requested_size());
178       continue;
179     }
180 
181     m.set_tag(tag);
182     LOG_POINTERS("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
183                  chunk, chunk + m.requested_size(), m.requested_size());
184     if (frontier)
185       frontier->push_back(chunk);
186   }
187 }
188 
189 // Scans a global range for pointers
190 void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
191   uptr allocator_begin = 0, allocator_end = 0;
192   GetAllocatorGlobalRange(&allocator_begin, &allocator_end);
193   if (begin <= allocator_begin && allocator_begin < end) {
194     CHECK_LE(allocator_begin, allocator_end);
195     CHECK_LE(allocator_end, end);
196     if (begin < allocator_begin)
197       ScanRangeForPointers(begin, allocator_begin, frontier, "GLOBAL",
198                            kReachable);
199     if (allocator_end < end)
200       ScanRangeForPointers(allocator_end, end, frontier, "GLOBAL", kReachable);
201   } else {
202     ScanRangeForPointers(begin, end, frontier, "GLOBAL", kReachable);
203   }
204 }
205 
206 void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg) {
207   Frontier *frontier = reinterpret_cast<Frontier *>(arg);
208   ScanRangeForPointers(begin, end, frontier, "FAKE STACK", kReachable);
209 }
210 
211 #if SANITIZER_FUCHSIA
212 
213 // Fuchsia handles all threads together with its own callback.
214 static void ProcessThreads(SuspendedThreadsList const &, Frontier *) {}
215 
216 #else
217 
218 // Scans thread data (stacks and TLS) for heap pointers.
219 static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
220                            Frontier *frontier) {
221   InternalMmapVector<uptr> registers;
222   for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) {
223     tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i));
224     LOG_THREADS("Processing thread %d.\n", os_id);
225     uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
226     DTLS *dtls;
227     bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
228                                               &tls_begin, &tls_end,
229                                               &cache_begin, &cache_end, &dtls);
230     if (!thread_found) {
231       // If a thread can't be found in the thread registry, it's probably in the
232       // process of destruction. Log this event and move on.
233       LOG_THREADS("Thread %d not found in registry.\n", os_id);
234       continue;
235     }
236     uptr sp;
237     PtraceRegistersStatus have_registers =
238         suspended_threads.GetRegistersAndSP(i, &registers, &sp);
239     if (have_registers != REGISTERS_AVAILABLE) {
240       Report("Unable to get registers from thread %d.\n", os_id);
241       // If unable to get SP, consider the entire stack to be reachable unless
242       // GetRegistersAndSP failed with ESRCH.
243       if (have_registers == REGISTERS_UNAVAILABLE_FATAL) continue;
244       sp = stack_begin;
245     }
246 
247     if (flags()->use_registers && have_registers) {
248       uptr registers_begin = reinterpret_cast<uptr>(registers.data());
249       uptr registers_end =
250           reinterpret_cast<uptr>(registers.data() + registers.size());
251       ScanRangeForPointers(registers_begin, registers_end, frontier,
252                            "REGISTERS", kReachable);
253     }
254 
255     if (flags()->use_stacks) {
256       LOG_THREADS("Stack at %p-%p (SP = %p).\n", stack_begin, stack_end, sp);
257       if (sp < stack_begin || sp >= stack_end) {
258         // SP is outside the recorded stack range (e.g. the thread is running a
259         // signal handler on alternate stack, or swapcontext was used).
260         // Again, consider the entire stack range to be reachable.
261         LOG_THREADS("WARNING: stack pointer not in stack range.\n");
262         uptr page_size = GetPageSizeCached();
263         int skipped = 0;
264         while (stack_begin < stack_end &&
265                !IsAccessibleMemoryRange(stack_begin, 1)) {
266           skipped++;
267           stack_begin += page_size;
268         }
269         LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n",
270                     skipped, stack_begin, stack_end);
271       } else {
272         // Shrink the stack range to ignore out-of-scope values.
273         stack_begin = sp;
274       }
275       ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
276                            kReachable);
277       ForEachExtraStackRange(os_id, ForEachExtraStackRangeCb, frontier);
278     }
279 
280     if (flags()->use_tls) {
281       if (tls_begin) {
282         LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end);
283         // If the tls and cache ranges don't overlap, scan full tls range,
284         // otherwise, only scan the non-overlapping portions
285         if (cache_begin == cache_end || tls_end < cache_begin ||
286             tls_begin > cache_end) {
287           ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
288         } else {
289           if (tls_begin < cache_begin)
290             ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
291                                  kReachable);
292           if (tls_end > cache_end)
293             ScanRangeForPointers(cache_end, tls_end, frontier, "TLS",
294                                  kReachable);
295         }
296       }
297       if (dtls && !DTLSInDestruction(dtls)) {
298         for (uptr j = 0; j < dtls->dtv_size; ++j) {
299           uptr dtls_beg = dtls->dtv[j].beg;
300           uptr dtls_end = dtls_beg + dtls->dtv[j].size;
301           if (dtls_beg < dtls_end) {
302             LOG_THREADS("DTLS %zu at %p-%p.\n", j, dtls_beg, dtls_end);
303             ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
304                                  kReachable);
305           }
306         }
307       } else {
308         // We are handling a thread with DTLS under destruction. Log about
309         // this and continue.
310         LOG_THREADS("Thread %d has DTLS under destruction.\n", os_id);
311       }
312     }
313   }
314 }
315 
316 #endif  // SANITIZER_FUCHSIA
317 
318 void ScanRootRegion(Frontier *frontier, const RootRegion &root_region,
319                     uptr region_begin, uptr region_end, bool is_readable) {
320   uptr intersection_begin = Max(root_region.begin, region_begin);
321   uptr intersection_end = Min(region_end, root_region.begin + root_region.size);
322   if (intersection_begin >= intersection_end) return;
323   LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
324                root_region.begin, root_region.begin + root_region.size,
325                region_begin, region_end,
326                is_readable ? "readable" : "unreadable");
327   if (is_readable)
328     ScanRangeForPointers(intersection_begin, intersection_end, frontier, "ROOT",
329                          kReachable);
330 }
331 
332 static void ProcessRootRegion(Frontier *frontier,
333                               const RootRegion &root_region) {
334   MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
335   MemoryMappedSegment segment;
336   while (proc_maps.Next(&segment)) {
337     ScanRootRegion(frontier, root_region, segment.start, segment.end,
338                    segment.IsReadable());
339   }
340 }
341 
342 // Scans root regions for heap pointers.
343 static void ProcessRootRegions(Frontier *frontier) {
344   if (!flags()->use_root_regions) return;
345   CHECK(root_regions);
346   for (uptr i = 0; i < root_regions->size(); i++) {
347     ProcessRootRegion(frontier, (*root_regions)[i]);
348   }
349 }
350 
351 static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
352   while (frontier->size()) {
353     uptr next_chunk = frontier->back();
354     frontier->pop_back();
355     LsanMetadata m(next_chunk);
356     ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
357                          "HEAP", tag);
358   }
359 }
360 
361 // ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
362 // which are reachable from it as indirectly leaked.
363 static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
364   chunk = GetUserBegin(chunk);
365   LsanMetadata m(chunk);
366   if (m.allocated() && m.tag() != kReachable) {
367     ScanRangeForPointers(chunk, chunk + m.requested_size(),
368                          /* frontier */ nullptr, "HEAP", kIndirectlyLeaked);
369   }
370 }
371 
372 // ForEachChunk callback. If chunk is marked as ignored, adds its address to
373 // frontier.
374 static void CollectIgnoredCb(uptr chunk, void *arg) {
375   CHECK(arg);
376   chunk = GetUserBegin(chunk);
377   LsanMetadata m(chunk);
378   if (m.allocated() && m.tag() == kIgnored) {
379     LOG_POINTERS("Ignored: chunk %p-%p of size %zu.\n",
380                  chunk, chunk + m.requested_size(), m.requested_size());
381     reinterpret_cast<Frontier *>(arg)->push_back(chunk);
382   }
383 }
384 
385 static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
386   CHECK(stack_id);
387   StackTrace stack = map->Get(stack_id);
388   // The top frame is our malloc/calloc/etc. The next frame is the caller.
389   if (stack.size >= 2)
390     return stack.trace[1];
391   return 0;
392 }
393 
394 struct InvalidPCParam {
395   Frontier *frontier;
396   StackDepotReverseMap *stack_depot_reverse_map;
397   bool skip_linker_allocations;
398 };
399 
400 // ForEachChunk callback. If the caller pc is invalid or is within the linker,
401 // mark as reachable. Called by ProcessPlatformSpecificAllocations.
402 static void MarkInvalidPCCb(uptr chunk, void *arg) {
403   CHECK(arg);
404   InvalidPCParam *param = reinterpret_cast<InvalidPCParam *>(arg);
405   chunk = GetUserBegin(chunk);
406   LsanMetadata m(chunk);
407   if (m.allocated() && m.tag() != kReachable && m.tag() != kIgnored) {
408     u32 stack_id = m.stack_trace_id();
409     uptr caller_pc = 0;
410     if (stack_id > 0)
411       caller_pc = GetCallerPC(stack_id, param->stack_depot_reverse_map);
412     // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
413     // it as reachable, as we can't properly report its allocation stack anyway.
414     if (caller_pc == 0 || (param->skip_linker_allocations &&
415                            GetLinker()->containsAddress(caller_pc))) {
416       m.set_tag(kReachable);
417       param->frontier->push_back(chunk);
418     }
419   }
420 }
421 
422 // On Linux, treats all chunks allocated from ld-linux.so as reachable, which
423 // covers dynamically allocated TLS blocks, internal dynamic loader's loaded
424 // modules accounting etc.
425 // Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
426 // They are allocated with a __libc_memalign() call in allocate_and_init()
427 // (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
428 // blocks, but we can make sure they come from our own allocator by intercepting
429 // __libc_memalign(). On top of that, there is no easy way to reach them. Their
430 // addresses are stored in a dynamically allocated array (the DTV) which is
431 // referenced from the static TLS. Unfortunately, we can't just rely on the DTV
432 // being reachable from the static TLS, and the dynamic TLS being reachable from
433 // the DTV. This is because the initial DTV is allocated before our interception
434 // mechanism kicks in, and thus we don't recognize it as allocated memory. We
435 // can't special-case it either, since we don't know its size.
436 // Our solution is to include in the root set all allocations made from
437 // ld-linux.so (which is where allocate_and_init() is implemented). This is
438 // guaranteed to include all dynamic TLS blocks (and possibly other allocations
439 // which we don't care about).
440 // On all other platforms, this simply checks to ensure that the caller pc is
441 // valid before reporting chunks as leaked.
442 void ProcessPC(Frontier *frontier) {
443   StackDepotReverseMap stack_depot_reverse_map;
444   InvalidPCParam arg;
445   arg.frontier = frontier;
446   arg.stack_depot_reverse_map = &stack_depot_reverse_map;
447   arg.skip_linker_allocations =
448       flags()->use_tls && flags()->use_ld_allocations && GetLinker() != nullptr;
449   ForEachChunk(MarkInvalidPCCb, &arg);
450 }
451 
452 // Sets the appropriate tag on each chunk.
453 static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
454                               Frontier *frontier) {
455   ForEachChunk(CollectIgnoredCb, frontier);
456   ProcessGlobalRegions(frontier);
457   ProcessThreads(suspended_threads, frontier);
458   ProcessRootRegions(frontier);
459   FloodFillTag(frontier, kReachable);
460 
461   CHECK_EQ(0, frontier->size());
462   ProcessPC(frontier);
463 
464   // The check here is relatively expensive, so we do this in a separate flood
465   // fill. That way we can skip the check for chunks that are reachable
466   // otherwise.
467   LOG_POINTERS("Processing platform-specific allocations.\n");
468   ProcessPlatformSpecificAllocations(frontier);
469   FloodFillTag(frontier, kReachable);
470 
471   // Iterate over leaked chunks and mark those that are reachable from other
472   // leaked chunks.
473   LOG_POINTERS("Scanning leaked chunks.\n");
474   ForEachChunk(MarkIndirectlyLeakedCb, nullptr);
475 }
476 
477 // ForEachChunk callback. Resets the tags to pre-leak-check state.
478 static void ResetTagsCb(uptr chunk, void *arg) {
479   (void)arg;
480   chunk = GetUserBegin(chunk);
481   LsanMetadata m(chunk);
482   if (m.allocated() && m.tag() != kIgnored)
483     m.set_tag(kDirectlyLeaked);
484 }
485 
486 static void PrintStackTraceById(u32 stack_trace_id) {
487   CHECK(stack_trace_id);
488   StackDepotGet(stack_trace_id).Print();
489 }
490 
491 // ForEachChunk callback. Aggregates information about unreachable chunks into
492 // a LeakReport.
493 static void CollectLeaksCb(uptr chunk, void *arg) {
494   CHECK(arg);
495   LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
496   chunk = GetUserBegin(chunk);
497   LsanMetadata m(chunk);
498   if (!m.allocated()) return;
499   if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
500     u32 resolution = flags()->resolution;
501     u32 stack_trace_id = 0;
502     if (resolution > 0) {
503       StackTrace stack = StackDepotGet(m.stack_trace_id());
504       stack.size = Min(stack.size, resolution);
505       stack_trace_id = StackDepotPut(stack);
506     } else {
507       stack_trace_id = m.stack_trace_id();
508     }
509     leak_report->AddLeakedChunk(chunk, stack_trace_id, m.requested_size(),
510                                 m.tag());
511   }
512 }
513 
514 static void PrintMatchedSuppressions() {
515   InternalMmapVector<Suppression *> matched;
516   GetSuppressionContext()->GetMatched(&matched);
517   if (!matched.size())
518     return;
519   const char *line = "-----------------------------------------------------";
520   Printf("%s\n", line);
521   Printf("Suppressions used:\n");
522   Printf("  count      bytes template\n");
523   for (uptr i = 0; i < matched.size(); i++)
524     Printf("%7zu %10zu %s\n", static_cast<uptr>(atomic_load_relaxed(
525         &matched[i]->hit_count)), matched[i]->weight, matched[i]->templ);
526   Printf("%s\n\n", line);
527 }
528 
529 static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
530   const InternalMmapVector<tid_t> &suspended_threads =
531       *(const InternalMmapVector<tid_t> *)arg;
532   if (tctx->status == ThreadStatusRunning) {
533     uptr i = InternalLowerBound(suspended_threads, 0, suspended_threads.size(),
534                                 tctx->os_id, CompareLess<int>());
535     if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
536       Report("Running thread %d was not suspended. False leaks are possible.\n",
537              tctx->os_id);
538   }
539 }
540 
541 #if SANITIZER_FUCHSIA
542 
543 // Fuchsia provides a libc interface that guarantees all threads are
544 // covered, and SuspendedThreadList is never really used.
545 static void ReportUnsuspendedThreads(const SuspendedThreadsList &) {}
546 
547 #else  // !SANITIZER_FUCHSIA
548 
549 static void ReportUnsuspendedThreads(
550     const SuspendedThreadsList &suspended_threads) {
551   InternalMmapVector<tid_t> threads(suspended_threads.ThreadCount());
552   for (uptr i = 0; i < suspended_threads.ThreadCount(); ++i)
553     threads[i] = suspended_threads.GetThreadID(i);
554 
555   Sort(threads.data(), threads.size());
556 
557   GetThreadRegistryLocked()->RunCallbackForEachThreadLocked(
558       &ReportIfNotSuspended, &threads);
559 }
560 
561 #endif  // !SANITIZER_FUCHSIA
562 
563 static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
564                                   void *arg) {
565   CheckForLeaksParam *param = reinterpret_cast<CheckForLeaksParam *>(arg);
566   CHECK(param);
567   CHECK(!param->success);
568   ReportUnsuspendedThreads(suspended_threads);
569   ClassifyAllChunks(suspended_threads, &param->frontier);
570   ForEachChunk(CollectLeaksCb, &param->leak_report);
571   // Clean up for subsequent leak checks. This assumes we did not overwrite any
572   // kIgnored tags.
573   ForEachChunk(ResetTagsCb, nullptr);
574   param->success = true;
575 }
576 
577 static bool CheckForLeaks() {
578   if (&__lsan_is_turned_off && __lsan_is_turned_off())
579       return false;
580   EnsureMainThreadIDIsCorrect();
581   CheckForLeaksParam param;
582   LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
583 
584   if (!param.success) {
585     Report("LeakSanitizer has encountered a fatal error.\n");
586     Report(
587         "HINT: For debugging, try setting environment variable "
588         "LSAN_OPTIONS=verbosity=1:log_threads=1\n");
589     Report(
590         "HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)\n");
591     Die();
592   }
593   param.leak_report.ApplySuppressions();
594   uptr unsuppressed_count = param.leak_report.UnsuppressedLeakCount();
595   if (unsuppressed_count > 0) {
596     Decorator d;
597     Printf("\n"
598            "================================================================="
599            "\n");
600     Printf("%s", d.Error());
601     Report("ERROR: LeakSanitizer: detected memory leaks\n");
602     Printf("%s", d.Default());
603     param.leak_report.ReportTopLeaks(flags()->max_leaks);
604   }
605   if (common_flags()->print_suppressions)
606     PrintMatchedSuppressions();
607   if (unsuppressed_count > 0) {
608     param.leak_report.PrintSummary();
609     return true;
610   }
611   return false;
612 }
613 
614 static bool has_reported_leaks = false;
615 bool HasReportedLeaks() { return has_reported_leaks; }
616 
617 void DoLeakCheck() {
618   BlockingMutexLock l(&global_mutex);
619   static bool already_done;
620   if (already_done) return;
621   already_done = true;
622   has_reported_leaks = CheckForLeaks();
623   if (has_reported_leaks) HandleLeaks();
624 }
625 
626 static int DoRecoverableLeakCheck() {
627   BlockingMutexLock l(&global_mutex);
628   bool have_leaks = CheckForLeaks();
629   return have_leaks ? 1 : 0;
630 }
631 
632 void DoRecoverableLeakCheckVoid() { DoRecoverableLeakCheck(); }
633 
634 static Suppression *GetSuppressionForAddr(uptr addr) {
635   Suppression *s = nullptr;
636 
637   // Suppress by module name.
638   SuppressionContext *suppressions = GetSuppressionContext();
639   if (const char *module_name =
640           Symbolizer::GetOrInit()->GetModuleNameForPc(addr))
641     if (suppressions->Match(module_name, kSuppressionLeak, &s))
642       return s;
643 
644   // Suppress by file or function name.
645   SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
646   for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
647     if (suppressions->Match(cur->info.function, kSuppressionLeak, &s) ||
648         suppressions->Match(cur->info.file, kSuppressionLeak, &s)) {
649       break;
650     }
651   }
652   frames->ClearAll();
653   return s;
654 }
655 
656 static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
657   StackTrace stack = StackDepotGet(stack_trace_id);
658   for (uptr i = 0; i < stack.size; i++) {
659     Suppression *s = GetSuppressionForAddr(
660         StackTrace::GetPreviousInstructionPc(stack.trace[i]));
661     if (s) return s;
662   }
663   return nullptr;
664 }
665 
666 ///// LeakReport implementation. /////
667 
668 // A hard limit on the number of distinct leaks, to avoid quadratic complexity
669 // in LeakReport::AddLeakedChunk(). We don't expect to ever see this many leaks
670 // in real-world applications.
671 // FIXME: Get rid of this limit by changing the implementation of LeakReport to
672 // use a hash table.
673 const uptr kMaxLeaksConsidered = 5000;
674 
675 void LeakReport::AddLeakedChunk(uptr chunk, u32 stack_trace_id,
676                                 uptr leaked_size, ChunkTag tag) {
677   CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
678   bool is_directly_leaked = (tag == kDirectlyLeaked);
679   uptr i;
680   for (i = 0; i < leaks_.size(); i++) {
681     if (leaks_[i].stack_trace_id == stack_trace_id &&
682         leaks_[i].is_directly_leaked == is_directly_leaked) {
683       leaks_[i].hit_count++;
684       leaks_[i].total_size += leaked_size;
685       break;
686     }
687   }
688   if (i == leaks_.size()) {
689     if (leaks_.size() == kMaxLeaksConsidered) return;
690     Leak leak = { next_id_++, /* hit_count */ 1, leaked_size, stack_trace_id,
691                   is_directly_leaked, /* is_suppressed */ false };
692     leaks_.push_back(leak);
693   }
694   if (flags()->report_objects) {
695     LeakedObject obj = {leaks_[i].id, chunk, leaked_size};
696     leaked_objects_.push_back(obj);
697   }
698 }
699 
700 static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
701   if (leak1.is_directly_leaked == leak2.is_directly_leaked)
702     return leak1.total_size > leak2.total_size;
703   else
704     return leak1.is_directly_leaked;
705 }
706 
707 void LeakReport::ReportTopLeaks(uptr num_leaks_to_report) {
708   CHECK(leaks_.size() <= kMaxLeaksConsidered);
709   Printf("\n");
710   if (leaks_.size() == kMaxLeaksConsidered)
711     Printf("Too many leaks! Only the first %zu leaks encountered will be "
712            "reported.\n",
713            kMaxLeaksConsidered);
714 
715   uptr unsuppressed_count = UnsuppressedLeakCount();
716   if (num_leaks_to_report > 0 && num_leaks_to_report < unsuppressed_count)
717     Printf("The %zu top leak(s):\n", num_leaks_to_report);
718   Sort(leaks_.data(), leaks_.size(), &LeakComparator);
719   uptr leaks_reported = 0;
720   for (uptr i = 0; i < leaks_.size(); i++) {
721     if (leaks_[i].is_suppressed) continue;
722     PrintReportForLeak(i);
723     leaks_reported++;
724     if (leaks_reported == num_leaks_to_report) break;
725   }
726   if (leaks_reported < unsuppressed_count) {
727     uptr remaining = unsuppressed_count - leaks_reported;
728     Printf("Omitting %zu more leak(s).\n", remaining);
729   }
730 }
731 
732 void LeakReport::PrintReportForLeak(uptr index) {
733   Decorator d;
734   Printf("%s", d.Leak());
735   Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
736          leaks_[index].is_directly_leaked ? "Direct" : "Indirect",
737          leaks_[index].total_size, leaks_[index].hit_count);
738   Printf("%s", d.Default());
739 
740   PrintStackTraceById(leaks_[index].stack_trace_id);
741 
742   if (flags()->report_objects) {
743     Printf("Objects leaked above:\n");
744     PrintLeakedObjectsForLeak(index);
745     Printf("\n");
746   }
747 }
748 
749 void LeakReport::PrintLeakedObjectsForLeak(uptr index) {
750   u32 leak_id = leaks_[index].id;
751   for (uptr j = 0; j < leaked_objects_.size(); j++) {
752     if (leaked_objects_[j].leak_id == leak_id)
753       Printf("%p (%zu bytes)\n", leaked_objects_[j].addr,
754              leaked_objects_[j].size);
755   }
756 }
757 
758 void LeakReport::PrintSummary() {
759   CHECK(leaks_.size() <= kMaxLeaksConsidered);
760   uptr bytes = 0, allocations = 0;
761   for (uptr i = 0; i < leaks_.size(); i++) {
762       if (leaks_[i].is_suppressed) continue;
763       bytes += leaks_[i].total_size;
764       allocations += leaks_[i].hit_count;
765   }
766   InternalScopedString summary(kMaxSummaryLength);
767   summary.append("%zu byte(s) leaked in %zu allocation(s).", bytes,
768                  allocations);
769   ReportErrorSummary(summary.data());
770 }
771 
772 void LeakReport::ApplySuppressions() {
773   for (uptr i = 0; i < leaks_.size(); i++) {
774     Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
775     if (s) {
776       s->weight += leaks_[i].total_size;
777       atomic_store_relaxed(&s->hit_count, atomic_load_relaxed(&s->hit_count) +
778           leaks_[i].hit_count);
779       leaks_[i].is_suppressed = true;
780     }
781   }
782 }
783 
784 uptr LeakReport::UnsuppressedLeakCount() {
785   uptr result = 0;
786   for (uptr i = 0; i < leaks_.size(); i++)
787     if (!leaks_[i].is_suppressed) result++;
788   return result;
789 }
790 
791 } // namespace __lsan
792 #else // CAN_SANITIZE_LEAKS
793 namespace __lsan {
794 void InitCommonLsan() { }
795 void DoLeakCheck() { }
796 void DoRecoverableLeakCheckVoid() { }
797 void DisableInThisThread() { }
798 void EnableInThisThread() { }
799 }
800 #endif // CAN_SANITIZE_LEAKS
801 
802 using namespace __lsan;
803 
804 extern "C" {
805 SANITIZER_INTERFACE_ATTRIBUTE
806 void __lsan_ignore_object(const void *p) {
807 #if CAN_SANITIZE_LEAKS
808   if (!common_flags()->detect_leaks)
809     return;
810   // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
811   // locked.
812   BlockingMutexLock l(&global_mutex);
813   IgnoreObjectResult res = IgnoreObjectLocked(p);
814   if (res == kIgnoreObjectInvalid)
815     VReport(1, "__lsan_ignore_object(): no heap object found at %p", p);
816   if (res == kIgnoreObjectAlreadyIgnored)
817     VReport(1, "__lsan_ignore_object(): "
818            "heap object at %p is already being ignored\n", p);
819   if (res == kIgnoreObjectSuccess)
820     VReport(1, "__lsan_ignore_object(): ignoring heap object at %p\n", p);
821 #endif // CAN_SANITIZE_LEAKS
822 }
823 
824 SANITIZER_INTERFACE_ATTRIBUTE
825 void __lsan_register_root_region(const void *begin, uptr size) {
826 #if CAN_SANITIZE_LEAKS
827   BlockingMutexLock l(&global_mutex);
828   CHECK(root_regions);
829   RootRegion region = {reinterpret_cast<uptr>(begin), size};
830   root_regions->push_back(region);
831   VReport(1, "Registered root region at %p of size %llu\n", begin, size);
832 #endif // CAN_SANITIZE_LEAKS
833 }
834 
835 SANITIZER_INTERFACE_ATTRIBUTE
836 void __lsan_unregister_root_region(const void *begin, uptr size) {
837 #if CAN_SANITIZE_LEAKS
838   BlockingMutexLock l(&global_mutex);
839   CHECK(root_regions);
840   bool removed = false;
841   for (uptr i = 0; i < root_regions->size(); i++) {
842     RootRegion region = (*root_regions)[i];
843     if (region.begin == reinterpret_cast<uptr>(begin) && region.size == size) {
844       removed = true;
845       uptr last_index = root_regions->size() - 1;
846       (*root_regions)[i] = (*root_regions)[last_index];
847       root_regions->pop_back();
848       VReport(1, "Unregistered root region at %p of size %llu\n", begin, size);
849       break;
850     }
851   }
852   if (!removed) {
853     Report(
854         "__lsan_unregister_root_region(): region at %p of size %llu has not "
855         "been registered.\n",
856         begin, size);
857     Die();
858   }
859 #endif // CAN_SANITIZE_LEAKS
860 }
861 
862 SANITIZER_INTERFACE_ATTRIBUTE
863 void __lsan_disable() {
864 #if CAN_SANITIZE_LEAKS
865   __lsan::DisableInThisThread();
866 #endif
867 }
868 
869 SANITIZER_INTERFACE_ATTRIBUTE
870 void __lsan_enable() {
871 #if CAN_SANITIZE_LEAKS
872   __lsan::EnableInThisThread();
873 #endif
874 }
875 
876 SANITIZER_INTERFACE_ATTRIBUTE
877 void __lsan_do_leak_check() {
878 #if CAN_SANITIZE_LEAKS
879   if (common_flags()->detect_leaks)
880     __lsan::DoLeakCheck();
881 #endif // CAN_SANITIZE_LEAKS
882 }
883 
884 SANITIZER_INTERFACE_ATTRIBUTE
885 int __lsan_do_recoverable_leak_check() {
886 #if CAN_SANITIZE_LEAKS
887   if (common_flags()->detect_leaks)
888     return __lsan::DoRecoverableLeakCheck();
889 #endif // CAN_SANITIZE_LEAKS
890   return 0;
891 }
892 
893 SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_options, void) {
894   return "";
895 }
896 
897 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
898 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
899 int __lsan_is_turned_off() {
900   return 0;
901 }
902 
903 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
904 const char *__lsan_default_suppressions() {
905   return "";
906 }
907 #endif
908 } // extern "C"
909