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