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

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

Powered by Google App Engine
This is Rietveld 408576698