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