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