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