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