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