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