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