lsan_common.cc revision 2946f13d6ca0cfc46d74c12e97dc40a17a7d232f
108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//=-- lsan_common.cc ------------------------------------------------------===//
208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//
308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//                     The LLVM Compiler Infrastructure
408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//
508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project// This file is distributed under the University of Illinois Open Source
608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project// License. See LICENSE.TXT for details.
708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//
808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//===----------------------------------------------------------------------===//
908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//
1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project// This file is a part of LeakSanitizer.
1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project// Implementation of common leak checking functionality.
1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//
1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project//===----------------------------------------------------------------------===//
1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project#include "lsan_common.h"
1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root#include "sanitizer_common/sanitizer_common.h"
1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project#include "sanitizer_common/sanitizer_flags.h"
1990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom#include "sanitizer_common/sanitizer_placement_new.h"
20f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom#include "sanitizer_common/sanitizer_stackdepot.h"
21d05ac5ff95fa7d673de209a780d5f9b4f106e50dKenny Root#include "sanitizer_common/sanitizer_stacktrace.h"
22f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom#include "sanitizer_common/sanitizer_stoptheworld.h"
236224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom#include "sanitizer_common/sanitizer_suppressions.h"
246224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom#include "sanitizer_common/sanitizer_report_decorator.h"
25f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root
26f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root#if CAN_SANITIZE_LEAKS
27f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Rootnamespace __lsan {
28f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root
29098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom// This mutex is used to prevent races between DoLeakCheck and IgnoreObject.
30f52606090f0f7160c2c7a85069959c1124151d79Brian CarlstromBlockingMutex global_mutex(LINKER_INITIALIZED);
312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3236e383e2f9c447e05adcca4426d8b33b2ef73ca7Kenny RootTHREADLOCAL int disable_counter;
33f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Rootbool DisabledInThisThread() { return disable_counter > 0; }
34f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root
35f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny RootFlags lsan_flags;
362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootstatic void InitializeFlags() {
3861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom  Flags *f = flags();
3961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom  // Default values.
4061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom  f->report_objects = false;
4161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom  f->resolution = 0;
42098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom  f->max_leaks = 0;
43f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root  f->exitcode = 23;
44987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root  f->suppressions="";
45f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root  f->use_registers = true;
46f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom  f->use_globals = true;
476224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  f->use_stacks = true;
48f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  f->use_tls = true;
4908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project  f->use_unaligned = false;
501f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom  f->verbosity = 0;
5108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project  f->log_pointers = false;
521f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom  f->log_threads = false;
5308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
54f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  const char *options = GetEnv("LSAN_OPTIONS");
5508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project  if (options) {
56923e3c5a80a6daefc14d4d0242ac46f23ac41b6aKenny Root    ParseFlag(options, &f->use_registers, "use_registers");
57eaeedc318b5fba9995fc64d15341017ec182fe4cKenny Root    ParseFlag(options, &f->use_globals, "use_globals");
58eaeedc318b5fba9995fc64d15341017ec182fe4cKenny Root    ParseFlag(options, &f->use_stacks, "use_stacks");
59923e3c5a80a6daefc14d4d0242ac46f23ac41b6aKenny Root    ParseFlag(options, &f->use_tls, "use_tls");
60eaeedc318b5fba9995fc64d15341017ec182fe4cKenny Root    ParseFlag(options, &f->use_unaligned, "use_unaligned");
61eaeedc318b5fba9995fc64d15341017ec182fe4cKenny Root    ParseFlag(options, &f->report_objects, "report_objects");
62e66dbe5ad60417a4a9bf5ddf0bc3eb02652e43c8Justin Morey    ParseFlag(options, &f->resolution, "resolution");
63e66dbe5ad60417a4a9bf5ddf0bc3eb02652e43c8Justin Morey    CHECK_GE(&f->resolution, 0);
64e66dbe5ad60417a4a9bf5ddf0bc3eb02652e43c8Justin Morey    ParseFlag(options, &f->max_leaks, "max_leaks");
65eaeedc318b5fba9995fc64d15341017ec182fe4cKenny Root    CHECK_GE(&f->max_leaks, 0);
66923e3c5a80a6daefc14d4d0242ac46f23ac41b6aKenny Root    ParseFlag(options, &f->verbosity, "verbosity");
67923e3c5a80a6daefc14d4d0242ac46f23ac41b6aKenny Root    ParseFlag(options, &f->log_pointers, "log_pointers");
68923e3c5a80a6daefc14d4d0242ac46f23ac41b6aKenny Root    ParseFlag(options, &f->log_threads, "log_threads");
69f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    ParseFlag(options, &f->exitcode, "exitcode");
7008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    ParseFlag(options, &f->suppressions, "suppressions");
7108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project  }
72f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom}
73f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
74a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny RootSuppressionContext *suppression_ctx;
75a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
76a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Rootvoid InitializeSuppressions() {
7738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  CHECK(!suppression_ctx);
78a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root  ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
7938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  suppression_ctx = new(placeholder_) SuppressionContext;
8061baefce87ed97b30e316469d69715503eea8996Kenny Root  char *suppressions_from_file;
8138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  uptr buffer_size;
82a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root  if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
8338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice                       &buffer_size, 1 << 26 /* max_len */))
84a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root    suppression_ctx->Parse(suppressions_from_file);
8538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  if (flags()->suppressions[0] && !buffer_size) {
86a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root    Printf("LeakSanitizer: failed to read suppressions file '%s'\n",
8738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice           flags()->suppressions);
88a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root    Die();
8938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  }
9047cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root  if (&__lsan_default_suppressions)
9138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    suppression_ctx->Parse(__lsan_default_suppressions());
920084d3b527f2da12fab2ed45914f172b84e50c20Kenny Root}
930084d3b527f2da12fab2ed45914f172b84e50c20Kenny Root
9408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectvoid InitCommonLsan() {
95f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  InitializeFlags();
9638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  InitializeSuppressions();
9738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  InitializePlatformSpecificModules();
9808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project}
9938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
100aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass Decorator: private __sanitizer::AnsiColorDecorator {
101f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom public:
10238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
103e4b82368b271aa959783814dde0087c84aed53b5Kenny Root  const char *Error() { return Red(); }
10438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  const char *Leak() { return Blue(); }
105bad843cfc413e5ccb61bacc426a204def0687e69Kenny Root  const char *End() { return Default(); }
10638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice};
107a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root
10838c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dicestatic inline bool CanBeAHeapPointer(uptr p) {
1098b7521eb38878822be3817270cc074ee1e22095dKenny Root  // Since our heap is located in mmap-ed memory, we can assume a sensible lower
11038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  // bound on heap addresses.
1118b7521eb38878822be3817270cc074ee1e22095dKenny Root  const uptr kMinAddress = 4 * 4096;
11238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  if (p < kMinAddress) return false;
113f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom#ifdef __x86_64__
11438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  // Accept only canonical form user-space addresses.
11534558f485bbfe7ca12622f59427321da11cb108dKenny Root  return ((p >> 47) == 0);
11638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice#else
117aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  return true;
11838c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice#endif
119aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root}
12038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
121aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// Scans the memory range, looking for byte patterns that point into allocator
12238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice// chunks. Marks those chunks with |tag| and adds them to |frontier|.
123aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// There are two usage modes for this function: finding reachable or ignored
124f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root// chunks (|tag| = kReachable or kIgnored) and finding indirectly leaked chunks
125f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
126f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root// so |frontier| = 0.
127f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Rootvoid ScanRangeForPointers(uptr begin, uptr end,
128f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root                          Frontier *frontier,
129f24ba0620d88b7d71ddb089b97d29fb1b073718dKenny Root                          const char *region_type, ChunkTag tag) {
13038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  const uptr alignment = flags()->pointer_alignment();
131aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  if (flags()->log_pointers)
13238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    Report("Scanning %s range %p-%p.\n", region_type, begin, end);
1336e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root  uptr pp = begin;
13438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  if (pp % alignment)
1356e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    pp = pp + alignment - pp % alignment;
1366e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root  for (; pp + sizeof(void *) <= end; pp += alignment) {  // NOLINT
13738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    void *p = *reinterpret_cast<void **>(pp);
138098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom    if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
1396e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    uptr chunk = PointsIntoChunk(p);
14038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    if (!chunk) continue;
141098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom    LsanMetadata m(chunk);
1426e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    // Reachable beats ignored beats leaked.
14338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    if (m.tag() == kReachable) continue;
144098faff2d757d91d9fd387a16053f55e1b4d5a5cBrian Carlstrom    if (m.tag() == kIgnored && tag != kReachable) continue;
1456e7efe14188211dc0f8a2e08276556e871fd8748Kenny Root    m.set_tag(tag);
146aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    if (flags()->log_pointers)
147aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root      Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
148aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root             chunk, chunk + m.requested_size(), m.requested_size());
14938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    if (frontier)
150aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root      frontier->push_back(chunk);
151aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  }
152aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root}
153aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root
15438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice// Scans thread data (stacks and TLS) for heap pointers.
155aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootstatic void ProcessThreads(SuspendedThreadsList const &suspended_threads,
15638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice                           Frontier *frontier) {
157aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount());
158aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  uptr registers_begin = reinterpret_cast<uptr>(registers.data());
159aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  uptr registers_end = registers_begin + registers.size();
160aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root  for (uptr i = 0; i < suspended_threads.thread_count(); i++) {
161aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i));
16238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    if (flags()->log_threads) Report("Processing thread %d.\n", os_id);
163aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
16460f83802801e224b51afac6c27c19e7c3d65ddc3Alex Klyubin    bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
16560f83802801e224b51afac6c27c19e7c3d65ddc3Alex Klyubin                                              &tls_begin, &tls_end,
16638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice                                              &cache_begin, &cache_end);
167aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    if (!thread_found) {
16838c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice      // If a thread can't be found in the thread registry, it's probably in the
169aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root      // process of destruction. Log this event and move on.
17038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice      if (flags()->log_threads)
171aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root        Report("Thread %d not found in registry.\n", os_id);
17238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice      continue;
173aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root    }
1747b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root    uptr sp;
1757b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root    bool have_registers =
1767b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root        (suspended_threads.GetRegistersAndSP(i, registers.data(), &sp) == 0);
1777b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root    if (!have_registers) {
1787b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root      Report("Unable to get registers from thread %d.\n");
1797b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root      // If unable to get SP, consider the entire stack to be reachable.
1807b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root      sp = stack_begin;
1817b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root    }
1827b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root
1837b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root    if (flags()->use_registers && have_registers)
1847b27ca77c328e510a165712a497c20b67c68e8a3Kenny Root      ScanRangeForPointers(registers_begin, registers_end, frontier,
1858b7521eb38878822be3817270cc074ee1e22095dKenny Root                           "REGISTERS", kReachable);
1868b7521eb38878822be3817270cc074ee1e22095dKenny Root
1878b7521eb38878822be3817270cc074ee1e22095dKenny Root    if (flags()->use_stacks) {
1888b7521eb38878822be3817270cc074ee1e22095dKenny Root      if (flags()->log_threads)
1898b7521eb38878822be3817270cc074ee1e22095dKenny Root        Report("Stack at %p-%p, SP = %p.\n", stack_begin, stack_end, sp);
1908b7521eb38878822be3817270cc074ee1e22095dKenny Root      if (sp < stack_begin || sp >= stack_end) {
1918b7521eb38878822be3817270cc074ee1e22095dKenny Root        // SP is outside the recorded stack range (e.g. the thread is running a
1928b7521eb38878822be3817270cc074ee1e22095dKenny Root        // signal handler on alternate stack). Again, consider the entire stack
1938b7521eb38878822be3817270cc074ee1e22095dKenny Root        // range to be reachable.
1948b7521eb38878822be3817270cc074ee1e22095dKenny Root        if (flags()->log_threads)
1958b7521eb38878822be3817270cc074ee1e22095dKenny Root          Report("WARNING: stack pointer not in stack range.\n");
1968b7521eb38878822be3817270cc074ee1e22095dKenny Root      } else {
197c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        // Shrink the stack range to ignore out-of-scope values.
198c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        stack_begin = sp;
199c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root      }
200c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root      ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
201c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root                           kReachable);
202c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root    }
203c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root
204c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root    if (flags()->use_tls) {
205c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root      if (flags()->log_threads) Report("TLS at %p-%p.\n", tls_begin, tls_end);
206c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root      if (cache_begin == cache_end) {
207c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
208c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root      } else {
209c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        // Because LSan should not be loaded with dlopen(), we can assume
210c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        // that allocator cache will be part of static TLS image.
211c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        CHECK_LE(tls_begin, cache_begin);
212c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        CHECK_GE(tls_end, cache_end);
213c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        if (tls_begin < cache_begin)
214c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root          ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
215c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root                               kReachable);
216c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root        if (tls_end > cache_end)
21738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice          ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
2188b7521eb38878822be3817270cc074ee1e22095dKenny Root      }
21938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    }
2208b7521eb38878822be3817270cc074ee1e22095dKenny Root  }
22138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice}
2228b7521eb38878822be3817270cc074ee1e22095dKenny Root
22338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dicestatic void FloodFillTag(Frontier *frontier, ChunkTag tag) {
22447cc520bd63c1eabfdef23cbab10457701f2a395Kenny Root  while (frontier->size()) {
22538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    uptr next_chunk = frontier->back();
226c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root    frontier->pop_back();
22738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    LsanMetadata m(next_chunk);
228c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root    ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
22938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice                         "HEAP", tag);
230c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root  }
23138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice}
2328b7521eb38878822be3817270cc074ee1e22095dKenny Root
23338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice// ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
2348b7521eb38878822be3817270cc074ee1e22095dKenny Root// which are reachable from it as indirectly leaked.
23538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dicestatic void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
2368b7521eb38878822be3817270cc074ee1e22095dKenny Root  chunk = GetUserBegin(chunk);
23738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  LsanMetadata m(chunk);
2388b7521eb38878822be3817270cc074ee1e22095dKenny Root  if (m.allocated() && m.tag() != kReachable) {
23938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    ScanRangeForPointers(chunk, chunk + m.requested_size(),
2408b7521eb38878822be3817270cc074ee1e22095dKenny Root                         /* frontier */ 0, "HEAP", kIndirectlyLeaked);
24138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  }
2428b7521eb38878822be3817270cc074ee1e22095dKenny Root}
24338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
2448b7521eb38878822be3817270cc074ee1e22095dKenny Root// ForEachChunk callback. If chunk is marked as ignored, adds its address to
245d5107430b8606db5b49f2857c290c783082bbed3Alex Klyubin// frontier.
246d5107430b8606db5b49f2857c290c783082bbed3Alex Klyubinstatic void CollectIgnoredCb(uptr chunk, void *arg) {
24738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  CHECK(arg);
2488b7521eb38878822be3817270cc074ee1e22095dKenny Root  chunk = GetUserBegin(chunk);
24938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  LsanMetadata m(chunk);
2508b7521eb38878822be3817270cc074ee1e22095dKenny Root  if (m.allocated() && m.tag() == kIgnored)
25138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    reinterpret_cast<Frontier *>(arg)->push_back(chunk);
2528b7521eb38878822be3817270cc074ee1e22095dKenny Root}
25338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
2548b7521eb38878822be3817270cc074ee1e22095dKenny Root// Sets the appropriate tag on each chunk.
25538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dicestatic void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) {
2568b7521eb38878822be3817270cc074ee1e22095dKenny Root  // Holds the flood fill frontier.
25738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  Frontier frontier(GetPageSizeCached());
2588b7521eb38878822be3817270cc074ee1e22095dKenny Root
2598b7521eb38878822be3817270cc074ee1e22095dKenny Root  if (flags()->use_globals)
26038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    ProcessGlobalRegions(&frontier);
2618b7521eb38878822be3817270cc074ee1e22095dKenny Root  ProcessThreads(suspended_threads, &frontier);
26238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  FloodFillTag(&frontier, kReachable);
263c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root  // The check here is relatively expensive, so we do this in a separate flood
26438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  // fill. That way we can skip the check for chunks that are reachable
2658b7521eb38878822be3817270cc074ee1e22095dKenny Root  // otherwise.
26638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  ProcessPlatformSpecificAllocations(&frontier);
2678b7521eb38878822be3817270cc074ee1e22095dKenny Root  FloodFillTag(&frontier, kReachable);
26860f83802801e224b51afac6c27c19e7c3d65ddc3Alex Klyubin
26960f83802801e224b51afac6c27c19e7c3d65ddc3Alex Klyubin  if (flags()->log_pointers)
27082f6e22581a00a2acaaa932cf471e276d696965bAlex Klyubin    Report("Scanning ignored chunks.\n");
27182f6e22581a00a2acaaa932cf471e276d696965bAlex Klyubin  CHECK_EQ(0, frontier.size());
27282f6e22581a00a2acaaa932cf471e276d696965bAlex Klyubin  ForEachChunk(CollectIgnoredCb, &frontier);
273079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom  FloodFillTag(&frontier, kIgnored);
274f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
27538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  // Iterate over leaked chunks and mark those that are reachable from other
276079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom  // leaked chunks.
27738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  if (flags()->log_pointers)
278079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom    Report("Scanning leaked chunks.\n");
27938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */);
280079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom}
281079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom
282f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstromstatic void PrintStackTraceById(u32 stack_trace_id) {
28338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  CHECK(stack_trace_id);
284e4b82368b271aa959783814dde0087c84aed53b5Kenny Root  uptr size = 0;
285652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  const uptr *trace = StackDepotGet(stack_trace_id, &size);
286975772cf55d83f29a24d57d0132d32a22af32f7fKenny Root  StackTrace::PrintStack(trace, size, common_flags()->symbolize,
28738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice                         common_flags()->strip_path_prefix, 0);
2882ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom}
289652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root
290652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root// ForEachChunk callback. Aggregates unreachable chunks into a LeakReport.
291f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstromstatic void CollectLeaksCb(uptr chunk, void *arg) {
29208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project  CHECK(arg);
293f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
294652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  chunk = GetUserBegin(chunk);
295f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  LsanMetadata m(chunk);
296652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  if (!m.allocated()) return;
297652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
29808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    uptr resolution = flags()->resolution;
299652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root    if (resolution > 0) {
30008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project      uptr size = 0;
301e4b82368b271aa959783814dde0087c84aed53b5Kenny Root      const uptr *trace = StackDepotGet(m.stack_trace_id(), &size);
302e4b82368b271aa959783814dde0087c84aed53b5Kenny Root      size = Min(size, resolution);
303652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root      leak_report->Add(StackDepotPut(trace, size), m.requested_size(), m.tag());
304652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root    } else {
305e4b82368b271aa959783814dde0087c84aed53b5Kenny Root      leak_report->Add(m.stack_trace_id(), m.requested_size(), m.tag());
306652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root    }
307e4b82368b271aa959783814dde0087c84aed53b5Kenny Root  }
308652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root}
309e4b82368b271aa959783814dde0087c84aed53b5Kenny Root
31008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project// ForEachChunkCallback. Prints addresses of unreachable chunks.
311f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstromstatic void PrintLeakedCb(uptr chunk, void *arg) {
312652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  chunk = GetUserBegin(chunk);
313bad843cfc413e5ccb61bacc426a204def0687e69Kenny Root  LsanMetadata m(chunk);
314652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  if (!m.allocated()) return;
315bad843cfc413e5ccb61bacc426a204def0687e69Kenny Root  if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
316bad843cfc413e5ccb61bacc426a204def0687e69Kenny Root    Printf("%s leaked %zu byte object at %p.\n",
317652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root           m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly",
318652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root           m.requested_size(), chunk);
319bad843cfc413e5ccb61bacc426a204def0687e69Kenny Root  }
320652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root}
321f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
322652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Rootstatic void PrintMatchedSuppressions() {
32398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom  InternalMmapVector<Suppression *> matched(1);
324f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  suppression_ctx->GetMatched(&matched);
325652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root  if (!matched.size())
32638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    return;
327f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom  const char *line = "-----------------------------------------------------";
328bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  Printf("%s\n", line);
329bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  Printf("Suppressions used:\n");
330bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  Printf("  count      bytes template\n");
33138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  for (uptr i = 0; i < matched.size(); i++)
332bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root    Printf("%7zu %10zu %s\n", static_cast<uptr>(matched[i]->hit_count),
33338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice           matched[i]->weight, matched[i]->templ);
334bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  Printf("%s\n\n", line);
335bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root}
33638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
3371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootstatic void PrintLeaked() {
338bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  Printf("\n");
33938c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  Printf("Reporting individual objects:\n");
340987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root  ForEachChunk(PrintLeakedCb, 0 /* arg */);
341bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root}
34238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice
3431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootstruct DoLeakCheckParam {
34438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  bool success;
3451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root  LeakReport leak_report;
34638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice};
3471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root
34838c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dicestatic void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
349f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root                                void *arg) {
35038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
3511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root  CHECK(param);
35238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  CHECK(!param->success);
353ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root  CHECK(param->leak_report.IsEmpty());
35438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice  ClassifyAllChunks(suspended_threads);
355bc4717526951c5dc5228970cd149bf6bfb5876fbKenny Root  ForEachChunk(CollectLeaksCb, &param->leak_report);
35698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom  if (!param->leak_report.IsEmpty() && flags()->report_objects)
35798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    PrintLeaked();
35898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom  param->success = true;
35998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom}
36098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
36198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromvoid DoLeakCheck() {
36298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom  EnsureMainThreadIDIsCorrect();
36398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom  BlockingMutexLock l(&global_mutex);
3642296bd6bf1d43d1ebceaabbb556d5542d529d311Kenny Root  static bool already_done;
3652296bd6bf1d43d1ebceaabbb556d5542d529d311Kenny Root  if (already_done) return;
3663a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  already_done = true;
3673a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  if (&__lsan_is_turned_off && __lsan_is_turned_off())
368c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root    return;
369c6e93518bda6c5bc2959641711eca9d9078fb530Kenny Root
3703a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  DoLeakCheckParam param;
3713a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  param.success = false;
3723a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  LockThreadRegistry();
3733a0a06c3fe017c9454dd181555b6904dd88d1002Kenny Root  LockAllocator();
3746224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  StopTheWorld(DoLeakCheckCallback, &param);
3756224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  UnlockAllocator();
3766224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  UnlockThreadRegistry();
3776224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom
3786224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  if (!param.success) {
3796224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom    Report("LeakSanitizer has encountered a fatal error.\n");
3806224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom    Die();
3816224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  }
3826224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  uptr have_unsuppressed = param.leak_report.ApplySuppressions();
3836224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  if (have_unsuppressed) {
3846224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom    Decorator d;
3852a4faf6763b502c98d13bf79d1c9fba223b698c7Kenny Root    Printf("\n"
3862a4faf6763b502c98d13bf79d1c9fba223b698c7Kenny Root           "================================================================="
3872a4faf6763b502c98d13bf79d1c9fba223b698c7Kenny Root           "\n");
3882a4faf6763b502c98d13bf79d1c9fba223b698c7Kenny Root    Printf("%s", d.Error());
3892a4faf6763b502c98d13bf79d1c9fba223b698c7Kenny Root    Report("ERROR: LeakSanitizer: detected memory leaks\n");
3906224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom    Printf("%s", d.End());
3916224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom    param.leak_report.PrintLargest(flags()->max_leaks);
3926224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  }
3936224c2e60c987d560cb5d76aa6af4c185ce87768Brian Carlstrom  if (have_unsuppressed || (flags()->verbosity >= 1)) {
39432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    PrintMatchedSuppressions();
39532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    param.leak_report.PrintSummary();
39632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
39732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (have_unsuppressed && flags()->exitcode)
39832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    internal__exit(flags()->exitcode);
39932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
40032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
40132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootstatic Suppression *GetSuppressionForAddr(uptr addr) {
40232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  static const uptr kMaxAddrFrames = 16;
40332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
40432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
40532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr addr_frames_num =
40632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
40732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < addr_frames_num; i++) {
40832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Suppression* s;
40932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||
41032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s) ||
41132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        suppression_ctx->Match(addr_frames[i].module, SuppressionLeak, &s))
41232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      return s;
41332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
41432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  return 0;
41532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
41632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
41732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootstatic Suppression *GetSuppressionForStack(u32 stack_trace_id) {
41832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr size = 0;
41932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  const uptr *trace = StackDepotGet(stack_trace_id, &size);
420e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root  for (uptr i = 0; i < size; i++) {
421e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root    Suppression *s =
42232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        GetSuppressionForAddr(StackTrace::GetPreviousInstructionPc(trace[i]));
42332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (s) return s;
42432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
42532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  return 0;
42632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
42732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
42832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root///// LeakReport implementation. /////
429f0bb425ede548a3771bb69273eb85ad7fdde1befKenny Root
430f0bb425ede548a3771bb69273eb85ad7fdde1befKenny Root// A hard limit on the number of distinct leaks, to avoid quadratic complexity
431f0bb425ede548a3771bb69273eb85ad7fdde1befKenny Root// in LeakReport::Add(). We don't expect to ever see this many leaks in
432f0bb425ede548a3771bb69273eb85ad7fdde1befKenny Root// real-world applications.
43332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root// FIXME: Get rid of this limit by changing the implementation of LeakReport to
43432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root// use a hash table.
43532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootconst uptr kMaxLeaksConsidered = 5000;
43632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
43732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid LeakReport::Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag) {
43832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
43932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  bool is_directly_leaked = (tag == kDirectlyLeaked);
44032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < leaks_.size(); i++)
44132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (leaks_[i].stack_trace_id == stack_trace_id &&
44232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root        leaks_[i].is_directly_leaked == is_directly_leaked) {
44332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      leaks_[i].hit_count++;
44432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      leaks_[i].total_size += leaked_size;
44532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      return;
44632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
44732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (leaks_.size() == kMaxLeaksConsidered) return;
44832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  Leak leak = { /* hit_count */ 1, leaked_size, stack_trace_id,
44932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                is_directly_leaked, /* is_suppressed */ false };
45032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  leaks_.push_back(leak);
45132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
45232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
45332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootstatic bool LeakComparator(const Leak &leak1, const Leak &leak2) {
45432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (leak1.is_directly_leaked == leak2.is_directly_leaked)
45532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    return leak1.total_size > leak2.total_size;
45632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  else
45732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    return leak1.is_directly_leaked;
45832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
45932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
46032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid LeakReport::PrintLargest(uptr num_leaks_to_print) {
46136e383e2f9c447e05adcca4426d8b33b2ef73ca7Kenny Root  CHECK(leaks_.size() <= kMaxLeaksConsidered);
46236e383e2f9c447e05adcca4426d8b33b2ef73ca7Kenny Root  Printf("\n");
46332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (leaks_.size() == kMaxLeaksConsidered)
46432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Printf("Too many leaks! Only the first %zu leaks encountered will be "
46532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root           "reported.\n",
46632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root           kMaxLeaksConsidered);
46732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
46832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr unsuppressed_count = 0;
46932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < leaks_.size(); i++)
47032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (!leaks_[i].is_suppressed) unsuppressed_count++;
47132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (num_leaks_to_print > 0 && num_leaks_to_print < unsuppressed_count)
47232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Printf("The %zu largest leak(s):\n", num_leaks_to_print);
47332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  InternalSort(&leaks_, leaks_.size(), LeakComparator);
47432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr leaks_printed = 0;
47532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  Decorator d;
47632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < leaks_.size(); i++) {
47732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (leaks_[i].is_suppressed) continue;
4787c3263f16bae0f1b2125de2c3c1c683303e768ceKenny Root    Printf("%s", d.Leak());
47932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
48032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root           leaks_[i].is_directly_leaked ? "Direct" : "Indirect",
48132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root           leaks_[i].total_size, leaks_[i].hit_count);
48232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Printf("%s", d.End());
48332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    PrintStackTraceById(leaks_[i].stack_trace_id);
48432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Printf("\n");
48532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    leaks_printed++;
48635beb3047b2b8ffc019f8218989a0255cc5e3818Kenny Root    if (leaks_printed == num_leaks_to_print) break;
48735beb3047b2b8ffc019f8218989a0255cc5e3818Kenny Root  }
48832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (leaks_printed < unsuppressed_count) {
48932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    uptr remaining = unsuppressed_count - leaks_printed;
4909ec4f876b0b8e2b659728d0468492cde3763ad5dKenny Root    Printf("Omitting %zu more leak(s).\n", remaining);
4919ec4f876b0b8e2b659728d0468492cde3763ad5dKenny Root  }
49232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
49332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
49432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid LeakReport::PrintSummary() {
49532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  CHECK(leaks_.size() <= kMaxLeaksConsidered);
49632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr bytes = 0, allocations = 0;
49732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < leaks_.size(); i++) {
49832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      if (leaks_[i].is_suppressed) continue;
49932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      bytes += leaks_[i].total_size;
50032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      allocations += leaks_[i].hit_count;
50132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
50232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  const int kMaxSummaryLength = 128;
50332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  InternalScopedBuffer<char> summary(kMaxSummaryLength);
50432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  internal_snprintf(summary.data(), kMaxSummaryLength,
50532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root                    "LeakSanitizer: %zu byte(s) leaked in %zu allocation(s).",
506e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root                    bytes, allocations);
507e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root  __sanitizer_report_error_summary(summary.data());
508e1429740ee37db9422d7622d11d32a29a4bc4301Kenny Root}
50932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
51032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootuptr LeakReport::ApplySuppressions() {
51132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  uptr unsuppressed_count = 0;
51232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  for (uptr i = 0; i < leaks_.size(); i++) {
51332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
51432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    if (s) {
51532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      s->weight += leaks_[i].total_size;
51632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      s->hit_count += leaks_[i].hit_count;
51732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root      leaks_[i].is_suppressed = true;
51832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    } else {
51932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    unsuppressed_count++;
52032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    }
52132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
52232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  return unsuppressed_count;
52332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
52432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}  // namespace __lsan
52532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif  // CAN_SANITIZE_LEAKS
52632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
52732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootusing namespace __lsan;  // NOLINT
52832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
52932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootextern "C" {
53032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny RootSANITIZER_INTERFACE_ATTRIBUTE
53132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid __lsan_ignore_object(const void *p) {
53232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#if CAN_SANITIZE_LEAKS
53332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
53432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  // locked.
53532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  BlockingMutexLock l(&global_mutex);
53632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  IgnoreObjectResult res = IgnoreObjectLocked(p);
53732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (res == kIgnoreObjectInvalid && flags()->verbosity >= 2)
53832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Report("__lsan_ignore_object(): no heap object found at %p", p);
53932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (res == kIgnoreObjectAlreadyIgnored && flags()->verbosity >= 2)
54032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Report("__lsan_ignore_object(): "
54132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root           "heap object at %p is already being ignored\n", p);
54232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (res == kIgnoreObjectSuccess && flags()->verbosity >= 3)
54332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Report("__lsan_ignore_object(): ignoring heap object at %p\n", p);
54432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif  // CAN_SANITIZE_LEAKS
54532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
54632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
54732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny RootSANITIZER_INTERFACE_ATTRIBUTE
54832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid __lsan_disable() {
54932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#if CAN_SANITIZE_LEAKS
55032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  __lsan::disable_counter++;
55132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif
55232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
55332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
55432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny RootSANITIZER_INTERFACE_ATTRIBUTE
55532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid __lsan_enable() {
55632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#if CAN_SANITIZE_LEAKS
55732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (!__lsan::disable_counter) {
55832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Report("Unmatched call to __lsan_enable().\n");
55932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    Die();
56032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  }
56132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  __lsan::disable_counter--;
56232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif
56332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
56432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
56532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny RootSANITIZER_INTERFACE_ATTRIBUTE
56632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootvoid __lsan_do_leak_check() {
56732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#if CAN_SANITIZE_LEAKS
56832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  if (common_flags()->detect_leaks)
56932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root    __lsan::DoLeakCheck();
57032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif  // CAN_SANITIZE_LEAKS
57132850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
57232850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root
57332850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#if !SANITIZER_SUPPORTS_WEAK_HOOKS
57432850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny RootSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
57532850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Rootint __lsan_is_turned_off() {
57632850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root  return 0;
57732850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}
57832850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root#endif
57932850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root}  // extern "C"
58032850b6ce29c70150cfe01c4ce2a1b353d92e6feKenny Root