lsan_common.cc revision 90b0f1e3ba126bb2e92ab51ef379c98782c23d90
1//=-- lsan_common.cc ------------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of LeakSanitizer. 11// Implementation of common leak checking functionality. 12// 13//===----------------------------------------------------------------------===// 14 15#include "lsan_common.h" 16 17#include "sanitizer_common/sanitizer_common.h" 18#include "sanitizer_common/sanitizer_flags.h" 19#include "sanitizer_common/sanitizer_placement_new.h" 20#include "sanitizer_common/sanitizer_stackdepot.h" 21#include "sanitizer_common/sanitizer_stacktrace.h" 22#include "sanitizer_common/sanitizer_stoptheworld.h" 23#include "sanitizer_common/sanitizer_suppressions.h" 24#include "sanitizer_common/sanitizer_report_decorator.h" 25 26#if CAN_SANITIZE_LEAKS 27namespace __lsan { 28 29// This mutex is used to prevent races between DoLeakCheck and IgnoreObject. 30BlockingMutex global_mutex(LINKER_INITIALIZED); 31 32THREADLOCAL int disable_counter; 33bool DisabledInThisThread() { return disable_counter > 0; } 34 35Flags lsan_flags; 36 37static void InitializeFlags() { 38 Flags *f = flags(); 39 // Default values. 40 f->report_objects = false; 41 f->resolution = 0; 42 f->max_leaks = 0; 43 f->exitcode = 23; 44 f->suppressions=""; 45 f->use_registers = true; 46 f->use_globals = true; 47 f->use_stacks = true; 48 f->use_tls = true; 49 f->use_unaligned = false; 50 f->verbosity = 0; 51 f->log_pointers = false; 52 f->log_threads = false; 53 54 const char *options = GetEnv("LSAN_OPTIONS"); 55 if (options) { 56 ParseFlag(options, &f->use_registers, "use_registers"); 57 ParseFlag(options, &f->use_globals, "use_globals"); 58 ParseFlag(options, &f->use_stacks, "use_stacks"); 59 ParseFlag(options, &f->use_tls, "use_tls"); 60 ParseFlag(options, &f->use_unaligned, "use_unaligned"); 61 ParseFlag(options, &f->report_objects, "report_objects"); 62 ParseFlag(options, &f->resolution, "resolution"); 63 CHECK_GE(&f->resolution, 0); 64 ParseFlag(options, &f->max_leaks, "max_leaks"); 65 CHECK_GE(&f->max_leaks, 0); 66 ParseFlag(options, &f->verbosity, "verbosity"); 67 ParseFlag(options, &f->log_pointers, "log_pointers"); 68 ParseFlag(options, &f->log_threads, "log_threads"); 69 ParseFlag(options, &f->exitcode, "exitcode"); 70 ParseFlag(options, &f->suppressions, "suppressions"); 71 } 72} 73 74SuppressionContext *suppression_ctx; 75 76void InitializeSuppressions() { 77 CHECK(!suppression_ctx); 78 ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)]; 79 suppression_ctx = new(placeholder_) SuppressionContext; 80 char *suppressions_from_file; 81 uptr buffer_size; 82 if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file, 83 &buffer_size, 1 << 26 /* max_len */)) 84 suppression_ctx->Parse(suppressions_from_file); 85 if (flags()->suppressions[0] && !buffer_size) { 86 Printf("LeakSanitizer: failed to read suppressions file '%s'\n", 87 flags()->suppressions); 88 Die(); 89 } 90 if (&__lsan_default_suppressions) 91 suppression_ctx->Parse(__lsan_default_suppressions()); 92} 93 94void InitCommonLsan() { 95 InitializeFlags(); 96 InitializeSuppressions(); 97 InitializePlatformSpecificModules(); 98} 99 100class Decorator: private __sanitizer::AnsiColorDecorator { 101 public: 102 Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { } 103 const char *Error() { return Red(); } 104 const char *Leak() { return Blue(); } 105 const char *End() { return Default(); } 106}; 107 108static inline bool CanBeAHeapPointer(uptr p) { 109 // Since our heap is located in mmap-ed memory, we can assume a sensible lower 110 // bound on heap addresses. 111 const uptr kMinAddress = 4 * 4096; 112 if (p < kMinAddress) return false; 113#ifdef __x86_64__ 114 // Accept only canonical form user-space addresses. 115 return ((p >> 47) == 0); 116#else 117 return true; 118#endif 119} 120 121// Scans the memory range, looking for byte patterns that point into allocator 122// chunks. Marks those chunks with |tag| and adds them to |frontier|. 123// There are two usage modes for this function: finding reachable or ignored 124// chunks (|tag| = kReachable or kIgnored) and finding indirectly leaked chunks 125// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill, 126// so |frontier| = 0. 127void ScanRangeForPointers(uptr begin, uptr end, 128 Frontier *frontier, 129 const char *region_type, ChunkTag tag) { 130 const uptr alignment = flags()->pointer_alignment(); 131 if (flags()->log_pointers) 132 Report("Scanning %s range %p-%p.\n", region_type, begin, end); 133 uptr pp = begin; 134 if (pp % alignment) 135 pp = pp + alignment - pp % alignment; 136 for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT 137 void *p = *reinterpret_cast<void **>(pp); 138 if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue; 139 uptr chunk = PointsIntoChunk(p); 140 if (!chunk) continue; 141 LsanMetadata m(chunk); 142 // Reachable beats ignored beats leaked. 143 if (m.tag() == kReachable) continue; 144 if (m.tag() == kIgnored && tag != kReachable) continue; 145 m.set_tag(tag); 146 if (flags()->log_pointers) 147 Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p, 148 chunk, chunk + m.requested_size(), m.requested_size()); 149 if (frontier) 150 frontier->push_back(chunk); 151 } 152} 153 154// Scans thread data (stacks and TLS) for heap pointers. 155static void ProcessThreads(SuspendedThreadsList const &suspended_threads, 156 Frontier *frontier) { 157 InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount()); 158 uptr registers_begin = reinterpret_cast<uptr>(registers.data()); 159 uptr registers_end = registers_begin + registers.size(); 160 for (uptr i = 0; i < suspended_threads.thread_count(); i++) { 161 uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i)); 162 if (flags()->log_threads) Report("Processing thread %d.\n", os_id); 163 uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end; 164 bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end, 165 &tls_begin, &tls_end, 166 &cache_begin, &cache_end); 167 if (!thread_found) { 168 // If a thread can't be found in the thread registry, it's probably in the 169 // process of destruction. Log this event and move on. 170 if (flags()->log_threads) 171 Report("Thread %d not found in registry.\n", os_id); 172 continue; 173 } 174 uptr sp; 175 bool have_registers = 176 (suspended_threads.GetRegistersAndSP(i, registers.data(), &sp) == 0); 177 if (!have_registers) { 178 Report("Unable to get registers from thread %d.\n"); 179 // If unable to get SP, consider the entire stack to be reachable. 180 sp = stack_begin; 181 } 182 183 if (flags()->use_registers && have_registers) 184 ScanRangeForPointers(registers_begin, registers_end, frontier, 185 "REGISTERS", kReachable); 186 187 if (flags()->use_stacks) { 188 if (flags()->log_threads) 189 Report("Stack at %p-%p, SP = %p.\n", stack_begin, stack_end, sp); 190 if (sp < stack_begin || sp >= stack_end) { 191 // SP is outside the recorded stack range (e.g. the thread is running a 192 // signal handler on alternate stack). Again, consider the entire stack 193 // range to be reachable. 194 if (flags()->log_threads) 195 Report("WARNING: stack pointer not in stack range.\n"); 196 } else { 197 // Shrink the stack range to ignore out-of-scope values. 198 stack_begin = sp; 199 } 200 ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", 201 kReachable); 202 } 203 204 if (flags()->use_tls) { 205 if (flags()->log_threads) Report("TLS at %p-%p.\n", tls_begin, tls_end); 206 if (cache_begin == cache_end) { 207 ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); 208 } else { 209 // Because LSan should not be loaded with dlopen(), we can assume 210 // that allocator cache will be part of static TLS image. 211 CHECK_LE(tls_begin, cache_begin); 212 CHECK_GE(tls_end, cache_end); 213 if (tls_begin < cache_begin) 214 ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", 215 kReachable); 216 if (tls_end > cache_end) 217 ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable); 218 } 219 } 220 } 221} 222 223static void FloodFillTag(Frontier *frontier, ChunkTag tag) { 224 while (frontier->size()) { 225 uptr next_chunk = frontier->back(); 226 frontier->pop_back(); 227 LsanMetadata m(next_chunk); 228 ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier, 229 "HEAP", tag); 230 } 231} 232 233// ForEachChunk callback. If the chunk is marked as leaked, marks all chunks 234// which are reachable from it as indirectly leaked. 235static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) { 236 chunk = GetUserBegin(chunk); 237 LsanMetadata m(chunk); 238 if (m.allocated() && m.tag() != kReachable) { 239 ScanRangeForPointers(chunk, chunk + m.requested_size(), 240 /* frontier */ 0, "HEAP", kIndirectlyLeaked); 241 } 242} 243 244// ForEachChunk callback. If chunk is marked as ignored, adds its address to 245// frontier. 246static void CollectIgnoredCb(uptr chunk, void *arg) { 247 CHECK(arg); 248 chunk = GetUserBegin(chunk); 249 LsanMetadata m(chunk); 250 if (m.allocated() && m.tag() == kIgnored) 251 reinterpret_cast<Frontier *>(arg)->push_back(chunk); 252} 253 254// Sets the appropriate tag on each chunk. 255static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) { 256 // Holds the flood fill frontier. 257 Frontier frontier(GetPageSizeCached()); 258 259 if (flags()->use_globals) 260 ProcessGlobalRegions(&frontier); 261 ProcessThreads(suspended_threads, &frontier); 262 FloodFillTag(&frontier, kReachable); 263 // The check here is relatively expensive, so we do this in a separate flood 264 // fill. That way we can skip the check for chunks that are reachable 265 // otherwise. 266 ProcessPlatformSpecificAllocations(&frontier); 267 FloodFillTag(&frontier, kReachable); 268 269 if (flags()->log_pointers) 270 Report("Scanning ignored chunks.\n"); 271 CHECK_EQ(0, frontier.size()); 272 ForEachChunk(CollectIgnoredCb, &frontier); 273 FloodFillTag(&frontier, kIgnored); 274 275 // Iterate over leaked chunks and mark those that are reachable from other 276 // leaked chunks. 277 if (flags()->log_pointers) 278 Report("Scanning leaked chunks.\n"); 279 ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */); 280} 281 282static void PrintStackTraceById(u32 stack_trace_id) { 283 CHECK(stack_trace_id); 284 uptr size = 0; 285 const uptr *trace = StackDepotGet(stack_trace_id, &size); 286 StackTrace::PrintStack(trace, size, common_flags()->symbolize, 0); 287} 288 289// ForEachChunk callback. Aggregates unreachable chunks into a LeakReport. 290static void CollectLeaksCb(uptr chunk, void *arg) { 291 CHECK(arg); 292 LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg); 293 chunk = GetUserBegin(chunk); 294 LsanMetadata m(chunk); 295 if (!m.allocated()) return; 296 if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) { 297 uptr resolution = flags()->resolution; 298 if (resolution > 0) { 299 uptr size = 0; 300 const uptr *trace = StackDepotGet(m.stack_trace_id(), &size); 301 size = Min(size, resolution); 302 leak_report->Add(StackDepotPut(trace, size), m.requested_size(), m.tag()); 303 } else { 304 leak_report->Add(m.stack_trace_id(), m.requested_size(), m.tag()); 305 } 306 } 307} 308 309// ForEachChunkCallback. Prints addresses of unreachable chunks. 310static void PrintLeakedCb(uptr chunk, void *arg) { 311 chunk = GetUserBegin(chunk); 312 LsanMetadata m(chunk); 313 if (!m.allocated()) return; 314 if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) { 315 Printf("%s leaked %zu byte object at %p.\n", 316 m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly", 317 m.requested_size(), chunk); 318 } 319} 320 321static void PrintMatchedSuppressions() { 322 InternalMmapVector<Suppression *> matched(1); 323 suppression_ctx->GetMatched(&matched); 324 if (!matched.size()) 325 return; 326 const char *line = "-----------------------------------------------------"; 327 Printf("%s\n", line); 328 Printf("Suppressions used:\n"); 329 Printf(" count bytes template\n"); 330 for (uptr i = 0; i < matched.size(); i++) 331 Printf("%7zu %10zu %s\n", static_cast<uptr>(matched[i]->hit_count), 332 matched[i]->weight, matched[i]->templ); 333 Printf("%s\n\n", line); 334} 335 336static void PrintLeaked() { 337 Printf("\n"); 338 Printf("Reporting individual objects:\n"); 339 ForEachChunk(PrintLeakedCb, 0 /* arg */); 340} 341 342struct DoLeakCheckParam { 343 bool success; 344 LeakReport leak_report; 345}; 346 347static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads, 348 void *arg) { 349 DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg); 350 CHECK(param); 351 CHECK(!param->success); 352 CHECK(param->leak_report.IsEmpty()); 353 ClassifyAllChunks(suspended_threads); 354 ForEachChunk(CollectLeaksCb, ¶m->leak_report); 355 if (!param->leak_report.IsEmpty() && flags()->report_objects) 356 PrintLeaked(); 357 param->success = true; 358} 359 360void DoLeakCheck() { 361 EnsureMainThreadIDIsCorrect(); 362 BlockingMutexLock l(&global_mutex); 363 static bool already_done; 364 if (already_done) return; 365 already_done = true; 366 if (&__lsan_is_turned_off && __lsan_is_turned_off()) 367 return; 368 369 DoLeakCheckParam param; 370 param.success = false; 371 LockThreadRegistry(); 372 LockAllocator(); 373 StopTheWorld(DoLeakCheckCallback, ¶m); 374 UnlockAllocator(); 375 UnlockThreadRegistry(); 376 377 if (!param.success) { 378 Report("LeakSanitizer has encountered a fatal error.\n"); 379 Die(); 380 } 381 uptr have_unsuppressed = param.leak_report.ApplySuppressions(); 382 if (have_unsuppressed) { 383 Decorator d; 384 Printf("\n" 385 "=================================================================" 386 "\n"); 387 Printf("%s", d.Error()); 388 Report("ERROR: LeakSanitizer: detected memory leaks\n"); 389 Printf("%s", d.End()); 390 param.leak_report.PrintLargest(flags()->max_leaks); 391 } 392 if (have_unsuppressed || (flags()->verbosity >= 1)) { 393 PrintMatchedSuppressions(); 394 param.leak_report.PrintSummary(); 395 } 396 if (have_unsuppressed && flags()->exitcode) 397 internal__exit(flags()->exitcode); 398} 399 400static Suppression *GetSuppressionForAddr(uptr addr) { 401 static const uptr kMaxAddrFrames = 16; 402 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 403 for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo(); 404 uptr addr_frames_num = 405 getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames); 406 for (uptr i = 0; i < addr_frames_num; i++) { 407 Suppression* s; 408 if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) || 409 suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s) || 410 suppression_ctx->Match(addr_frames[i].module, SuppressionLeak, &s)) 411 return s; 412 } 413 return 0; 414} 415 416static Suppression *GetSuppressionForStack(u32 stack_trace_id) { 417 uptr size = 0; 418 const uptr *trace = StackDepotGet(stack_trace_id, &size); 419 for (uptr i = 0; i < size; i++) { 420 Suppression *s = 421 GetSuppressionForAddr(StackTrace::GetPreviousInstructionPc(trace[i])); 422 if (s) return s; 423 } 424 return 0; 425} 426 427///// LeakReport implementation. ///// 428 429// A hard limit on the number of distinct leaks, to avoid quadratic complexity 430// in LeakReport::Add(). We don't expect to ever see this many leaks in 431// real-world applications. 432// FIXME: Get rid of this limit by changing the implementation of LeakReport to 433// use a hash table. 434const uptr kMaxLeaksConsidered = 5000; 435 436void LeakReport::Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag) { 437 CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked); 438 bool is_directly_leaked = (tag == kDirectlyLeaked); 439 for (uptr i = 0; i < leaks_.size(); i++) 440 if (leaks_[i].stack_trace_id == stack_trace_id && 441 leaks_[i].is_directly_leaked == is_directly_leaked) { 442 leaks_[i].hit_count++; 443 leaks_[i].total_size += leaked_size; 444 return; 445 } 446 if (leaks_.size() == kMaxLeaksConsidered) return; 447 Leak leak = { /* hit_count */ 1, leaked_size, stack_trace_id, 448 is_directly_leaked, /* is_suppressed */ false }; 449 leaks_.push_back(leak); 450} 451 452static bool LeakComparator(const Leak &leak1, const Leak &leak2) { 453 if (leak1.is_directly_leaked == leak2.is_directly_leaked) 454 return leak1.total_size > leak2.total_size; 455 else 456 return leak1.is_directly_leaked; 457} 458 459void LeakReport::PrintLargest(uptr num_leaks_to_print) { 460 CHECK(leaks_.size() <= kMaxLeaksConsidered); 461 Printf("\n"); 462 if (leaks_.size() == kMaxLeaksConsidered) 463 Printf("Too many leaks! Only the first %zu leaks encountered will be " 464 "reported.\n", 465 kMaxLeaksConsidered); 466 467 uptr unsuppressed_count = 0; 468 for (uptr i = 0; i < leaks_.size(); i++) 469 if (!leaks_[i].is_suppressed) unsuppressed_count++; 470 if (num_leaks_to_print > 0 && num_leaks_to_print < unsuppressed_count) 471 Printf("The %zu largest leak(s):\n", num_leaks_to_print); 472 InternalSort(&leaks_, leaks_.size(), LeakComparator); 473 uptr leaks_printed = 0; 474 Decorator d; 475 for (uptr i = 0; i < leaks_.size(); i++) { 476 if (leaks_[i].is_suppressed) continue; 477 Printf("%s", d.Leak()); 478 Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n", 479 leaks_[i].is_directly_leaked ? "Direct" : "Indirect", 480 leaks_[i].total_size, leaks_[i].hit_count); 481 Printf("%s", d.End()); 482 PrintStackTraceById(leaks_[i].stack_trace_id); 483 Printf("\n"); 484 leaks_printed++; 485 if (leaks_printed == num_leaks_to_print) break; 486 } 487 if (leaks_printed < unsuppressed_count) { 488 uptr remaining = unsuppressed_count - leaks_printed; 489 Printf("Omitting %zu more leak(s).\n", remaining); 490 } 491} 492 493void LeakReport::PrintSummary() { 494 CHECK(leaks_.size() <= kMaxLeaksConsidered); 495 uptr bytes = 0, allocations = 0; 496 for (uptr i = 0; i < leaks_.size(); i++) { 497 if (leaks_[i].is_suppressed) continue; 498 bytes += leaks_[i].total_size; 499 allocations += leaks_[i].hit_count; 500 } 501 const int kMaxSummaryLength = 128; 502 InternalScopedBuffer<char> summary(kMaxSummaryLength); 503 internal_snprintf(summary.data(), kMaxSummaryLength, 504 "LeakSanitizer: %zu byte(s) leaked in %zu allocation(s).", 505 bytes, allocations); 506 __sanitizer_report_error_summary(summary.data()); 507} 508 509uptr LeakReport::ApplySuppressions() { 510 uptr unsuppressed_count = 0; 511 for (uptr i = 0; i < leaks_.size(); i++) { 512 Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id); 513 if (s) { 514 s->weight += leaks_[i].total_size; 515 s->hit_count += leaks_[i].hit_count; 516 leaks_[i].is_suppressed = true; 517 } else { 518 unsuppressed_count++; 519 } 520 } 521 return unsuppressed_count; 522} 523} // namespace __lsan 524#endif // CAN_SANITIZE_LEAKS 525 526using namespace __lsan; // NOLINT 527 528extern "C" { 529SANITIZER_INTERFACE_ATTRIBUTE 530void __lsan_ignore_object(const void *p) { 531#if CAN_SANITIZE_LEAKS 532 // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not 533 // locked. 534 BlockingMutexLock l(&global_mutex); 535 IgnoreObjectResult res = IgnoreObjectLocked(p); 536 if (res == kIgnoreObjectInvalid && flags()->verbosity >= 2) 537 Report("__lsan_ignore_object(): no heap object found at %p", p); 538 if (res == kIgnoreObjectAlreadyIgnored && flags()->verbosity >= 2) 539 Report("__lsan_ignore_object(): " 540 "heap object at %p is already being ignored\n", p); 541 if (res == kIgnoreObjectSuccess && flags()->verbosity >= 3) 542 Report("__lsan_ignore_object(): ignoring heap object at %p\n", p); 543#endif // CAN_SANITIZE_LEAKS 544} 545 546SANITIZER_INTERFACE_ATTRIBUTE 547void __lsan_disable() { 548#if CAN_SANITIZE_LEAKS 549 __lsan::disable_counter++; 550#endif 551} 552 553SANITIZER_INTERFACE_ATTRIBUTE 554void __lsan_enable() { 555#if CAN_SANITIZE_LEAKS 556 if (!__lsan::disable_counter) { 557 Report("Unmatched call to __lsan_enable().\n"); 558 Die(); 559 } 560 __lsan::disable_counter--; 561#endif 562} 563 564SANITIZER_INTERFACE_ATTRIBUTE 565void __lsan_do_leak_check() { 566#if CAN_SANITIZE_LEAKS 567 if (common_flags()->detect_leaks) 568 __lsan::DoLeakCheck(); 569#endif // CAN_SANITIZE_LEAKS 570} 571 572#if !SANITIZER_SUPPORTS_WEAK_HOOKS 573SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 574int __lsan_is_turned_off() { 575 return 0; 576} 577#endif 578} // extern "C" 579