Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: third_party/tcmalloc/chromium/src/heap-checker.cc

Issue 9311003: Update the tcmalloc chromium branch to r144 (gperftools 2.0), and merge chromium-specific changes. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixed. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2005, Google Inc. 1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 #include <sys/mman.h> 45 #include <sys/mman.h>
46 #endif 46 #endif
47 #ifdef HAVE_PTHREAD 47 #ifdef HAVE_PTHREAD
48 #include <pthread.h> 48 #include <pthread.h>
49 #endif 49 #endif
50 #include <sys/stat.h> 50 #include <sys/stat.h>
51 #include <sys/types.h> 51 #include <sys/types.h>
52 #include <time.h> 52 #include <time.h>
53 #include <assert.h> 53 #include <assert.h>
54 54
55 #ifdef HAVE_LINUX_PTRACE_H 55 #if defined(HAVE_LINUX_PTRACE_H)
56 #include <linux/ptrace.h> 56 #include <linux/ptrace.h>
57 #endif 57 #endif
58 #ifdef HAVE_SYS_SYSCALL_H 58 #ifdef HAVE_SYS_SYSCALL_H
59 #include <sys/syscall.h> 59 #include <sys/syscall.h>
60 #endif 60 #endif
61 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(_ _MINGW32__) 61 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(_ _MINGW32__)
62 #include <wtypes.h> 62 #include <wtypes.h>
63 #include <winbase.h> 63 #include <winbase.h>
64 #undef ERROR // windows defines these as macros, which can cause trouble 64 #undef ERROR // windows defines these as macros, which can cause trouble
65 #undef max 65 #undef max
66 #undef min 66 #undef min
67 #endif 67 #endif
68 68
69 #include <string> 69 #include <string>
70 #include <vector> 70 #include <vector>
71 #include <map> 71 #include <map>
72 #include <set> 72 #include <set>
73 #include <algorithm> 73 #include <algorithm>
74 #include <functional> 74 #include <functional>
75 75
76 #include <google/heap-checker.h> 76 #include <gperftools/heap-checker.h>
77 77
78 #include "base/basictypes.h" 78 #include "base/basictypes.h"
79 #include "base/googleinit.h" 79 #include "base/googleinit.h"
80 #include "base/logging.h" 80 #include "base/logging.h"
81 #include <google/stacktrace.h> 81 #include <gperftools/stacktrace.h>
82 #include "base/commandlineflags.h" 82 #include "base/commandlineflags.h"
83 #include "base/elfcore.h" // for i386_regs 83 #include "base/elfcore.h" // for i386_regs
84 #include "base/thread_lister.h" 84 #include "base/thread_lister.h"
85 #include "heap-profile-table.h" 85 #include "heap-profile-table.h"
86 #include "base/low_level_alloc.h" 86 #include "base/low_level_alloc.h"
87 #include "malloc_hook-inl.h" 87 #include "malloc_hook-inl.h"
88 #include <google/malloc_hook.h> 88 #include <gperftools/malloc_hook.h>
89 #include <google/malloc_extension.h> 89 #include <gperftools/malloc_extension.h>
90 #include "maybe_threads.h" 90 #include "maybe_threads.h"
91 #include "memory_region_map.h" 91 #include "memory_region_map.h"
92 #include "base/spinlock.h" 92 #include "base/spinlock.h"
93 #include "base/sysinfo.h" 93 #include "base/sysinfo.h"
94 #include "base/stl_allocator.h" 94 #include "base/stl_allocator.h"
95 95
96 using std::string; 96 using std::string;
97 using std::basic_string; 97 using std::basic_string;
98 using std::pair; 98 using std::pair;
99 using std::map; 99 using std::map;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 //---------------------------------------------------------------------- 137 //----------------------------------------------------------------------
138 // Flags that control heap-checking 138 // Flags that control heap-checking
139 //---------------------------------------------------------------------- 139 //----------------------------------------------------------------------
140 140
141 DEFINE_string(heap_check, 141 DEFINE_string(heap_check,
142 EnvToString("HEAPCHECK", ""), 142 EnvToString("HEAPCHECK", ""),
143 "The heap leak checking to be done over the whole executable: " 143 "The heap leak checking to be done over the whole executable: "
144 "\"minimal\", \"normal\", \"strict\", " 144 "\"minimal\", \"normal\", \"strict\", "
145 "\"draconian\", \"as-is\", and \"local\" " 145 "\"draconian\", \"as-is\", and \"local\" "
146 " or the empty string are the supported choices. " 146 " or the empty string are the supported choices. "
147 "(See HeapLeakChecker::InternalInitStart for details.)"); 147 "(See HeapLeakChecker_InternalInitStart for details.)");
148 148
149 DEFINE_bool(heap_check_report, true, "Obsolete"); 149 DEFINE_bool(heap_check_report, true, "Obsolete");
150 150
151 DEFINE_bool(heap_check_before_constructors, 151 DEFINE_bool(heap_check_before_constructors,
152 true, 152 true,
153 "deprecated; pretty much always true now"); 153 "deprecated; pretty much always true now");
154 154
155 DEFINE_bool(heap_check_after_destructors, 155 DEFINE_bool(heap_check_after_destructors,
156 EnvToBool("HEAP_CHECK_AFTER_DESTRUCTORS", false), 156 EnvToBool("HEAP_CHECK_AFTER_DESTRUCTORS", false),
157 "If overall heap check is to end after global destructors " 157 "If overall heap check is to end after global destructors "
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 static pid_t heap_checker_pid = 0; 271 static pid_t heap_checker_pid = 0;
272 272
273 // If we did heap profiling during global constructors execution 273 // If we did heap profiling during global constructors execution
274 static bool constructor_heap_profiling = false; 274 static bool constructor_heap_profiling = false;
275 275
276 // RAW_VLOG level we dump key INFO messages at. If you want to turn 276 // RAW_VLOG level we dump key INFO messages at. If you want to turn
277 // off these messages, set the environment variable PERFTOOLS_VERBOSE=-1. 277 // off these messages, set the environment variable PERFTOOLS_VERBOSE=-1.
278 static const int heap_checker_info_level = 0; 278 static const int heap_checker_info_level = 0;
279 279
280 //---------------------------------------------------------------------- 280 //----------------------------------------------------------------------
281 // Cancel our InitialMallocHook_* if present.
282 static void CancelInitialMallocHooks(); // defined below
283
284 //----------------------------------------------------------------------
285 // HeapLeakChecker's own memory allocator that is 281 // HeapLeakChecker's own memory allocator that is
286 // independent of the normal program allocator. 282 // independent of the normal program allocator.
287 //---------------------------------------------------------------------- 283 //----------------------------------------------------------------------
288 284
289 // Wrapper of LowLevelAlloc for STL_Allocator and direct use. 285 // Wrapper of LowLevelAlloc for STL_Allocator and direct use.
290 // We always access this class under held heap_checker_lock, 286 // We always access this class under held heap_checker_lock,
291 // this allows us to in particular protect the period when threads are stopped 287 // this allows us to in particular protect the period when threads are stopped
292 // at random spots with ListAllProcessThreads by heap_checker_lock, 288 // at random spots with ListAllProcessThreads by heap_checker_lock,
293 // w/o worrying about the lock in LowLevelAlloc::Arena. 289 // w/o worrying about the lock in LowLevelAlloc::Arena.
294 // We rely on the fact that we use an own arena with an own lock here. 290 // We rely on the fact that we use an own arena with an own lock here.
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 template<typename T> 538 template<typename T>
543 inline static const void* AsPtr(T addr) { 539 inline static const void* AsPtr(T addr) {
544 return reinterpret_cast<void*>(addr); 540 return reinterpret_cast<void*>(addr);
545 } 541 }
546 inline static uintptr_t AsInt(const void* ptr) { 542 inline static uintptr_t AsInt(const void* ptr) {
547 return reinterpret_cast<uintptr_t>(ptr); 543 return reinterpret_cast<uintptr_t>(ptr);
548 } 544 }
549 545
550 //---------------------------------------------------------------------- 546 //----------------------------------------------------------------------
551 547
548 // We've seen reports that strstr causes heap-checker crashes in some
549 // libc's (?):
550 // http://code.google.com/p/gperftools/issues/detail?id=263
551 // It's simple enough to use our own. This is not in time-critical code.
552 static const char* hc_strstr(const char* s1, const char* s2) {
553 const size_t len = strlen(s2);
554 RAW_CHECK(len > 0, "Unexpected empty string passed to strstr()");
555 for (const char* p = strchr(s1, *s2); p != NULL; p = strchr(p+1, *s2)) {
556 if (strncmp(p, s2, len) == 0) {
557 return p;
558 }
559 }
560 return NULL;
561 }
562
563 //----------------------------------------------------------------------
564
552 // Our hooks for MallocHook 565 // Our hooks for MallocHook
553 static void NewHook(const void* ptr, size_t size) { 566 static void NewHook(const void* ptr, size_t size) {
554 if (ptr != NULL) { 567 if (ptr != NULL) {
555 const int counter = get_thread_disable_counter(); 568 const int counter = get_thread_disable_counter();
556 const bool ignore = (counter > 0); 569 const bool ignore = (counter > 0);
557 RAW_VLOG(16, "Recording Alloc: %p of %"PRIuS "; %d", ptr, size, 570 RAW_VLOG(16, "Recording Alloc: %p of %"PRIuS "; %d", ptr, size,
558 int(counter)); 571 int(counter));
572
573 // Fetch the caller's stack trace before acquiring heap_checker_lock.
574 void* stack[HeapProfileTable::kMaxStackDepth];
575 int depth = HeapProfileTable::GetCallerStackTrace(0, stack);
576
559 { SpinLockHolder l(&heap_checker_lock); 577 { SpinLockHolder l(&heap_checker_lock);
560 if (size > max_heap_object_size) max_heap_object_size = size; 578 if (size > max_heap_object_size) max_heap_object_size = size;
561 uintptr_t addr = AsInt(ptr); 579 uintptr_t addr = AsInt(ptr);
562 if (addr < min_heap_address) min_heap_address = addr; 580 if (addr < min_heap_address) min_heap_address = addr;
563 addr += size; 581 addr += size;
564 if (addr > max_heap_address) max_heap_address = addr; 582 if (addr > max_heap_address) max_heap_address = addr;
565 if (heap_checker_on) { 583 if (heap_checker_on) {
566 heap_profile->RecordAlloc(ptr, size, 0); 584 heap_profile->RecordAlloc(ptr, size, depth, stack);
567 if (ignore) { 585 if (ignore) {
568 heap_profile->MarkAsIgnored(ptr); 586 heap_profile->MarkAsIgnored(ptr);
569 } 587 }
570 } 588 }
571 } 589 }
572 RAW_VLOG(17, "Alloc Recorded: %p of %"PRIuS"", ptr, size); 590 RAW_VLOG(17, "Alloc Recorded: %p of %"PRIuS"", ptr, size);
573 } 591 }
574 } 592 }
575 593
576 static void DeleteHook(const void* ptr) { 594 static void DeleteHook(const void* ptr) {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 return; 777 return;
760 } 778 }
761 } 779 }
762 RAW_VLOG(11, "%s-disabling %"PRIuS" bytes at %p", 780 RAW_VLOG(11, "%s-disabling %"PRIuS" bytes at %p",
763 (stack_disable ? "Stack" : "Range"), info.object_size, ptr); 781 (stack_disable ? "Stack" : "Range"), info.object_size, ptr);
764 live_objects->push_back(AllocObject(ptr, info.object_size, 782 live_objects->push_back(AllocObject(ptr, info.object_size,
765 MUST_BE_ON_HEAP)); 783 MUST_BE_ON_HEAP));
766 } 784 }
767 } 785 }
768 786
787 static const char kUnnamedProcSelfMapEntry[] = "UNNAMED";
788
769 // This function takes some fields from a /proc/self/maps line: 789 // This function takes some fields from a /proc/self/maps line:
770 // 790 //
771 // start_address start address of a memory region. 791 // start_address start address of a memory region.
772 // end_address end address of a memory region 792 // end_address end address of a memory region
773 // permissions rwx + private/shared bit 793 // permissions rwx + private/shared bit
774 // filename filename of the mapped file 794 // filename filename of the mapped file
775 // 795 //
776 // If the region is not writeable, then it cannot have any heap 796 // If the region is not writeable, then it cannot have any heap
777 // pointers in it, otherwise we record it as a candidate live region 797 // pointers in it, otherwise we record it as a candidate live region
778 // to get filtered later. 798 // to get filtered later.
779 static void RecordGlobalDataLocked(uintptr_t start_address, 799 static void RecordGlobalDataLocked(uintptr_t start_address,
780 uintptr_t end_address, 800 uintptr_t end_address,
781 const char* permissions, 801 const char* permissions,
782 const char* filename) { 802 const char* filename) {
783 RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 803 RAW_DCHECK(heap_checker_lock.IsHeld(), "");
784 // Ignore non-writeable regions. 804 // Ignore non-writeable regions.
785 if (strchr(permissions, 'w') == NULL) return; 805 if (strchr(permissions, 'w') == NULL) return;
786 if (filename == NULL || *filename == '\0') filename = "UNNAMED"; 806 if (filename == NULL || *filename == '\0') {
807 filename = kUnnamedProcSelfMapEntry;
808 }
787 RAW_VLOG(11, "Looking into %s: 0x%" PRIxPTR "..0x%" PRIxPTR, 809 RAW_VLOG(11, "Looking into %s: 0x%" PRIxPTR "..0x%" PRIxPTR,
788 filename, start_address, end_address); 810 filename, start_address, end_address);
789 (*library_live_objects)[filename]. 811 (*library_live_objects)[filename].
790 push_back(AllocObject(AsPtr(start_address), 812 push_back(AllocObject(AsPtr(start_address),
791 end_address - start_address, 813 end_address - start_address,
792 MAYBE_LIVE)); 814 MAYBE_LIVE));
793 } 815 }
794 816
795 // See if 'library' from /proc/self/maps has base name 'library_base' 817 // See if 'library' from /proc/self/maps has base name 'library_base'
796 // i.e. contains it and has '.' or '-' after it. 818 // i.e. contains it and has '.' or '-' after it.
797 static bool IsLibraryNamed(const char* library, const char* library_base) { 819 static bool IsLibraryNamed(const char* library, const char* library_base) {
798 const char* p = strstr(library, library_base); 820 const char* p = hc_strstr(library, library_base);
799 size_t sz = strlen(library_base); 821 size_t sz = strlen(library_base);
800 return p != NULL && (p[sz] == '.' || p[sz] == '-'); 822 return p != NULL && (p[sz] == '.' || p[sz] == '-');
801 } 823 }
802 824
803 // static 825 // static
804 void HeapLeakChecker::DisableLibraryAllocsLocked(const char* library, 826 void HeapLeakChecker::DisableLibraryAllocsLocked(const char* library,
805 uintptr_t start_address, 827 uintptr_t start_address,
806 uintptr_t end_address) { 828 uintptr_t end_address) {
807 RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 829 RAW_DCHECK(heap_checker_lock.IsHeld(), "");
808 int depth = 0; 830 int depth = 0;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 continue; 922 continue;
901 } 923 }
902 // Determine if any shared libraries are present (this is the same 924 // Determine if any shared libraries are present (this is the same
903 // list of extensions as is found in pprof). We want to ignore 925 // list of extensions as is found in pprof). We want to ignore
904 // 'fake' libraries with inode 0 when determining. However, some 926 // 'fake' libraries with inode 0 when determining. However, some
905 // systems don't share inodes via /proc, so we turn off this check 927 // systems don't share inodes via /proc, so we turn off this check
906 // if we don't see any evidence that we're getting inode info. 928 // if we don't see any evidence that we're getting inode info.
907 if (inode != 0) { 929 if (inode != 0) {
908 saw_nonzero_inode = true; 930 saw_nonzero_inode = true;
909 } 931 }
910 if ((strstr(filename, "lib") && strstr(filename, ".so")) || 932 if ((hc_strstr(filename, "lib") && hc_strstr(filename, ".so")) ||
911 strstr(filename, ".dll") || 933 hc_strstr(filename, ".dll") ||
912 // not all .dylib filenames start with lib. .dylib is big enough 934 // not all .dylib filenames start with lib. .dylib is big enough
913 // that we are unlikely to get false matches just checking that. 935 // that we are unlikely to get false matches just checking that.
914 strstr(filename, ".dylib") || strstr(filename, ".bundle")) { 936 hc_strstr(filename, ".dylib") || hc_strstr(filename, ".bundle")) {
915 saw_shared_lib = true; 937 saw_shared_lib = true;
916 if (inode != 0) { 938 if (inode != 0) {
917 saw_shared_lib_with_nonzero_inode = true; 939 saw_shared_lib_with_nonzero_inode = true;
918 } 940 }
919 } 941 }
920 942
921 switch (proc_maps_task) { 943 switch (proc_maps_task) {
922 case DISABLE_LIBRARY_ALLOCS: 944 case DISABLE_LIBRARY_ALLOCS:
923 // All lines starting like 945 // All lines starting like
924 // "401dc000-4030f000 r??p 00132000 03:01 13991972 lib/bin" 946 // "401dc000-4030f000 r??p 00132000 03:01 13991972 lib/bin"
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 const size_t remainder = AsInt(object) % pointer_source_alignment; 1402 const size_t remainder = AsInt(object) % pointer_source_alignment;
1381 if (remainder) { 1403 if (remainder) {
1382 object += pointer_source_alignment - remainder; 1404 object += pointer_source_alignment - remainder;
1383 if (size >= pointer_source_alignment - remainder) { 1405 if (size >= pointer_source_alignment - remainder) {
1384 size -= pointer_source_alignment - remainder; 1406 size -= pointer_source_alignment - remainder;
1385 } else { 1407 } else {
1386 size = 0; 1408 size = 0;
1387 } 1409 }
1388 } 1410 }
1389 if (size < sizeof(void*)) continue; 1411 if (size < sizeof(void*)) continue;
1412
1413 #ifdef NO_FRAME_POINTER
1414 // Frame pointer omission requires us to use libunwind, which uses direct
1415 // mmap and munmap system calls, and that needs special handling.
1416 if (name2 == kUnnamedProcSelfMapEntry) {
1417 static const uintptr_t page_mask = ~(getpagesize() - 1);
1418 const uintptr_t addr = reinterpret_cast<uintptr_t>(object);
1419 if ((addr & page_mask) == 0 && (size & page_mask) == 0) {
1420 // This is an object we slurped from /proc/self/maps.
1421 // It may or may not be readable at this point.
1422 //
1423 // In case all the above conditions made a mistake, and the object is
1424 // not related to libunwind, we also verify that it's not readable
1425 // before ignoring it.
1426 if (msync(const_cast<char*>(object), size, MS_ASYNC) != 0) {
1427 // Skip unreadable object, so we don't crash trying to sweep it.
1428 RAW_VLOG(0, "Ignoring inaccessible object [%p, %p) "
1429 "(msync error %d (%s))",
1430 object, object + size, errno, strerror(errno));
1431 continue;
1432 }
1433 }
1434 }
1435 #endif
1436
1390 const char* const max_object = object + size - sizeof(void*); 1437 const char* const max_object = object + size - sizeof(void*);
1391 while (object <= max_object) { 1438 while (object <= max_object) {
1392 // potentially unaligned load: 1439 // potentially unaligned load:
1393 const uintptr_t addr = *reinterpret_cast<const uintptr_t*>(object); 1440 const uintptr_t addr = *reinterpret_cast<const uintptr_t*>(object);
1394 // Do fast check before the more expensive HaveOnHeapLocked lookup: 1441 // Do fast check before the more expensive HaveOnHeapLocked lookup:
1395 // this code runs for all memory words that are potentially pointers: 1442 // this code runs for all memory words that are potentially pointers:
1396 const bool can_be_on_heap = 1443 const bool can_be_on_heap =
1397 // Order tests by the likelyhood of the test failing in 64/32 bit modes. 1444 // Order tests by the likelyhood of the test failing in 64/32 bit modes.
1398 // Yes, this matters: we either lose 5..6% speed in 32 bit mode 1445 // Yes, this matters: we either lose 5..6% speed in 32 bit mode
1399 // (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode. 1446 // (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 //---------------------------------------------------------------------- 1499 //----------------------------------------------------------------------
1453 // HeapLeakChecker leak check disabling components 1500 // HeapLeakChecker leak check disabling components
1454 //---------------------------------------------------------------------- 1501 //----------------------------------------------------------------------
1455 1502
1456 // static 1503 // static
1457 void HeapLeakChecker::DisableChecksIn(const char* pattern) { 1504 void HeapLeakChecker::DisableChecksIn(const char* pattern) {
1458 RAW_LOG(WARNING, "DisableChecksIn(%s) is ignored", pattern); 1505 RAW_LOG(WARNING, "DisableChecksIn(%s) is ignored", pattern);
1459 } 1506 }
1460 1507
1461 // static 1508 // static
1462 void HeapLeakChecker::IgnoreObject(const void* ptr) { 1509 void HeapLeakChecker::DoIgnoreObject(const void* ptr) {
1463 SpinLockHolder l(&heap_checker_lock); 1510 SpinLockHolder l(&heap_checker_lock);
1464 if (!heap_checker_on) return; 1511 if (!heap_checker_on) return;
1465 size_t object_size; 1512 size_t object_size;
1466 if (!HaveOnHeapLocked(&ptr, &object_size)) { 1513 if (!HaveOnHeapLocked(&ptr, &object_size)) {
1467 RAW_LOG(ERROR, "No live heap object at %p to ignore", ptr); 1514 RAW_LOG(ERROR, "No live heap object at %p to ignore", ptr);
1468 } else { 1515 } else {
1469 RAW_VLOG(10, "Going to ignore live object at %p of %"PRIuS" bytes", 1516 RAW_VLOG(10, "Going to ignore live object at %p of %"PRIuS" bytes",
1470 ptr, object_size); 1517 ptr, object_size);
1471 if (ignored_objects == NULL) { 1518 if (ignored_objects == NULL) {
1472 ignored_objects = new(Allocator::Allocate(sizeof(IgnoredObjectsMap))) 1519 ignored_objects = new(Allocator::Allocate(sizeof(IgnoredObjectsMap)))
1473 IgnoredObjectsMap; 1520 IgnoredObjectsMap;
1474 } 1521 }
1475 if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) { 1522 if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) {
1476 RAW_LOG(FATAL, "Object at %p is already being ignored", ptr); 1523 RAW_LOG(WARNING, "Object at %p is already being ignored", ptr);
1477 } 1524 }
1478 } 1525 }
1479 } 1526 }
1480 1527
1481 // static 1528 // static
1482 void HeapLeakChecker::UnIgnoreObject(const void* ptr) { 1529 void HeapLeakChecker::UnIgnoreObject(const void* ptr) {
1483 SpinLockHolder l(&heap_checker_lock); 1530 SpinLockHolder l(&heap_checker_lock);
1484 if (!heap_checker_on) return; 1531 if (!heap_checker_on) return;
1485 size_t object_size; 1532 size_t object_size;
1486 if (!HaveOnHeapLocked(&ptr, &object_size)) { 1533 if (!HaveOnHeapLocked(&ptr, &object_size)) {
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1856 if (!heap_cleanups_) 1903 if (!heap_cleanups_)
1857 return; 1904 return;
1858 for (int i = 0; i < heap_cleanups_->size(); i++) { 1905 for (int i = 0; i < heap_cleanups_->size(); i++) {
1859 void (*f)(void) = (*heap_cleanups_)[i]; 1906 void (*f)(void) = (*heap_cleanups_)[i];
1860 f(); 1907 f();
1861 } 1908 }
1862 delete heap_cleanups_; 1909 delete heap_cleanups_;
1863 heap_cleanups_ = NULL; 1910 heap_cleanups_ = NULL;
1864 } 1911 }
1865 1912
1866 // Program exit heap cleanup registered with atexit(). 1913 // Program exit heap cleanup registered as a module object destructor.
1867 // Will not get executed when we crash on a signal. 1914 // Will not get executed when we crash on a signal.
1868 // 1915 //
1869 /*static*/ void HeapLeakChecker::RunHeapCleanups() { 1916 void HeapLeakChecker_RunHeapCleanups() {
1917 if (FLAGS_heap_check == "local") // don't check heap in this mode
1918 return;
1870 { SpinLockHolder l(&heap_checker_lock); 1919 { SpinLockHolder l(&heap_checker_lock);
1871 // can get here (via forks?) with other pids 1920 // can get here (via forks?) with other pids
1872 if (heap_checker_pid != getpid()) return; 1921 if (heap_checker_pid != getpid()) return;
1873 } 1922 }
1874 HeapCleaner::RunHeapCleanups(); 1923 HeapCleaner::RunHeapCleanups();
1875 if (!FLAGS_heap_check_after_destructors) DoMainHeapCheck(); 1924 if (!FLAGS_heap_check_after_destructors) HeapLeakChecker::DoMainHeapCheck();
1876 } 1925 }
1877 1926
1878 static bool internal_init_start_has_run = false; 1927 static bool internal_init_start_has_run = false;
1879 1928
1880 // Called exactly once, before main() (but hopefully just before). 1929 // Called exactly once, before main() (but hopefully just before).
1881 // This picks a good unique name for the dumped leak checking heap profiles. 1930 // This picks a good unique name for the dumped leak checking heap profiles.
1882 // 1931 //
1883 // Because we crash when InternalInitStart is called more than once, 1932 // Because we crash when InternalInitStart is called more than once,
1884 // it's fine that we hold heap_checker_lock only around pieces of 1933 // it's fine that we hold heap_checker_lock only around pieces of
1885 // this function: this is still enough for thread-safety w.r.t. other functions 1934 // this function: this is still enough for thread-safety w.r.t. other functions
1886 // of this module. 1935 // of this module.
1887 // We can't hold heap_checker_lock throughout because it would deadlock 1936 // We can't hold heap_checker_lock throughout because it would deadlock
1888 // on a memory allocation since our new/delete hooks can be on. 1937 // on a memory allocation since our new/delete hooks can be on.
1889 // 1938 //
1890 /*static*/ void HeapLeakChecker::InternalInitStart() { 1939 void HeapLeakChecker_InternalInitStart() {
1891 { SpinLockHolder l(&heap_checker_lock); 1940 { SpinLockHolder l(&heap_checker_lock);
1892 RAW_CHECK(!internal_init_start_has_run, 1941 RAW_CHECK(!internal_init_start_has_run,
1893 "Heap-check constructor called twice. Perhaps you both linked" 1942 "Heap-check constructor called twice. Perhaps you both linked"
1894 " in the heap checker, and also used LD_PRELOAD to load it?"); 1943 " in the heap checker, and also used LD_PRELOAD to load it?");
1895 internal_init_start_has_run = true; 1944 internal_init_start_has_run = true;
1896 1945
1946 #ifdef ADDRESS_SANITIZER
1947 // AddressSanitizer's custom malloc conflicts with HeapChecker.
1948 FLAGS_heap_check = "";
1949 #endif
1950
1897 if (FLAGS_heap_check.empty()) { 1951 if (FLAGS_heap_check.empty()) {
1898 // turns out we do not need checking in the end; can stop profiling 1952 // turns out we do not need checking in the end; can stop profiling
1899 TurnItselfOffLocked(); 1953 HeapLeakChecker::TurnItselfOffLocked();
1900 return; 1954 return;
1901 } else if (RunningOnValgrind()) { 1955 } else if (RunningOnValgrind()) {
1902 // There is no point in trying -- we'll just fail. 1956 // There is no point in trying -- we'll just fail.
1903 RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off"); 1957 RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off");
1904 TurnItselfOffLocked(); 1958 HeapLeakChecker::TurnItselfOffLocked();
1905 return; 1959 return;
1906 } 1960 }
1907 } 1961 }
1908 1962
1909 // Changing this to false can be useful when debugging heap-checker itself: 1963 // Changing this to false can be useful when debugging heap-checker itself:
1910 if (!FLAGS_heap_check_run_under_gdb && IsDebuggerAttached()) { 1964 if (!FLAGS_heap_check_run_under_gdb && IsDebuggerAttached()) {
1911 RAW_LOG(WARNING, "Someone is ptrace()ing us; will turn itself off"); 1965 RAW_LOG(WARNING, "Someone is ptrace()ing us; will turn itself off");
1912 SpinLockHolder l(&heap_checker_lock); 1966 SpinLockHolder l(&heap_checker_lock);
1913 TurnItselfOffLocked(); 1967 HeapLeakChecker::TurnItselfOffLocked();
1914 return; 1968 return;
1915 } 1969 }
1916 1970
1917 { SpinLockHolder l(&heap_checker_lock); 1971 { SpinLockHolder l(&heap_checker_lock);
1918 if (!constructor_heap_profiling) { 1972 if (!constructor_heap_profiling) {
1919 RAW_LOG(FATAL, "Can not start so late. You have to enable heap checking " 1973 RAW_LOG(FATAL, "Can not start so late. You have to enable heap checking "
1920 "with HEAPCHECK=<mode>."); 1974 "with HEAPCHECK=<mode>.");
1921 } 1975 }
1922 } 1976 }
1923 1977
(...skipping 30 matching lines...) Expand all
1954 FLAGS_heap_check_ignore_thread_live = false; // no live flood (stricter) 2008 FLAGS_heap_check_ignore_thread_live = false; // no live flood (stricter)
1955 FLAGS_heap_check_ignore_global_live = false; // no live flood (stricter) 2009 FLAGS_heap_check_ignore_global_live = false; // no live flood (stricter)
1956 } else if (FLAGS_heap_check == "as-is") { 2010 } else if (FLAGS_heap_check == "as-is") {
1957 // do nothing: use other flags as is 2011 // do nothing: use other flags as is
1958 } else if (FLAGS_heap_check == "local") { 2012 } else if (FLAGS_heap_check == "local") {
1959 // do nothing 2013 // do nothing
1960 } else { 2014 } else {
1961 RAW_LOG(FATAL, "Unsupported heap_check flag: %s", 2015 RAW_LOG(FATAL, "Unsupported heap_check flag: %s",
1962 FLAGS_heap_check.c_str()); 2016 FLAGS_heap_check.c_str());
1963 } 2017 }
2018 // FreeBSD doesn't seem to honor atexit execution order:
2019 // http://code.google.com/p/gperftools/issues/detail?id=375
2020 // Since heap-checking before destructors depends on atexit running
2021 // at the right time, on FreeBSD we always check after, even in the
2022 // less strict modes. This just means FreeBSD is always a bit
2023 // stricter in its checking than other OSes.
2024 #ifdef __FreeBSD__
2025 FLAGS_heap_check_after_destructors = true;
2026 #endif
2027
1964 { SpinLockHolder l(&heap_checker_lock); 2028 { SpinLockHolder l(&heap_checker_lock);
1965 RAW_DCHECK(heap_checker_pid == getpid(), ""); 2029 RAW_DCHECK(heap_checker_pid == getpid(), "");
1966 heap_checker_on = true; 2030 heap_checker_on = true;
1967 RAW_DCHECK(heap_profile, ""); 2031 RAW_DCHECK(heap_profile, "");
1968 ProcMapsResult pm_result = UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS); 2032 HeapLeakChecker::ProcMapsResult pm_result = HeapLeakChecker::UseProcMapsLock ed(HeapLeakChecker::DISABLE_LIBRARY_ALLOCS);
1969 // might neeed to do this more than once 2033 // might neeed to do this more than once
1970 // if one later dynamically loads libraries that we want disabled 2034 // if one later dynamically loads libraries that we want disabled
1971 if (pm_result != PROC_MAPS_USED) { // can't function 2035 if (pm_result != HeapLeakChecker::PROC_MAPS_USED) { // can't function
1972 TurnItselfOffLocked(); 2036 HeapLeakChecker::TurnItselfOffLocked();
1973 return; 2037 return;
1974 } 2038 }
1975 } 2039 }
1976 2040
1977 // make a good place and name for heap profile leak dumps 2041 // make a good place and name for heap profile leak dumps
1978 string* profile_prefix = 2042 string* profile_prefix =
1979 new string(FLAGS_heap_check_dump_directory + "/" + invocation_name()); 2043 new string(FLAGS_heap_check_dump_directory + "/" + invocation_name());
1980 2044
1981 // Finalize prefix for dumping leak checking profiles. 2045 // Finalize prefix for dumping leak checking profiles.
1982 const int32 our_pid = getpid(); // safest to call getpid() outside lock 2046 const int32 our_pid = getpid(); // safest to call getpid() outside lock
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2016 // "nm <this_binary> | grep new" will show that tcmalloc's new/delete 2080 // "nm <this_binary> | grep new" will show that tcmalloc's new/delete
2017 // implementation did not get linked-in into this binary 2081 // implementation did not get linked-in into this binary
2018 // (i.e. nm will list __builtin_new and __builtin_vec_new as undefined). 2082 // (i.e. nm will list __builtin_new and __builtin_vec_new as undefined).
2019 // If this happens, it is a BUILD bug to be fixed. 2083 // If this happens, it is a BUILD bug to be fixed.
2020 2084
2021 RAW_VLOG(heap_checker_info_level, 2085 RAW_VLOG(heap_checker_info_level,
2022 "WARNING: Perftools heap leak checker is active " 2086 "WARNING: Perftools heap leak checker is active "
2023 "-- Performance may suffer"); 2087 "-- Performance may suffer");
2024 2088
2025 if (FLAGS_heap_check != "local") { 2089 if (FLAGS_heap_check != "local") {
2026 // Schedule registered heap cleanup
2027 atexit(RunHeapCleanups);
2028 HeapLeakChecker* main_hc = new HeapLeakChecker(); 2090 HeapLeakChecker* main_hc = new HeapLeakChecker();
2029 SpinLockHolder l(&heap_checker_lock); 2091 SpinLockHolder l(&heap_checker_lock);
2030 RAW_DCHECK(main_heap_checker == NULL, 2092 RAW_DCHECK(main_heap_checker == NULL,
2031 "Repeated creation of main_heap_checker"); 2093 "Repeated creation of main_heap_checker");
2032 main_heap_checker = main_hc; 2094 main_heap_checker = main_hc;
2033 do_main_heap_check = true; 2095 do_main_heap_check = true;
2034 } 2096 }
2035 2097
2036 { SpinLockHolder l(&heap_checker_lock); 2098 { SpinLockHolder l(&heap_checker_lock);
2037 RAW_CHECK(heap_checker_on && constructor_heap_profiling, 2099 RAW_CHECK(heap_checker_on && constructor_heap_profiling,
(...skipping 12 matching lines...) Expand all
2050 // TODO(csilvers): support this in some manner. 2112 // TODO(csilvers): support this in some manner.
2051 #if 0 2113 #if 0
2052 SetCommandLineOptionWithMode("max_free_queue_size", "104857600", // 100M 2114 SetCommandLineOptionWithMode("max_free_queue_size", "104857600", // 100M
2053 SET_FLAG_IF_DEFAULT); 2115 SET_FLAG_IF_DEFAULT);
2054 #endif 2116 #endif
2055 } 2117 }
2056 2118
2057 // We want this to run early as well, but not so early as 2119 // We want this to run early as well, but not so early as
2058 // ::BeforeConstructors (we want flag assignments to have already 2120 // ::BeforeConstructors (we want flag assignments to have already
2059 // happened, for instance). Initializer-registration does the trick. 2121 // happened, for instance). Initializer-registration does the trick.
2060 REGISTER_MODULE_INITIALIZER(init_start, HeapLeakChecker::InternalInitStart()); 2122 REGISTER_MODULE_INITIALIZER(init_start, HeapLeakChecker_InternalInitStart());
2123 REGISTER_MODULE_DESTRUCTOR(init_start, HeapLeakChecker_RunHeapCleanups());
2124
2125 // static
2126 bool HeapLeakChecker::NoGlobalLeaksMaybeSymbolize(
2127 ShouldSymbolize should_symbolize) {
2128 // we never delete or change main_heap_checker once it's set:
2129 HeapLeakChecker* main_hc = GlobalChecker();
2130 if (main_hc) {
2131 RAW_VLOG(10, "Checking for whole-program memory leaks");
2132 return main_hc->DoNoLeaks(should_symbolize);
2133 }
2134 return true;
2135 }
2061 2136
2062 // static 2137 // static
2063 bool HeapLeakChecker::DoMainHeapCheck() { 2138 bool HeapLeakChecker::DoMainHeapCheck() {
2064 if (FLAGS_heap_check_delay_seconds > 0) { 2139 if (FLAGS_heap_check_delay_seconds > 0) {
2065 sleep(FLAGS_heap_check_delay_seconds); 2140 sleep(FLAGS_heap_check_delay_seconds);
2066 } 2141 }
2067 { SpinLockHolder l(&heap_checker_lock); 2142 { SpinLockHolder l(&heap_checker_lock);
2068 if (!do_main_heap_check) return false; 2143 if (!do_main_heap_check) return false;
2069 RAW_DCHECK(heap_checker_pid == getpid(), ""); 2144 RAW_DCHECK(heap_checker_pid == getpid(), "");
2070 do_main_heap_check = false; // will do it now; no need to do it more 2145 do_main_heap_check = false; // will do it now; no need to do it more
2071 } 2146 }
2072 2147
2073 if (!NoGlobalLeaks()) { 2148 // The program is over, so it's safe to symbolize addresses (which
2149 // requires a fork) because no serious work is expected to be done
2150 // after this. Symbolizing is really useful -- knowing what
2151 // function has a leak is better than knowing just an address --
2152 // and while we can only safely symbolize once in a program run,
2153 // now is the time (after all, there's no "later" that would be better).
2154 if (!NoGlobalLeaksMaybeSymbolize(SYMBOLIZE)) {
2074 if (FLAGS_heap_check_identify_leaks) { 2155 if (FLAGS_heap_check_identify_leaks) {
2075 RAW_LOG(FATAL, "Whole-program memory leaks found."); 2156 RAW_LOG(FATAL, "Whole-program memory leaks found.");
2076 } 2157 }
2077 RAW_LOG(ERROR, "Exiting with error code (instead of crashing) " 2158 RAW_LOG(ERROR, "Exiting with error code (instead of crashing) "
2078 "because of whole-program memory leaks"); 2159 "because of whole-program memory leaks");
2079 _exit(1); // we don't want to call atexit() routines! 2160 _exit(1); // we don't want to call atexit() routines!
2080 } 2161 }
2081 return true; 2162 return true;
2082 } 2163 }
2083 2164
2084 // static 2165 // static
2085 HeapLeakChecker* HeapLeakChecker::GlobalChecker() { 2166 HeapLeakChecker* HeapLeakChecker::GlobalChecker() {
2086 SpinLockHolder l(&heap_checker_lock); 2167 SpinLockHolder l(&heap_checker_lock);
2087 return main_heap_checker; 2168 return main_heap_checker;
2088 } 2169 }
2089 2170
2090 // static 2171 // static
2091 bool HeapLeakChecker::NoGlobalLeaks() { 2172 bool HeapLeakChecker::NoGlobalLeaks() {
2092 // we never delete or change main_heap_checker once it's set: 2173 // symbolizing requires a fork, which isn't safe to do in general.
2093 HeapLeakChecker* main_hc = GlobalChecker(); 2174 return NoGlobalLeaksMaybeSymbolize(DO_NOT_SYMBOLIZE);
2094 if (main_hc) {
2095 RAW_VLOG(10, "Checking for whole-program memory leaks");
2096 // The program is over, so it's safe to symbolize addresses (which
2097 // requires a fork) because no serious work is expected to be done
2098 // after this. Symbolizing is really useful -- knowing what
2099 // function has a leak is better than knowing just an address --
2100 // and while we can only safely symbolize once in a program run,
2101 // now is the time (after all, there's no "later" that would be better).
2102 return main_hc->DoNoLeaks(SYMBOLIZE);
2103 }
2104 return true;
2105 } 2175 }
2106 2176
2107 // static 2177 // static
2108 void HeapLeakChecker::CancelGlobalCheck() { 2178 void HeapLeakChecker::CancelGlobalCheck() {
2109 SpinLockHolder l(&heap_checker_lock); 2179 SpinLockHolder l(&heap_checker_lock);
2110 if (do_main_heap_check) { 2180 if (do_main_heap_check) {
2111 RAW_VLOG(heap_checker_info_level, 2181 RAW_VLOG(heap_checker_info_level,
2112 "Canceling the automatic at-exit whole-program memory leak check"); 2182 "Canceling the automatic at-exit whole-program memory leak check");
2113 do_main_heap_check = false; 2183 do_main_heap_check = false;
2114 } 2184 }
2115 } 2185 }
2116 2186
2117 // static 2187 // static
2118 void HeapLeakChecker::BeforeConstructorsLocked() { 2188 void HeapLeakChecker::BeforeConstructorsLocked() {
2119 RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 2189 RAW_DCHECK(heap_checker_lock.IsHeld(), "");
2120 RAW_CHECK(!constructor_heap_profiling, 2190 RAW_CHECK(!constructor_heap_profiling,
2121 "BeforeConstructorsLocked called multiple times"); 2191 "BeforeConstructorsLocked called multiple times");
2192 #ifdef ADDRESS_SANITIZER
2193 // AddressSanitizer's custom malloc conflicts with HeapChecker.
2194 return;
2195 #endif
2122 // Set hooks early to crash if 'new' gets called before we make heap_profile, 2196 // Set hooks early to crash if 'new' gets called before we make heap_profile,
2123 // and make sure no other hooks existed: 2197 // and make sure no other hooks existed:
2124 RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); 2198 RAW_CHECK(MallocHook::AddNewHook(&NewHook), "");
2125 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); 2199 RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), "");
2126 constructor_heap_profiling = true; 2200 constructor_heap_profiling = true;
2127 MemoryRegionMap::Init(1); 2201 MemoryRegionMap::Init(1);
2128 // Set up MemoryRegionMap with (at least) one caller stack frame to record 2202 // Set up MemoryRegionMap with (at least) one caller stack frame to record
2129 // (important that it's done before HeapProfileTable creation below). 2203 // (important that it's done before HeapProfileTable creation below).
2130 Allocator::Init(); 2204 Allocator::Init();
2131 RAW_CHECK(heap_profile == NULL, ""); 2205 RAW_CHECK(heap_profile == NULL, "");
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
2289 // static 2363 // static
2290 const void* HeapLeakChecker::GetAllocCaller(void* ptr) { 2364 const void* HeapLeakChecker::GetAllocCaller(void* ptr) {
2291 // this is used only in the unittest, so the heavy checks are fine 2365 // this is used only in the unittest, so the heavy checks are fine
2292 HeapProfileTable::AllocInfo info; 2366 HeapProfileTable::AllocInfo info;
2293 { SpinLockHolder l(&heap_checker_lock); 2367 { SpinLockHolder l(&heap_checker_lock);
2294 RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), ""); 2368 RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), "");
2295 } 2369 }
2296 RAW_CHECK(info.stack_depth >= 1, ""); 2370 RAW_CHECK(info.stack_depth >= 1, "");
2297 return info.call_stack[0]; 2371 return info.call_stack[0];
2298 } 2372 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698