15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Maxim Lifantsev 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Running: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ./heap-checker_unittest 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the unittest crashes because it can't find pprof, try: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PPROF_PATH=/usr/local/someplace/bin/pprof ./heap-checker_unittest 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test that the whole-program heap checker will actually cause a leak, try: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LEAK= ./heap-checker_unittest 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LOOP_LEAK= ./heap-checker_unittest 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Both of the above commands *should* abort with an error message. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CAVEAT: Do not use vector<> and string on-heap objects in this test, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise the test can sometimes fail for tricky leak checks 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when we want some allocated object not to be found live by the heap checker. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This can happen with memory allocators like tcmalloc that can allocate 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap objects back to back without any book-keeping data in between. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// What happens is that end-of-storage pointers of a live vector 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (or a string depending on the STL implementation used) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can happen to point to that other heap-allocated 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object that is not reachable otherwise and that 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we don't want to be reachable. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The implication of this for real leak checking 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is just one more chance for the liveness flood to be inexact 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (see the comment in our .h file). 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config_for_unittests.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_POLL_H 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <poll.h> 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> // to get uint16_t (ISO naming madness) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h> // another place uint16_t might be defined 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> // errno 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> // for sleep(), geteuid() 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MMAP 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> // for open(), close() 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <execinfo.h> // backtrace 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <grp.h> // getgrent, getgrnam 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pwd.h> 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream> // for cout 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iomanip> // for hex 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory> 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h" 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_lister.h" 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/heap-checker.h> 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "memory_region_map.h" 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_extension.h> 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h> 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// form of the name instead. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MAP_ANONYMOUS 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define MAP_ANONYMOUS MAP_ANON 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace std; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): write a shell script to test that these indeed crash us 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (i.e. we do detect leaks) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maybe add more such crash tests. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_leak, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_LEAK", false), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a leak crash"); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_loop_leak, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_LOOP_LEAK", false), 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a looped leak crash"); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_register_leak, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_REGISTER_LEAK", false), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should cause a leak crash by hiding a pointer " 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "that is only in a register"); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_cancel_global_check, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK", false), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If should test HeapLeakChecker::CancelGlobalCheck " 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "when --test_leak or --test_loop_leak are given; " 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "the test should not fail then"); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(maybe_stripped, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_MAYBE_STRIPPED", true), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we think we can be a stripped binary"); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(interfering_threads, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_INTERFERING_THREADS", true), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we should use threads trying " 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "to interfere with leak checking"); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(hoarding_threads, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_HOARDING_THREADS", true), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If threads (usually the manager thread) are known " 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "to retain some old state in their global buffers, " 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "so that it's hard to force leaks when threads are around"); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(maxim): Chage the default to false 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the standard environment used NTPL threads: 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they do not seem to have this problem. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(no_threads, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECKER_TEST_NO_THREADS", false), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If we should not use any threads"); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is used so we can make can_create_leaks_reliably true 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for any pthread implementation and test with that. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_int64(heap_check_max_pointer_offset); // heap-checker.cc 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_string(heap_check); // in heap-checker.cc 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WARN_IF(cond, msg) LOG_IF(WARNING, cond, msg) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is an evil macro! Be very careful using it... 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef VLOG // and we start by evilling overriding logging.h VLOG 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VLOG(lvl) if (FLAGS_verbose >= (lvl)) cout << "\n" 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is, likewise, evil 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOGF VLOG(INFO) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads(); // below 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Closure { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Closure() { } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() = 0; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Callback0 : public Closure { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback0(FunctionSignature f) : f_(f) {} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(); delete this; } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1> class Callback1 : public Closure { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(P1); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback1<P1>(FunctionSignature f, P1 p1) : f_(f), p1_(p1) {} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(p1_); delete this; } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P1 p1_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2> class Callback2 : public Closure { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef void (*FunctionSignature)(P1,P2); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Callback2<P1,P2>(FunctionSignature f, P1 p1, P2 p2) : f_(f), p1_(p1), p2_(p2) {} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() { (*f_)(p1_, p2_); delete this; } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FunctionSignature f_; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P1 p1_; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P2 p2_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback0* NewCallback(void (*function)()) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback0(function); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1> 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback1<P1>* NewCallback(void (*function)(P1), P1 p1) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback1<P1>(function, p1); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2> 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback2<P1,P2>* NewCallback(void (*function)(P1,P2), P1 p1, P2 p2) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new Callback2<P1,P2>(function, p1, p2); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set to true at end of main, so threads know. Not entirely thread-safe!, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but probably good enough. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool g_have_exited_main = false; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we can reliably create leaks (i.e. make leaked object 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// really unreachable from any global data). 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool can_create_leaks_reliably = false; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use a simple allocation wrapper 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to make sure we wipe out the newly allocated objects 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in case they still happened to contain some pointer data 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accidentally left by the memory allocator. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Initialized { }; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Initialized initialized; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new(size_t size, const Initialized&) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Below we use "p = new(initialized) Foo[1];" and "delete[] p;" 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead of "p = new(initialized) Foo;" 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when we need to delete an allocated object. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = malloc(size); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(p, 0, size); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new[](size_t size, const Initialized&) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = new char[size]; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(p, 0, size); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoWipeStack(int n); // defined below 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WipeStack() { DoWipeStack(20); } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Pause() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll(NULL, 0, 77); // time for thread activity in HeapBusyThreadBody 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indirectly test malloc_extension.*: 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(MallocExtension::instance()->VerifyAllMemory()); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int blocks; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t total; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int histogram[kMallocHistogramSize]; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MallocExtension::instance() 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ->MallocMemoryStats(&blocks, &total, histogram) && total != 0) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << "Malloc stats: " << blocks << " blocks of " 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << total << " bytes"; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kMallocHistogramSize; ++i) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (histogram[i]) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << " Malloc histogram at " << i << " : " << histogram[i]; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // e.g. MallocExtension::VerifyAllMemory 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can leave pointers to heap objects on stack 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make gcc think a pointer is "used" 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Use(T** foo) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Dummy-using " << static_cast<void*>(*foo) << " at " << foo; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arbitrary value, but not such that xor'ing with it is likely 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to map one valid pointer to another valid pointer: 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uintptr_t kHideMask = 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uintptr_t>(0xF03A5F7BF03A5F7BLL); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helpers to hide a pointer from live data traversal. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We just xor the pointer so that (with high probability) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's not a valid address of a heap object anymore. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Both Hide and UnHide must be executed within RunHidden() below 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to prevent leaving stale data on active stack that can be a pointer 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a heap object that is not actually reachable via live variables. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (UnHide might leave heap pointer value for an object 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that will be deallocated but later another object 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can be allocated at the same heap address.) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Hide(T** ptr) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we cast values, not dereferenced pointers, so no aliasing issues: 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "hid: " << static_cast<void*>(*ptr); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void UnHide(T** ptr) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "unhiding: " << static_cast<void*>(*ptr); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we cast values, not dereferenced pointers, so no aliasing issues: 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void LogHidden(const char* message, const void* ptr) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOGF << message << " : " 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ptr << " ^ " << reinterpret_cast<void*>(kHideMask) << endl; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// volatile to fool the compiler against inlining the calls to these 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile run_hidden_ptr)(Closure* c, int n); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile wipe_stack_ptr)(int n); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoRunHidden(Closure* c, int n) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(10) << "Level " << n << " at " << &n; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*run_hidden_ptr)(c, n-1); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*wipe_stack_ptr)(n); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c->Run(); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ void DoWipeStack(int n) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(10) << "Wipe level " << n << " at " << &n; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int sz = 30; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volatile int arr[sz]; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < sz; ++i) arr[i] = 0; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*wipe_stack_ptr)(n-1); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(0); // undo -foptimize-sibling-calls 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This executes closure c several stack frames down from the current one 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and then makes an effort to also wipe out the stack data that was used by 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the closure. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This way we prevent leak checker from finding any temporary pointers 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the closure execution on the stack and deciding that 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these pointers (and the pointed objects) are still live. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHidden(Closure* c) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoRunHidden(c, 15); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWipeStack(20); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoAllocHidden(size_t size, void** ptr) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = new(initialized) char[size]; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&p); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); // use only hidden versions 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Allocated hidden " << p << " at " << &p; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = p; // assign the hidden versions 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* AllocHidden(size_t size) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* r; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoAllocHidden, size, &r)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoDeAllocHidden(void** ptr) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(ptr); // use only hidden versions 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = *ptr; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Deallocating hidden " << p; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnHide(&p); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] reinterpret_cast<char*>(p); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DeAllocHidden(void** ptr) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoDeAllocHidden, ptr)); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = NULL; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(ptr); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PreventHeapReclaiming(size_t size) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (true) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void** no_reclaim_list = NULL; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(size >= sizeof(void*)); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't use malloc_reclaim_memory flag in opt mode as debugallocation.cc 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not used. Instead we allocate a bunch of heap objects that are 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the same size as what we are going to leak to ensure that the object 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are about to leak is not at the same address as some old allocated 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and freed object that might still have pointers leading to it. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 100; ++i) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** p = reinterpret_cast<void**>(new(initialized) char[size]); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[0] = no_reclaim_list; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) no_reclaim_list = p; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool RunSilent(HeapLeakChecker* check, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool (HeapLeakChecker::* func)()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // By default, don't print the 'we detected a leak' message in the 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cases we're expecting a leak (we still print when --v is >= 1). 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This way, the logging output is less confusing: we only print 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "we detected a leak", and how to diagnose it, for *unexpected* leaks. 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 old_FLAGS_verbose = FLAGS_verbose; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VLOG_IS_ON(1)) // not on a verbose setting 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_verbose = FATAL; // only log fatal errors 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool retval = (check->*func)(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_verbose = old_FLAGS_verbose; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retval; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RUN_SILENT(check, func) RunSilent(&(check), &HeapLeakChecker::func) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum CheckType { SAME_HEAP, NO_LEAKS }; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VerifyLeaks(HeapLeakChecker* check, CheckType type, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int leaked_bytes, int leaked_objects) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // to help with can_create_leaks_reliably 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool no_leaks = 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type == NO_LEAKS ? RUN_SILENT(*check, BriefNoLeaks) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : RUN_SILENT(*check, BriefSameHeap); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_create_leaks_reliably) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these might still fail occasionally, but it should be very rare 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(no_leaks, false); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check->BytesLeaked(), leaked_bytes); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check->ObjectsLeaked(), leaked_objects); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(no_leaks != false, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Expected leaks not found: " 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Some liveness flood must be too optimistic"); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathSimple() { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_simple"); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(300); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, 300 + 100 * sizeof(int), 2); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeDeathLoop(void** arr1, void** arr2) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreventHeapReclaiming(2 * sizeof(void*)); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** a1 = new(initialized) void*[2]; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** a2 = new(initialized) void*[2]; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a1[1] = reinterpret_cast<void*>(a2); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a2[1] = reinterpret_cast<void*>(a1); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&a1); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&a2); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&a1); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&a2); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Made hidden loop at " << &a1 << " to " << arr1; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arr1 = a1; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arr2 = a2; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates two objects linked together 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathLoop() { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_loop"); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr1; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arr2; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2)); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr1); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&arr2); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", arr1); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", arr2); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, 4 * sizeof(void*), 2); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&arr1); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&arr2); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathInverse() { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(250 * sizeof(int)); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_inverse"); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * static_cast<int64>(sizeof(int)), 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathNoLeaks() { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(250 * sizeof(int)); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_noleaks"); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check.BriefNoLeaks(), true); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have less objecs 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountLess() { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(50 * sizeof(int)); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(50 * sizeof(int)); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar1); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar2); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_count_less"); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * sizeof(int), 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have more objecs 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountMore() { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", foo); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_count_more"); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(50 * sizeof(int)); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(50 * sizeof(int)); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar1); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", bar2); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, SAME_HEAP, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100 * sizeof(int), 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHiddenPointer() { 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = &i; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HiddenPointer<void> p(foo); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(foo, p.get()); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Confirm pointer doesn't appear to contain a byte sequence 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that == the pointer. We don't really need to test that 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the xor trick itself works, as without it nothing in this 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // test suite would work. See the Hide/Unhide/*Hidden* set 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of helper methods. 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(foo, *reinterpret_cast<void**>(&p)); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple tests that deallocate what they allocated 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakChecker() { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("trivial"); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int foo = 5; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* p = &foo; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("simple"); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(200 * sizeof(int)); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false positives 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerNoFalsePositives() { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("trivial_p"); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int foo = 5; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* p = &foo; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&p); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { HeapLeakChecker check("simple_p"); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo = AllocHidden(100 * sizeof(int)); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar = AllocHidden(200 * sizeof(int)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.SameHeap()); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test that we detect leaks when we have same total # of bytes and 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// objects, but different individual object sizes 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLeakButTotalsMatch() { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(240 * sizeof(int)); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(160 * sizeof(int)); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar1); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Pre leaking", bar2); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("trick"); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo1 = AllocHidden(280 * sizeof(int)); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo1); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo2 = AllocHidden(120 * sizeof(int)); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo2); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo1); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", foo2); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // foo1 and foo2 leaked 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyLeaks(&check, NO_LEAKS, (280+120)*sizeof(int), 2); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo1); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo2); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false negatives from pprof 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathTrick() { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar1 = AllocHidden(240 * sizeof(int)); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar1); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* bar2 = AllocHidden(160 * sizeof(int)); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&bar2); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_trick"); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar1); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&bar2); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo1 = AllocHidden(280 * sizeof(int)); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo1); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* foo2 = AllocHidden(120 * sizeof(int)); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Use(&foo2); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(maxim): use the above if we make pprof work in automated test runs 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_maybe_stripped) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(RUN_SILENT(check, SameHeap), false); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pprof checking should catch the leak 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(RUN_SILENT(check, SameHeap) != false, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "death_trick leak is not caught; " 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "we must be using a stripped binary"); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo1); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeAllocHidden(&foo2); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple leak 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TransLeaks() { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocHidden(1 * sizeof(char)); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// range-based disabling using Disabler 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ScopedDisabledLeaks() { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Disabler disabler; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocHidden(3 * sizeof(int)); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransLeaks(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)malloc(10); // Direct leak 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* RunDisabledLeaks(void* a) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedDisabledLeaks(); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks inside of a thread 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ThreadDisabledLeaks() { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_no_threads) return; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_t tid; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_t attr; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_attr_init(&attr), 0); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_create(&tid, &attr, RunDisabledLeaks, NULL), 0); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* res; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_join(tid, &res), 0); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different disabled leaks (some in threads) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDisabling() { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("disabling"); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunDisabledLeaks(NULL); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadDisabledLeaks(); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.SameHeap()); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef set<int> IntSet; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int some_ints[] = { 1, 2, 3, 21, 22, 23, 24, 25 }; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAlloc() { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = new(initialized) IntSet[1]; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *x = IntSet(some_ints, some_ints + 6); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 1000; i++) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x->insert(i*3); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] x; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal STL usage does not result in a leak report. 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false leak report in this case.) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAlloc() { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("stl"); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoTestSTLAlloc)); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(check.BriefSameHeap(), true); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAllocInverse(IntSet** setx) { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = new(initialized) IntSet[1]; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *x = IntSet(some_ints, some_ints + 3); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 100; i++) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x->insert(i*2); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(&x); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *setx = x; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void FreeTestSTLAllocInverse(IntSet** setx) { 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x = *setx; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnHide(&x); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] x; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal leaked STL usage *does* result in a leak report. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false absence of leak report in this case.) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAllocInverse() { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check("death_inverse_stl"); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntSet* x; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(DoTestSTLAllocInverse, &x)); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogHidden("Leaking", x); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_create_leaks_reliably) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WipeStack(); // to help with can_create_leaks_reliably 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these might still fail occasionally, but it should be very rare 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(RUN_SILENT(check, BriefNoLeaks), false); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(check.BytesLeaked(), 100 * sizeof(int)); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(check.ObjectsLeaked(), 100); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assumes set<>s are represented by some kind of binary tree 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or something else allocating >=1 heap object per set object 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WARN_IF(RUN_SILENT(check, BriefNoLeaks) != false, 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Expected leaks not found: " 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Some liveness flood must be too optimistic"); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunHidden(NewCallback(FreeTestSTLAllocInverse, &x)); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class Alloc> 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DirectTestSTLAlloc(Alloc allocator, const char* name) { 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker check((string("direct_stl-") + name).c_str()); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kSize = 1000; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename Alloc::pointer ptrs[kSize]; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; ++i) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename Alloc::pointer p = allocator.allocate(i*3+1); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(p); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will crash if p is not known to heap profiler: 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (i.e. STL's "allocator" does not have a direct hook to heap profiler) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::UnIgnoreObject(p); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptrs[i] = p; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kSize; ++i) { 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator.deallocate(ptrs[i], i*3+1); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptrs[i] = NULL; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(check.BriefSameHeap()); // just in case 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct group* grp = NULL; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kKeys = 50; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_key_t key[kKeys]; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyFree(void* ptr) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] reinterpret_cast<char*>(ptr); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool key_init_has_run = false; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyInit() { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kKeys; ++i) { 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_key_create(&key[i], KeyFree), 0); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "pthread key " << i << " : " << key[i]; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_init_has_run = true; // needed for a sanity-check 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// force various C library static and thread-specific allocations 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLibCAllocate() { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(key_init_has_run); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kKeys; ++i) { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = pthread_getspecific(key[i]); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == p) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test-logging inside threads which (potentially) creates and uses 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-local data inside standard C++ library: 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Adding pthread-specifics for thread " << pthread_self() 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " pid " << getpid(); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = new(initialized) char[77 + i]; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "pthread specific " << i << " : " << p; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_setspecific(key[i], p); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strerror(errno); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const time_t now = time(NULL); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctime(&now); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *stack[1]; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backtrace(stack, 1); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gid_t gid = getgid(); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getgrgid(gid); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (grp == NULL) grp = getgrent(); // a race condition here is okay 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getgrnam(grp->gr_name); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getpwuid(geteuid()); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Continuous random heap memory activity to try to disrupt heap checking. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* HeapBusyThreadBody(void* a) { 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int thread_num = reinterpret_cast<intptr_t>(a); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "A new HeapBusyThread " << thread_num; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int user = 0; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to hide ptr from heap checker in a CPU register: 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Here we are just making a best effort to put the only pointer 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to a heap object into a thread register to test 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the thread-register finding machinery in the heap checker. 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__i386__) && defined(__GNUC__) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr asm("esi"); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__x86_64__) && defined(__GNUC__) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr asm("r15"); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register int** ptr; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = NULL; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef set<int> Set; 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set s1; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (1) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TestLibCAllocate() calls libc functions that don't work so well 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after main() has exited. So we just don't do the test then. 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_have_exited_main) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestLibCAllocate(); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr == NULL) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = new(initialized) int*[1]; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr = new(initialized) int[1]; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set<int>* s2 = new(initialized) set<int>[1]; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.insert(random()); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s2->insert(*s1.begin()); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user += *s2->begin(); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **ptr += user; 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 51 == 0) { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.clear(); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 2 == 0) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.~Set(); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new(&s1) Set; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << pthread_self() << " (" << getpid() << "): in wait: " 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ptr << ", " << *ptr << "; " << s1.size(); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << pthread_self() << " (" << getpid() << "): in wait, ptr = " 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << reinterpret_cast<void*>( 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "^" << reinterpret_cast<void*>(kHideMask); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_register_leak && thread_num % 5 == 0) { 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hide the register "ptr" value with an xor mask. 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If one provides --test_register_leak flag, the test should 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (with very high probability) crash on some leak check 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a leak report (of some x * sizeof(int) + y * sizeof(int*) bytes) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointing at the two lines above in this function 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with "new(initialized) int" in them as the allocators 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the leaked objects. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CAVEAT: We can't really prevent a compiler to save some 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // temporary values of "ptr" on the stack and thus let us find 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the heap objects not via the register. 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hence it's normal if for certain compilers or optimization modes 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // --test_register_leak does not cause a leak crash of the above form 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (this happens e.g. for gcc 4.0.1 in opt mode). 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = reinterpret_cast<int **>( 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // busy loop to get the thread interrupted at: 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 1; i < 10000000; ++i) user += (1 + user * user * 5) / i; 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = reinterpret_cast<int **>( 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<uintptr_t>(ptr) ^ kHideMask); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll(NULL, 0, random() % 100); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << pthread_self() << ": continuing"; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (random() % 3 == 0) { 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] *ptr; 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] ptr; 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = NULL; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete [] s2; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads() { 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeyInit(); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_interfering_threads || FLAGS_no_threads) return; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int n = 17; // make many threads 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_t tid; 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_t attr; 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(pthread_attr_init(&attr), 0); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make them and let them run 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < n; ++i) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Creating extra thread " << i + 1; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pthread_create(&tid, &attr, HeapBusyThreadBody, 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(i)) == 0); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pause(); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= // 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code section is to test that objects that are reachable from global 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// variables are not reported as leaks 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as that (Un)IgnoreObject work for such objects fine. 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An object making functions: 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a "weird" pointer to a new object for which 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's worth checking that the object is reachable via that pointer. 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void* (*ObjMakerFunc)(); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<ObjMakerFunc> obj_makers; // list of registered object makers 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper macro to register an object making function 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'name' is an identifier of this object maker, 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'body' is its function body that must declare 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointer 'p' to the nex object to return. 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage example: 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// REGISTER_OBJ_MAKER(trivial, int* p = new(initialized) int;) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REGISTER_OBJ_MAKER(name, body) \ 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ObjMaker_##name##_() { \ 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Obj making " << #name; \ 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body; \ 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; \ 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ObjMakerRegistrar maker_reg_##name##__(&ObjMaker_##name##_); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// helper class for REGISTER_OBJ_MAKER 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ObjMakerRegistrar { 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjMakerRegistrar(ObjMakerFunc obj_maker) { obj_makers.push_back(obj_maker); } 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of the objects/pointers made with all the obj_makers 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test reachability via global data pointers during leak checks. 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<void*>* live_objects = new list<void*>; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer so that it does not get destructed on exit 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exerciser for one ObjMakerFunc. 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestPointerReach(ObjMakerFunc obj_maker) { 998