blob: c170bc79082743dcdf152aff7366016a8db69ef3 [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2000, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// ---
32// Author: Urs Holzle <opensource@google.com>
33
34#include "config.h"
35#include <errno.h>
36#ifdef HAVE_FCNTL_H
37#include <fcntl.h>
38#endif
39#ifdef HAVE_INTTYPES_H
40#include <inttypes.h>
41#endif
42// We only need malloc.h for struct mallinfo.
43#ifdef HAVE_STRUCT_MALLINFO
44// Malloc can be in several places on older versions of OS X.
45# if defined(HAVE_MALLOC_H)
46# include <malloc.h>
47# elif defined(HAVE_MALLOC_MALLOC_H)
48# include <malloc/malloc.h>
49# elif defined(HAVE_SYS_MALLOC_H)
50# include <sys/malloc.h>
51# endif
52#endif
53#ifdef HAVE_PTHREAD
54#include <pthread.h>
55#endif
56#include <stdarg.h>
57#include <stdio.h>
58#include <string.h>
59#ifdef HAVE_MMAP
60#include <sys/mman.h>
61#endif
62#include <sys/stat.h>
63#include <sys/types.h>
64#ifdef HAVE_UNISTD_H
65#include <unistd.h>
66#endif
67
68#include <gperftools/malloc_extension.h>
69#include <gperftools/malloc_hook.h>
70#include <gperftools/stacktrace.h>
71#include "addressmap-inl.h"
72#include "base/commandlineflags.h"
73#include "base/googleinit.h"
74#include "base/logging.h"
75#include "base/spinlock.h"
76#include "malloc_hook-inl.h"
77#include "symbolize.h"
78
79// NOTE: due to #define below, tcmalloc.cc will omit tc_XXX
80// definitions. So that debug implementations can be defined
81// instead. We're going to use do_malloc, do_free and other do_XXX
82// functions that are defined in tcmalloc.cc for actual memory
83// management
84#define TCMALLOC_USING_DEBUGALLOCATION
85#include "tcmalloc.cc"
86
87// __THROW is defined in glibc systems. It means, counter-intuitively,
88// "This function will never throw an exception." It's an optional
89// optimization tool, but we may need to use it to match glibc prototypes.
90#ifndef __THROW // I guess we're not on a glibc system
91# define __THROW // __THROW is just an optimization, so ok to make it ""
92#endif
93
94// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
95// form of the name instead.
96#ifndef MAP_ANONYMOUS
97# define MAP_ANONYMOUS MAP_ANON
98#endif
99
100// ========================================================================= //
101
102DEFINE_bool(malloctrace,
103 EnvToBool("TCMALLOC_TRACE", false),
104 "Enables memory (de)allocation tracing to /tmp/google.alloc.");
105#ifdef HAVE_MMAP
106DEFINE_bool(malloc_page_fence,
107 EnvToBool("TCMALLOC_PAGE_FENCE", false),
108 "Enables putting of memory allocations at page boundaries "
109 "with a guard page following the allocation (to catch buffer "
110 "overruns right when they happen).");
111DEFINE_bool(malloc_page_fence_never_reclaim,
112 EnvToBool("TCMALLOC_PAGE_FRANCE_NEVER_RECLAIM", false),
113 "Enables making the virtual address space inaccessible "
114 "upon a deallocation instead of returning it and reusing later.");
115#else
116DEFINE_bool(malloc_page_fence, false, "Not usable (requires mmap)");
117DEFINE_bool(malloc_page_fence_never_reclaim, false, "Not usable (required mmap)");
118#endif
119DEFINE_bool(malloc_reclaim_memory,
120 EnvToBool("TCMALLOC_RECLAIM_MEMORY", true),
121 "If set to false, we never return memory to malloc "
122 "when an object is deallocated. This ensures that all "
123 "heap object addresses are unique.");
124DEFINE_int32(max_free_queue_size,
125 EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024),
126 "If greater than 0, keep freed blocks in a queue instead of "
127 "releasing them to the allocator immediately. Release them when "
128 "the total size of all blocks in the queue would otherwise exceed "
129 "this limit.");
130
131DEFINE_bool(symbolize_stacktrace,
132 EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true),
133 "Symbolize the stack trace when provided (on some error exits)");
134
135// If we are LD_PRELOAD-ed against a non-pthreads app, then
136// pthread_once won't be defined. We declare it here, for that
137// case (with weak linkage) which will cause the non-definition to
138// resolve to NULL. We can then check for NULL or not in Instance.
139extern "C" int pthread_once(pthread_once_t *, void (*)(void))
140 ATTRIBUTE_WEAK;
141
142// ========================================================================= //
143
144// A safe version of printf() that does not do any allocation and
145// uses very little stack space.
146static void TracePrintf(int fd, const char *fmt, ...)
147 __attribute__ ((__format__ (__printf__, 2, 3)));
148
149// Round "value" up to next "alignment" boundary.
150// Requires that "alignment" be a power of two.
151static intptr_t RoundUp(intptr_t value, intptr_t alignment) {
152 return (value + alignment - 1) & ~(alignment - 1);
153}
154
155// ========================================================================= //
156
157class MallocBlock;
158
159// A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate
160// (below) pushes blocks into this queue instead of returning them to the
161// underlying allocator immediately. See MallocBlock::Deallocate for more
162// information.
163//
164// We can't use an STL class for this because we need to be careful not to
165// perform any heap de-allocations in any of the code in this class, since the
166// code in MallocBlock::Deallocate is not re-entrant.
167template <typename QueueEntry>
168class FreeQueue {
169 public:
170 FreeQueue() : q_front_(0), q_back_(0) {}
171
172 bool Full() {
173 return (q_front_ + 1) % kFreeQueueSize == q_back_;
174 }
175
176 void Push(const QueueEntry& block) {
177 q_[q_front_] = block;
178 q_front_ = (q_front_ + 1) % kFreeQueueSize;
179 }
180
181 QueueEntry Pop() {
182 RAW_CHECK(q_back_ != q_front_, "Queue is empty");
183 const QueueEntry& ret = q_[q_back_];
184 q_back_ = (q_back_ + 1) % kFreeQueueSize;
185 return ret;
186 }
187
188 size_t size() const {
189 return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize;
190 }
191
192 private:
193 // Maximum number of blocks kept in the free queue before being freed.
194 static const int kFreeQueueSize = 1024;
195
196 QueueEntry q_[kFreeQueueSize];
197 int q_front_;
198 int q_back_;
199};
200
201struct MallocBlockQueueEntry {
202 MallocBlockQueueEntry() : block(NULL), size(0),
203 num_deleter_pcs(0), deleter_threadid(0) {}
204 MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) {
205 if (FLAGS_max_free_queue_size != 0 && b != NULL) {
206 // Adjust the number of frames to skip (4) if you change the
207 // location of this call.
208 num_deleter_pcs =
209 GetStackTrace(deleter_pcs,
210 sizeof(deleter_pcs) / sizeof(deleter_pcs[0]),
211 4);
212 deleter_threadid = pthread_self();
213 } else {
214 num_deleter_pcs = 0;
215 // Zero is an illegal pthread id by my reading of the pthread
216 // implementation:
217 deleter_threadid = 0;
218 }
219 }
220
221 MallocBlock* block;
222 size_t size;
223
224 // When deleted and put in the free queue, we (flag-controlled)
225 // record the stack so that if corruption is later found, we can
226 // print the deleter's stack. (These three vars add 144 bytes of
227 // overhead under the LP64 data model.)
228 void* deleter_pcs[16];
229 int num_deleter_pcs;
230 pthread_t deleter_threadid;
231};
232
233class MallocBlock {
234 public: // allocation type constants
235
236 // Different allocation types we distinguish.
237 // Note: The lower 4 bits are not random: we index kAllocName array
238 // by these values masked with kAllocTypeMask;
239 // the rest are "random" magic bits to help catch memory corruption.
240 static const int kMallocType = 0xEFCDAB90;
241 static const int kNewType = 0xFEBADC81;
242 static const int kArrayNewType = 0xBCEADF72;
243
244 private: // constants
245
246 // A mask used on alloc types above to get to 0, 1, 2
247 static const int kAllocTypeMask = 0x3;
248 // An additional bit to set in AllocType constants
249 // to mark now deallocated regions.
250 static const int kDeallocatedTypeBit = 0x4;
251
252 // For better memory debugging, we initialize all storage to known
253 // values, and overwrite the storage when it's deallocated:
254 // Byte that fills uninitialized storage.
255 static const int kMagicUninitializedByte = 0xAB;
256 // Byte that fills deallocated storage.
257 // NOTE: tcmalloc.cc depends on the value of kMagicDeletedByte
258 // to work around a bug in the pthread library.
259 static const int kMagicDeletedByte = 0xCD;
260 // A size_t (type of alloc_type_ below) in a deallocated storage
261 // filled with kMagicDeletedByte.
262 static const size_t kMagicDeletedSizeT =
263 0xCDCDCDCD | (((size_t)0xCDCDCDCD << 16) << 16);
264 // Initializer works for 32 and 64 bit size_ts;
265 // "<< 16 << 16" is to fool gcc from issuing a warning
266 // when size_ts are 32 bits.
267
268 // NOTE: on Linux, you can enable malloc debugging support in libc by
269 // setting the environment variable MALLOC_CHECK_ to 1 before you
270 // start the program (see man malloc).
271
272 // We use either do_malloc or mmap to make the actual allocation. In
273 // order to remember which one of the two was used for any block, we store an
274 // appropriate magic word next to the block.
275 static const int kMagicMalloc = 0xDEADBEEF;
276 static const int kMagicMMap = 0xABCDEFAB;
277
278 // This array will be filled with 0xCD, for use with memcmp.
279 static unsigned char kMagicDeletedBuffer[1024];
280 static pthread_once_t deleted_buffer_initialized_;
281 static bool deleted_buffer_initialized_no_pthreads_;
282
283 private: // data layout
284
285 // The four fields size1_,offset_,magic1_,alloc_type_
286 // should together occupy a multiple of 16 bytes. (At the
287 // moment, sizeof(size_t) == 4 or 8 depending on piii vs
288 // k8, and 4 of those sum to 16 or 32 bytes).
289 // This, combined with do_malloc's alignment guarantees,
290 // ensures that SSE types can be stored into the returned
291 // block, at &size2_.
292 size_t size1_;
293 size_t offset_; // normally 0 unless memaligned memory
294 // see comments in memalign() and FromRawPointer().
295 size_t magic1_;
296 size_t alloc_type_;
297 // here comes the actual data (variable length)
298 // ...
299 // then come the size2_ and magic2_, or a full page of mprotect-ed memory
300 // if the malloc_page_fence feature is enabled.
301 size_t size2_;
302 int magic2_;
303
304 private: // static data and helpers
305
306 // Allocation map: stores the allocation type for each allocated object,
307 // or the type or'ed with kDeallocatedTypeBit
308 // for each formerly allocated object.
309 typedef AddressMap<int> AllocMap;
310 static AllocMap* alloc_map_;
311 // This protects alloc_map_ and consistent state of metadata
312 // for each still-allocated object in it.
313 // We use spin locks instead of pthread_mutex_t locks
314 // to prevent crashes via calls to pthread_mutex_(un)lock
315 // for the (de)allocations coming from pthreads initialization itself.
316 static SpinLock alloc_map_lock_;
317
318 // A queue of freed blocks. Instead of releasing blocks to the allocator
319 // immediately, we put them in a queue, freeing them only when necessary
320 // to keep the total size of all the freed blocks below the limit set by
321 // FLAGS_max_free_queue_size.
322 static FreeQueue<MallocBlockQueueEntry>* free_queue_;
323
324 static size_t free_queue_size_; // total size of blocks in free_queue_
325 // protects free_queue_ and free_queue_size_
326 static SpinLock free_queue_lock_;
327
328 // Names of allocation types (kMallocType, kNewType, kArrayNewType)
329 static const char* const kAllocName[];
330 // Names of corresponding deallocation types
331 static const char* const kDeallocName[];
332
333 static const char* AllocName(int type) {
334 return kAllocName[type & kAllocTypeMask];
335 }
336
337 static const char* DeallocName(int type) {
338 return kDeallocName[type & kAllocTypeMask];
339 }
340
341 private: // helper accessors
342
343 bool IsMMapped() const { return kMagicMMap == magic1_; }
344
345 bool IsValidMagicValue(int value) const {
346 return kMagicMMap == value || kMagicMalloc == value;
347 }
348
349 static size_t real_malloced_size(size_t size) {
350 return size + sizeof(MallocBlock);
351 }
352
353 /*
354 * Here we assume size of page is kMinAlign aligned,
355 * so if size is MALLOC_ALIGNMENT aligned too, then we could
356 * guarantee return address is also kMinAlign aligned, because
357 * mmap return address at nearby page boundary on Linux.
358 */
359 static size_t real_mmapped_size(size_t size) {
360 size_t tmp = size + MallocBlock::data_offset();
361 tmp = RoundUp(tmp, kMinAlign);
362 return tmp;
363 }
364
365 size_t real_size() {
366 return IsMMapped() ? real_mmapped_size(size1_) : real_malloced_size(size1_);
367 }
368
369 // NOTE: if the block is mmapped (that is, we're using the
370 // malloc_page_fence option) then there's no size2 or magic2
371 // (instead, the guard page begins where size2 would be).
372
373 size_t* size2_addr() { return (size_t*)((char*)&size2_ + size1_); }
374 const size_t* size2_addr() const {
375 return (const size_t*)((char*)&size2_ + size1_);
376 }
377
378 int* magic2_addr() { return (int*)(size2_addr() + 1); }
379 const int* magic2_addr() const { return (const int*)(size2_addr() + 1); }
380
381 private: // other helpers
382
383 void Initialize(size_t size, int type) {
384 RAW_CHECK(IsValidMagicValue(magic1_), "");
385 // record us as allocated in the map
386 alloc_map_lock_.Lock();
387 if (!alloc_map_) {
388 void* p = do_malloc(sizeof(AllocMap));
389 alloc_map_ = new(p) AllocMap(do_malloc, do_free);
390 }
391 alloc_map_->Insert(data_addr(), type);
392 // initialize us
393 size1_ = size;
394 offset_ = 0;
395 alloc_type_ = type;
396 if (!IsMMapped()) {
397 *magic2_addr() = magic1_;
398 *size2_addr() = size;
399 }
400 alloc_map_lock_.Unlock();
401 memset(data_addr(), kMagicUninitializedByte, size);
402 if (!IsMMapped()) {
403 RAW_CHECK(size1_ == *size2_addr(), "should hold");
404 RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
405 }
406 }
407
408 size_t CheckAndClear(int type) {
409 alloc_map_lock_.Lock();
410 CheckLocked(type);
411 if (!IsMMapped()) {
412 RAW_CHECK(size1_ == *size2_addr(), "should hold");
413 }
414 // record us as deallocated in the map
415 alloc_map_->Insert(data_addr(), type | kDeallocatedTypeBit);
416 alloc_map_lock_.Unlock();
417 // clear us
418 const size_t size = real_size();
419 memset(this, kMagicDeletedByte, size);
420 return size;
421 }
422
423 void CheckLocked(int type) const {
424 int map_type = 0;
425 const int* found_type =
426 alloc_map_ != NULL ? alloc_map_->Find(data_addr()) : NULL;
427 if (found_type == NULL) {
428 RAW_LOG(FATAL, "memory allocation bug: object at %p "
429 "has never been allocated", data_addr());
430 } else {
431 map_type = *found_type;
432 }
433 if ((map_type & kDeallocatedTypeBit) != 0) {
434 RAW_LOG(FATAL, "memory allocation bug: object at %p "
435 "has been already deallocated (it was allocated with %s)",
436 data_addr(), AllocName(map_type & ~kDeallocatedTypeBit));
437 }
438 if (alloc_type_ == kMagicDeletedSizeT) {
439 RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
440 "has been corrupted; or else the object has been already "
441 "deallocated and our memory map has been corrupted",
442 data_addr());
443 }
444 if (!IsValidMagicValue(magic1_)) {
445 RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
446 "has been corrupted; "
447 "or else our memory map has been corrupted and this is a "
448 "deallocation for not (currently) heap-allocated object",
449 data_addr());
450 }
451 if (!IsMMapped()) {
452 if (size1_ != *size2_addr()) {
453 RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
454 "has been corrupted", data_addr());
455 }
456 if (!IsValidMagicValue(*magic2_addr())) {
457 RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
458 "has been corrupted", data_addr());
459 }
460 }
461 if (alloc_type_ != type) {
462 if ((alloc_type_ != MallocBlock::kMallocType) &&
463 (alloc_type_ != MallocBlock::kNewType) &&
464 (alloc_type_ != MallocBlock::kArrayNewType)) {
465 RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
466 "has been corrupted", data_addr());
467 }
468 RAW_LOG(FATAL, "memory allocation/deallocation mismatch at %p: "
469 "allocated with %s being deallocated with %s",
470 data_addr(), AllocName(alloc_type_), DeallocName(type));
471 }
472 if (alloc_type_ != map_type) {
473 RAW_LOG(FATAL, "memory stomping bug: our memory map has been corrupted : "
474 "allocation at %p made with %s "
475 "is recorded in the map to be made with %s",
476 data_addr(), AllocName(alloc_type_), AllocName(map_type));
477 }
478 }
479
480 public: // public accessors
481
482 void* data_addr() { return (void*)&size2_; }
483 const void* data_addr() const { return (const void*)&size2_; }
484
485 static size_t data_offset() { return OFFSETOF_MEMBER(MallocBlock, size2_); }
486
487 size_t data_size() const { return size1_; }
488
489 void set_offset(int offset) { this->offset_ = offset; }
490
491 public: // our main interface
492
493 static MallocBlock* Allocate(size_t size, int type) {
494 // Prevent an integer overflow / crash with large allocation sizes.
495 // TODO - Note that for a e.g. 64-bit size_t, max_size_t may not actually
496 // be the maximum value, depending on how the compiler treats ~0. The worst
497 // practical effect is that allocations are limited to 4Gb or so, even if
498 // the address space could take more.
499 static size_t max_size_t = ~0;
500 if (size > max_size_t - sizeof(MallocBlock)) {
501 RAW_LOG(ERROR, "Massive size passed to malloc: %" PRIuS "", size);
502 return NULL;
503 }
504 MallocBlock* b = NULL;
505 const bool use_malloc_page_fence = FLAGS_malloc_page_fence;
506#ifdef HAVE_MMAP
507 if (use_malloc_page_fence) {
508 // Put the block towards the end of the page and make the next page
509 // inaccessible. This will catch buffer overrun right when it happens.
510 size_t sz = real_mmapped_size(size);
511 int pagesize = getpagesize();
512 int num_pages = (sz + pagesize - 1) / pagesize + 1;
513 char* p = (char*) mmap(NULL, num_pages * pagesize, PROT_READ|PROT_WRITE,
514 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
515 if (p == MAP_FAILED) {
516 // If the allocation fails, abort rather than returning NULL to
517 // malloc. This is because in most cases, the program will run out
518 // of memory in this mode due to tremendous amount of wastage. There
519 // is no point in propagating the error elsewhere.
520 RAW_LOG(FATAL, "Out of memory: possibly due to page fence overhead: %s",
521 strerror(errno));
522 }
523 // Mark the page after the block inaccessible
524 if (mprotect(p + (num_pages - 1) * pagesize, pagesize, PROT_NONE)) {
525 RAW_LOG(FATAL, "Guard page setup failed: %s", strerror(errno));
526 }
527 b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz);
528 } else {
529 b = (MallocBlock*) do_malloc(real_malloced_size(size));
530 }
531#else
532 b = (MallocBlock*) do_malloc(real_malloced_size(size));
533#endif
534
535 // It would be nice to output a diagnostic on allocation failure
536 // here, but logging (other than FATAL) requires allocating
537 // memory, which could trigger a nasty recursion. Instead, preserve
538 // malloc semantics and return NULL on failure.
539 if (b != NULL) {
540 b->magic1_ = use_malloc_page_fence ? kMagicMMap : kMagicMalloc;
541 b->Initialize(size, type);
542 }
543 return b;
544 }
545
546 void Deallocate(int type) {
547 if (IsMMapped()) { // have to do this before CheckAndClear
548#ifdef HAVE_MMAP
549 int size = CheckAndClear(type);
550 int pagesize = getpagesize();
551 int num_pages = (size + pagesize - 1) / pagesize + 1;
552 char* p = (char*) this;
553 if (FLAGS_malloc_page_fence_never_reclaim ||
554 !FLAGS_malloc_reclaim_memory) {
555 mprotect(p - (num_pages - 1) * pagesize + size,
556 num_pages * pagesize, PROT_NONE);
557 } else {
558 munmap(p - (num_pages - 1) * pagesize + size, num_pages * pagesize);
559 }
560#endif
561 } else {
562 const size_t size = CheckAndClear(type);
563 if (FLAGS_malloc_reclaim_memory) {
564 // Instead of freeing the block immediately, push it onto a queue of
565 // recently freed blocks. Free only enough blocks to keep from
566 // exceeding the capacity of the queue or causing the total amount of
567 // un-released memory in the queue from exceeding
568 // FLAGS_max_free_queue_size.
569 ProcessFreeQueue(this, size, FLAGS_max_free_queue_size);
570 }
571 }
572 }
573
574 static size_t FreeQueueSize() {
575 SpinLockHolder l(&free_queue_lock_);
576 return free_queue_size_;
577 }
578
579 static void ProcessFreeQueue(MallocBlock* b, size_t size,
580 int max_free_queue_size) {
581 // MallocBlockQueueEntry are about 144 in size, so we can only
582 // use a small array of them on the stack.
583 MallocBlockQueueEntry entries[4];
584 int num_entries = 0;
585 MallocBlockQueueEntry new_entry(b, size);
586 free_queue_lock_.Lock();
587 if (free_queue_ == NULL)
588 free_queue_ = new FreeQueue<MallocBlockQueueEntry>;
589 RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!");
590
591 if (b != NULL) {
592 free_queue_size_ += size + sizeof(MallocBlockQueueEntry);
593 free_queue_->Push(new_entry);
594 }
595
596 // Free blocks until the total size of unfreed blocks no longer exceeds
597 // max_free_queue_size, and the free queue has at least one free
598 // space in it.
599 while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) {
600 RAW_CHECK(num_entries < arraysize(entries), "entries array overflow");
601 entries[num_entries] = free_queue_->Pop();
602 free_queue_size_ -=
603 entries[num_entries].size + sizeof(MallocBlockQueueEntry);
604 num_entries++;
605 if (num_entries == arraysize(entries)) {
606 // The queue will not be full at this point, so it is ok to
607 // release the lock. The queue may still contain more than
608 // max_free_queue_size, but this is not a strict invariant.
609 free_queue_lock_.Unlock();
610 for (int i = 0; i < num_entries; i++) {
611 CheckForDanglingWrites(entries[i]);
612 do_free(entries[i].block);
613 }
614 num_entries = 0;
615 free_queue_lock_.Lock();
616 }
617 }
618 RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
619 free_queue_lock_.Unlock();
620 for (int i = 0; i < num_entries; i++) {
621 CheckForDanglingWrites(entries[i]);
622 do_free(entries[i].block);
623 }
624 }
625
626 static void InitDeletedBuffer() {
627 memset(kMagicDeletedBuffer, kMagicDeletedByte, sizeof(kMagicDeletedBuffer));
628 deleted_buffer_initialized_no_pthreads_ = true;
629 }
630
631 static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) {
632 // Initialize the buffer if necessary.
633 if (pthread_once)
634 pthread_once(&deleted_buffer_initialized_, &InitDeletedBuffer);
635 if (!deleted_buffer_initialized_no_pthreads_) {
636 // This will be the case on systems that don't link in pthreads,
637 // including on FreeBSD where pthread_once has a non-zero address
638 // (but doesn't do anything) even when pthreads isn't linked in.
639 InitDeletedBuffer();
640 }
641
642 const unsigned char* p =
643 reinterpret_cast<unsigned char*>(queue_entry.block);
644
645 static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer);
646 const size_t size = queue_entry.size;
647 const size_t buffers = size / size_of_buffer;
648 const size_t remainder = size % size_of_buffer;
649 size_t buffer_idx;
650 for (buffer_idx = 0; buffer_idx < buffers; ++buffer_idx) {
651 CheckForCorruptedBuffer(queue_entry, buffer_idx, p, size_of_buffer);
652 p += size_of_buffer;
653 }
654 CheckForCorruptedBuffer(queue_entry, buffer_idx, p, remainder);
655 }
656
657 static void CheckForCorruptedBuffer(const MallocBlockQueueEntry& queue_entry,
658 size_t buffer_idx,
659 const unsigned char* buffer,
660 size_t size_of_buffer) {
661 if (memcmp(buffer, kMagicDeletedBuffer, size_of_buffer) == 0) {
662 return;
663 }
664
665 RAW_LOG(ERROR,
666 "Found a corrupted memory buffer in MallocBlock (may be offset "
667 "from user ptr): buffer index: %zd, buffer ptr: %p, size of "
668 "buffer: %zd", buffer_idx, buffer, size_of_buffer);
669
670 // The magic deleted buffer should only be 1024 bytes, but in case
671 // this changes, let's put an upper limit on the number of debug
672 // lines we'll output:
673 if (size_of_buffer <= 1024) {
674 for (int i = 0; i < size_of_buffer; ++i) {
675 if (buffer[i] != kMagicDeletedByte) {
676 RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0x%02x).",
677 i, buffer[i], kMagicDeletedByte);
678 }
679 }
680 } else {
681 RAW_LOG(ERROR, "Buffer too large to print corruption.");
682 }
683
684 const MallocBlock* b = queue_entry.block;
685 const size_t size = queue_entry.size;
686 if (queue_entry.num_deleter_pcs > 0) {
687 TracePrintf(STDERR_FILENO, "Deleted by thread %p\n",
688 reinterpret_cast<void*>(
689 PRINTABLE_PTHREAD(queue_entry.deleter_threadid)));
690
691 // We don't want to allocate or deallocate memory here, so we use
692 // placement-new. It's ok that we don't destroy this, since we're
693 // just going to error-exit below anyway. Union is for alignment.
694 union { void* alignment; char buf[sizeof(SymbolTable)]; } tablebuf;
695 SymbolTable* symbolization_table = new (tablebuf.buf) SymbolTable;
696 for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
697 // Symbolizes the previous address of pc because pc may be in the
698 // next function. This may happen when the function ends with
699 // a call to a function annotated noreturn (e.g. CHECK).
700 char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
701 symbolization_table->Add(pc - 1);
702 }
703 if (FLAGS_symbolize_stacktrace)
704 symbolization_table->Symbolize();
705 for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
706 char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
707 TracePrintf(STDERR_FILENO, " @ %p %s\n",
708 pc, symbolization_table->GetSymbol(pc - 1));
709 }
710 } else {
711 RAW_LOG(ERROR,
712 "Skipping the printing of the deleter's stack! Its stack was "
713 "not found; either the corruption occurred too early in "
714 "execution to obtain a stack trace or --max_free_queue_size was "
715 "set to 0.");
716 }
717
718 RAW_LOG(FATAL,
719 "Memory was written to after being freed. MallocBlock: %p, user "
720 "ptr: %p, size: %zd. If you can't find the source of the error, "
721 "try using ASan (http://code.google.com/p/address-sanitizer/), "
722 "Valgrind, or Purify, or study the "
723 "output of the deleter's stack printed above.",
724 b, b->data_addr(), size);
725 }
726
727 static MallocBlock* FromRawPointer(void* p) {
728 const size_t data_offset = MallocBlock::data_offset();
729 // Find the header just before client's memory.
730 MallocBlock *mb = reinterpret_cast<MallocBlock *>(
731 reinterpret_cast<char *>(p) - data_offset);
732 // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer.
733 if (mb->alloc_type_ == kMagicDeletedSizeT) {
734 RAW_LOG(FATAL, "memory allocation bug: object at %p has been already"
735 " deallocated; or else a word before the object has been"
736 " corrupted (memory stomping bug)", p);
737 }
738 // If mb->offset_ is zero (common case), mb is the real header.
739 // If mb->offset_ is non-zero, this block was allocated by debug
740 // memallign implementation, and mb->offset_ is the distance
741 // backwards to the real header from mb, which is a fake header.
742 if (mb->offset_ == 0) {
743 return mb;
744 }
745
746 MallocBlock *main_block = reinterpret_cast<MallocBlock *>(
747 reinterpret_cast<char *>(mb) - mb->offset_);
748
749 if (main_block->offset_ != 0) {
750 RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
751 " Need 0 but got %x",
752 (unsigned)(main_block->offset_));
753 }
754 if (main_block >= p) {
755 RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
756 " Detected main_block address overflow: %x",
757 (unsigned)(mb->offset_));
758 }
759 if (main_block->size2_addr() < p) {
760 RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted."
761 " It points below it's own main_block: %x",
762 (unsigned)(mb->offset_));
763 }
764
765 return main_block;
766 }
767
768 static const MallocBlock* FromRawPointer(const void* p) {
769 // const-safe version: we just cast about
770 return FromRawPointer(const_cast<void*>(p));
771 }
772
773 void Check(int type) const {
774 alloc_map_lock_.Lock();
775 CheckLocked(type);
776 alloc_map_lock_.Unlock();
777 }
778
779 static bool CheckEverything() {
780 alloc_map_lock_.Lock();
781 if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0);
782 alloc_map_lock_.Unlock();
783 return true; // if we get here, we're okay
784 }
785
786 static bool MemoryStats(int* blocks, size_t* total,
787 int histogram[kMallocHistogramSize]) {
788 memset(histogram, 0, kMallocHistogramSize * sizeof(int));
789 alloc_map_lock_.Lock();
790 stats_blocks_ = 0;
791 stats_total_ = 0;
792 stats_histogram_ = histogram;
793 if (alloc_map_ != NULL) alloc_map_->Iterate(StatsCallback, 0);
794 *blocks = stats_blocks_;
795 *total = stats_total_;
796 alloc_map_lock_.Unlock();
797 return true;
798 }
799
800 private: // helpers for CheckEverything and MemoryStats
801
802 static void CheckCallback(const void* ptr, int* type, int dummy) {
803 if ((*type & kDeallocatedTypeBit) == 0) {
804 FromRawPointer(ptr)->CheckLocked(*type);
805 }
806 }
807
808 // Accumulation variables for StatsCallback protected by alloc_map_lock_
809 static int stats_blocks_;
810 static size_t stats_total_;
811 static int* stats_histogram_;
812
813 static void StatsCallback(const void* ptr, int* type, int dummy) {
814 if ((*type & kDeallocatedTypeBit) == 0) {
815 const MallocBlock* b = FromRawPointer(ptr);
816 b->CheckLocked(*type);
817 ++stats_blocks_;
818 size_t mysize = b->size1_;
819 int entry = 0;
820 stats_total_ += mysize;
821 while (mysize) {
822 ++entry;
823 mysize >>= 1;
824 }
825 RAW_CHECK(entry < kMallocHistogramSize,
826 "kMallocHistogramSize should be at least as large as log2 "
827 "of the maximum process memory size");
828 stats_histogram_[entry] += 1;
829 }
830 }
831};
832
833void DanglingWriteChecker() {
834 // Clear out the remaining free queue to check for dangling writes.
835 MallocBlock::ProcessFreeQueue(NULL, 0, 0);
836}
837
838// ========================================================================= //
839
840const int MallocBlock::kMagicMalloc;
841const int MallocBlock::kMagicMMap;
842
843MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
844SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
845
846FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL;
847size_t MallocBlock::free_queue_size_ = 0;
848SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED);
849
850unsigned char MallocBlock::kMagicDeletedBuffer[1024];
851pthread_once_t MallocBlock::deleted_buffer_initialized_ = PTHREAD_ONCE_INIT;
852bool MallocBlock::deleted_buffer_initialized_no_pthreads_ = false;
853
854const char* const MallocBlock::kAllocName[] = {
855 "malloc",
856 "new",
857 "new []",
858 NULL,
859};
860
861const char* const MallocBlock::kDeallocName[] = {
862 "free",
863 "delete",
864 "delete []",
865 NULL,
866};
867
868int MallocBlock::stats_blocks_;
869size_t MallocBlock::stats_total_;
870int* MallocBlock::stats_histogram_;
871
872// ========================================================================= //
873
874// The following cut-down version of printf() avoids
875// using stdio or ostreams.
876// This is to guarantee no recursive calls into
877// the allocator and to bound the stack space consumed. (The pthread
878// manager thread in linuxthreads has a very small stack,
879// so fprintf can't be called.)
880static void TracePrintf(int fd, const char *fmt, ...) {
881 char buf[64];
882 int i = 0;
883 va_list ap;
884 va_start(ap, fmt);
885 const char *p = fmt;
886 char numbuf[25];
887 if (fd < 0) {
888 return;
889 }
890 numbuf[sizeof(numbuf)-1] = 0;
891 while (*p != '\0') { // until end of format string
892 char *s = &numbuf[sizeof(numbuf)-1];
893 if (p[0] == '%' && p[1] != 0) { // handle % formats
894 int64 l = 0;
895 unsigned long base = 0;
896 if (*++p == 's') { // %s
897 s = va_arg(ap, char *);
898 } else if (*p == 'l' && p[1] == 'd') { // %ld
899 l = va_arg(ap, long);
900 base = 10;
901 p++;
902 } else if (*p == 'l' && p[1] == 'u') { // %lu
903 l = va_arg(ap, unsigned long);
904 base = 10;
905 p++;
906 } else if (*p == 'z' && p[1] == 'u') { // %zu
907 l = va_arg(ap, size_t);
908 base = 10;
909 p++;
910 } else if (*p == 'u') { // %u
911 l = va_arg(ap, unsigned int);
912 base = 10;
913 } else if (*p == 'd') { // %d
914 l = va_arg(ap, int);
915 base = 10;
916 } else if (*p == 'p') { // %p
917 l = va_arg(ap, intptr_t);
918 base = 16;
919 } else {
920 write(STDERR_FILENO, "Unimplemented TracePrintf format\n", 33);
921 write(STDERR_FILENO, p, 2);
922 write(STDERR_FILENO, "\n", 1);
923 abort();
924 }
925 p++;
926 if (base != 0) {
927 bool minus = (l < 0 && base == 10);
928 uint64 ul = minus? -l : l;
929 do {
930 *--s = "0123456789abcdef"[ul % base];
931 ul /= base;
932 } while (ul != 0);
933 if (base == 16) {
934 *--s = 'x';
935 *--s = '0';
936 } else if (minus) {
937 *--s = '-';
938 }
939 }
940 } else { // handle normal characters
941 *--s = *p++;
942 }
943 while (*s != 0) {
944 if (i == sizeof(buf)) {
945 write(fd, buf, i);
946 i = 0;
947 }
948 buf[i++] = *s++;
949 }
950 }
951 if (i != 0) {
952 write(fd, buf, i);
953 }
954 va_end(ap);
955}
956
957// Return the file descriptor we're writing a log to
958static int TraceFd() {
959 static int trace_fd = -1;
960 if (trace_fd == -1) { // Open the trace file on the first call
961 const char *val = getenv("TCMALLOC_TRACE_FILE");
962 bool fallback_to_stderr = false;
963 if (!val) {
964 val = "/tmp/google.alloc";
965 fallback_to_stderr = true;
966 }
967 trace_fd = open(val, O_CREAT|O_TRUNC|O_WRONLY, 0666);
968 if (trace_fd == -1) {
969 if (fallback_to_stderr) {
970 trace_fd = 2;
971 TracePrintf(trace_fd, "Can't open %s. Logging to stderr.\n", val);
972 } else {
973 TracePrintf(2, "Can't open %s. Logging disabled.\n", val);
974 }
975 }
976 // Add a header to the log.
977 TracePrintf(trace_fd, "Trace started: %lu\n",
978 static_cast<unsigned long>(time(NULL)));
979 TracePrintf(trace_fd,
980 "func\tsize\tptr\tthread_id\tstack pcs for tools/symbolize\n");
981 }
982 return trace_fd;
983}
984
985// Print the hex stack dump on a single line. PCs are separated by tabs.
986static void TraceStack(void) {
987 void *pcs[16];
988 int n = GetStackTrace(pcs, sizeof(pcs)/sizeof(pcs[0]), 0);
989 for (int i = 0; i != n; i++) {
990 TracePrintf(TraceFd(), "\t%p", pcs[i]);
991 }
992}
993
994// This protects MALLOC_TRACE, to make sure its info is atomically written.
995static SpinLock malloc_trace_lock(SpinLock::LINKER_INITIALIZED);
996
997#define MALLOC_TRACE(name, size, addr) \
998 do { \
999 if (FLAGS_malloctrace) { \
1000 SpinLockHolder l(&malloc_trace_lock); \
1001 TracePrintf(TraceFd(), "%s\t%" PRIuS "\t%p\t%" GPRIuPTHREAD, \
1002 name, size, addr, PRINTABLE_PTHREAD(pthread_self())); \
1003 TraceStack(); \
1004 TracePrintf(TraceFd(), "\n"); \
1005 } \
1006 } while (0)
1007
1008// ========================================================================= //
1009
1010// Write the characters buf[0, ..., size-1] to
1011// the malloc trace buffer.
1012// This function is intended for debugging,
1013// and is not declared in any header file.
1014// You must insert a declaration of it by hand when you need
1015// to use it.
1016void __malloctrace_write(const char *buf, size_t size) {
1017 if (FLAGS_malloctrace) {
1018 write(TraceFd(), buf, size);
1019 }
1020}
1021
1022// ========================================================================= //
1023
1024// General debug allocation/deallocation
1025
1026static inline void* DebugAllocate(size_t size, int type) {
1027 MallocBlock* ptr = MallocBlock::Allocate(size, type);
1028 if (ptr == NULL) return NULL;
1029 MALLOC_TRACE("malloc", size, ptr->data_addr());
1030 return ptr->data_addr();
1031}
1032
1033static inline void DebugDeallocate(void* ptr, int type) {
1034 MALLOC_TRACE("free",
1035 (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
1036 ptr);
1037 if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type);
1038}
1039
1040// ========================================================================= //
1041
1042// The following functions may be called via MallocExtension::instance()
1043// for memory verification and statistics.
1044class DebugMallocImplementation : public TCMallocImplementation {
1045 public:
1046 virtual bool GetNumericProperty(const char* name, size_t* value) {
1047 bool result = TCMallocImplementation::GetNumericProperty(name, value);
1048 if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
1049 // Subtract bytes kept in the free queue
1050 size_t qsize = MallocBlock::FreeQueueSize();
1051 if (*value >= qsize) {
1052 *value -= qsize;
1053 }
1054 }
1055 return result;
1056 }
1057
1058 virtual bool VerifyNewMemory(const void* p) {
1059 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
1060 return true;
1061 }
1062
1063 virtual bool VerifyArrayNewMemory(const void* p) {
1064 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
1065 return true;
1066 }
1067
1068 virtual bool VerifyMallocMemory(const void* p) {
1069 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
1070 return true;
1071 }
1072
1073 virtual bool VerifyAllMemory() {
1074 return MallocBlock::CheckEverything();
1075 }
1076
1077 virtual bool MallocMemoryStats(int* blocks, size_t* total,
1078 int histogram[kMallocHistogramSize]) {
1079 return MallocBlock::MemoryStats(blocks, total, histogram);
1080 }
1081
1082 virtual size_t GetEstimatedAllocatedSize(size_t size) {
1083 return size;
1084 }
1085
1086 virtual size_t GetAllocatedSize(const void* p) {
1087 if (p) {
1088 RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned,
1089 "ptr not allocated by tcmalloc");
1090 return MallocBlock::FromRawPointer(p)->data_size();
1091 }
1092 return 0;
1093 }
1094
1095 virtual MallocExtension::Ownership GetOwnership(const void* p) {
1096 if (!p) {
1097 // nobody owns NULL
1098 return MallocExtension::kNotOwned;
1099 }
1100
1101 // FIXME: note that correct GetOwnership should not touch memory
1102 // that is not owned by tcmalloc. Main implementation is using
1103 // pagemap to discover if page in question is owned by us or
1104 // not. But pagemap only has marks for first and last page of
1105 // spans. Note that if p was returned out of our memalign with
1106 // big alignment, then it will point outside of marked pages. Also
1107 // note that FromRawPointer call below requires touching memory
1108 // before pointer in order to handle memalign-ed chunks
1109 // (offset_). This leaves us with two options:
1110 //
1111 // * do FromRawPointer first and have possibility of crashing if
1112 // we're given not owned pointer
1113 //
1114 // * return incorrect ownership for those large memalign chunks
1115 //
1116 // I've decided to choose later, which appears to happen rarer and
1117 // therefore is arguably a lesser evil
1118
1119 MallocExtension::Ownership rv = TCMallocImplementation::GetOwnership(p);
1120 if (rv != MallocExtension::kOwned) {
1121 return rv;
1122 }
1123
1124 const MallocBlock* mb = MallocBlock::FromRawPointer(p);
1125 return TCMallocImplementation::GetOwnership(mb);
1126 }
1127
1128 virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
1129 static const char* kDebugFreeQueue = "debug.free_queue";
1130
1131 TCMallocImplementation::GetFreeListSizes(v);
1132
1133 MallocExtension::FreeListInfo i;
1134 i.type = kDebugFreeQueue;
1135 i.min_object_size = 0;
1136 i.max_object_size = numeric_limits<size_t>::max();
1137 i.total_bytes_free = MallocBlock::FreeQueueSize();
1138 v->push_back(i);
1139 }
1140
1141 };
1142
1143static union {
1144 char chars[sizeof(DebugMallocImplementation)];
1145 void *ptr;
1146} debug_malloc_implementation_space;
1147
1148REGISTER_MODULE_INITIALIZER(debugallocation, {
1149#if (__cplusplus >= 201103L)
1150 COMPILE_ASSERT(alignof(debug_malloc_implementation_space) >= alignof(DebugMallocImplementation),
1151 debug_malloc_implementation_space_is_not_properly_aligned);
1152#endif
1153 // Either we or valgrind will control memory management. We
1154 // register our extension if we're the winner. Otherwise let
1155 // Valgrind use its own malloc (so don't register our extension).
1156 if (!RunningOnValgrind()) {
1157 DebugMallocImplementation *impl = new (debug_malloc_implementation_space.chars) DebugMallocImplementation();
1158 MallocExtension::Register(impl);
1159 }
1160});
1161
1162REGISTER_MODULE_DESTRUCTOR(debugallocation, {
1163 if (!RunningOnValgrind()) {
1164 // When the program exits, check all blocks still in the free
1165 // queue for corruption.
1166 DanglingWriteChecker();
1167 }
1168});
1169
1170// ========================================================================= //
1171
1172struct debug_alloc_retry_data {
1173 size_t size;
1174 int new_type;
1175};
1176
1177static void *retry_debug_allocate(void *arg) {
1178 debug_alloc_retry_data *data = static_cast<debug_alloc_retry_data *>(arg);
1179 return DebugAllocate(data->size, data->new_type);
1180}
1181
1182// This is mostly the same a cpp_alloc in tcmalloc.cc.
1183// TODO(csilvers): change Allocate() above to call cpp_alloc, so we
1184// don't have to reproduce the logic here. To make tc_new_mode work
1185// properly, I think we'll need to separate out the logic of throwing
1186// from the logic of calling the new-handler.
1187inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) {
1188 void* p = DebugAllocate(size, new_type);
1189 if (p != NULL) {
1190 return p;
1191 }
1192 struct debug_alloc_retry_data data;
1193 data.size = size;
1194 data.new_type = new_type;
1195 return handle_oom(retry_debug_allocate, &data,
1196 true, nothrow);
1197}
1198
1199inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
1200 void* p = DebugAllocate(size, MallocBlock::kMallocType);
1201 if (p != NULL) {
1202 return p;
1203 }
1204 struct debug_alloc_retry_data data;
1205 data.size = size;
1206 data.new_type = MallocBlock::kMallocType;
1207 return handle_oom(retry_debug_allocate, &data,
1208 false, true);
1209}
1210
1211// Exported routines
1212
1213extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
1214 void* ptr = do_debug_malloc_or_debug_cpp_alloc(size);
1215 MallocHook::InvokeNewHook(ptr, size);
1216 return ptr;
1217}
1218
1219extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
1220 MallocHook::InvokeDeleteHook(ptr);
1221 DebugDeallocate(ptr, MallocBlock::kMallocType);
1222}
1223
1224extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) __THROW {
1225 // Overflow check
1226 const size_t total_size = count * size;
1227 if (size != 0 && total_size / size != count) return NULL;
1228
1229 void* block = do_debug_malloc_or_debug_cpp_alloc(total_size);
1230 MallocHook::InvokeNewHook(block, total_size);
1231 if (block) memset(block, 0, total_size);
1232 return block;
1233}
1234
1235extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW {
1236 MallocHook::InvokeDeleteHook(ptr);
1237 DebugDeallocate(ptr, MallocBlock::kMallocType);
1238}
1239
1240extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW {
1241 if (ptr == NULL) {
1242 ptr = do_debug_malloc_or_debug_cpp_alloc(size);
1243 MallocHook::InvokeNewHook(ptr, size);
1244 return ptr;
1245 }
1246 if (size == 0) {
1247 MallocHook::InvokeDeleteHook(ptr);
1248 DebugDeallocate(ptr, MallocBlock::kMallocType);
1249 return NULL;
1250 }
1251 MallocBlock* old = MallocBlock::FromRawPointer(ptr);
1252 old->Check(MallocBlock::kMallocType);
1253 MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType);
1254
1255 // If realloc fails we are to leave the old block untouched and
1256 // return null
1257 if (p == NULL) return NULL;
1258
1259 // if ptr was allocated via memalign, then old->data_size() is not
1260 // start of user data. So we must be careful to copy only user-data
1261 char *old_begin = (char *)old->data_addr();
1262 char *old_end = old_begin + old->data_size();
1263
1264 ssize_t old_ssize = old_end - (char *)ptr;
1265 CHECK_CONDITION(old_ssize >= 0);
1266
1267 size_t old_size = (size_t)old_ssize;
1268 CHECK_CONDITION(old_size <= old->data_size());
1269
1270 memcpy(p->data_addr(), ptr, (old_size < size) ? old_size : size);
1271 MallocHook::InvokeDeleteHook(ptr);
1272 MallocHook::InvokeNewHook(p->data_addr(), size);
1273 DebugDeallocate(ptr, MallocBlock::kMallocType);
1274 MALLOC_TRACE("realloc", p->data_size(), p->data_addr());
1275 return p->data_addr();
1276}
1277
1278extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
1279 void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, false);
1280 MallocHook::InvokeNewHook(ptr, size);
1281 if (ptr == NULL) {
1282 RAW_LOG(FATAL, "Unable to allocate %" PRIuS " bytes: new failed.", size);
1283 }
1284 return ptr;
1285}
1286
1287extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
1288 void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, true);
1289 MallocHook::InvokeNewHook(ptr, size);
1290 return ptr;
1291}
1292
1293extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
1294 MallocHook::InvokeDeleteHook(p);
1295 DebugDeallocate(p, MallocBlock::kNewType);
1296}
1297
1298// Some STL implementations explicitly invoke this.
1299// It is completely equivalent to a normal delete (delete never throws).
1300extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) __THROW {
1301 MallocHook::InvokeDeleteHook(p);
1302 DebugDeallocate(p, MallocBlock::kNewType);
1303}
1304
1305extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
1306 void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, false);
1307 MallocHook::InvokeNewHook(ptr, size);
1308 if (ptr == NULL) {
1309 RAW_LOG(FATAL, "Unable to allocate %" PRIuS " bytes: new[] failed.", size);
1310 }
1311 return ptr;
1312}
1313
1314extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
1315 __THROW {
1316 void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, true);
1317 MallocHook::InvokeNewHook(ptr, size);
1318 return ptr;
1319}
1320
1321extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
1322 MallocHook::InvokeDeleteHook(p);
1323 DebugDeallocate(p, MallocBlock::kArrayNewType);
1324}
1325
1326// Some STL implementations explicitly invoke this.
1327// It is completely equivalent to a normal delete (delete never throws).
1328extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) __THROW {
1329 MallocHook::InvokeDeleteHook(p);
1330 DebugDeallocate(p, MallocBlock::kArrayNewType);
1331}
1332
1333// This is mostly the same as do_memalign in tcmalloc.cc.
1334static void *do_debug_memalign(size_t alignment, size_t size) {
1335 // Allocate >= size bytes aligned on "alignment" boundary
1336 // "alignment" is a power of two.
1337 void *p = 0;
1338 RAW_CHECK((alignment & (alignment-1)) == 0, "must be power of two");
1339 const size_t data_offset = MallocBlock::data_offset();
1340 // Allocate "alignment-1" extra bytes to ensure alignment is possible, and
1341 // a further data_offset bytes for an additional fake header.
1342 size_t extra_bytes = data_offset + alignment - 1;
1343 if (size + extra_bytes < size) return NULL; // Overflow
1344 p = DebugAllocate(size + extra_bytes, MallocBlock::kMallocType);
1345 if (p != 0) {
1346 intptr_t orig_p = reinterpret_cast<intptr_t>(p);
1347 // Leave data_offset bytes for fake header, and round up to meet
1348 // alignment.
1349 p = reinterpret_cast<void *>(RoundUp(orig_p + data_offset, alignment));
1350 // Create a fake header block with an offset_ that points back to the
1351 // real header. FromRawPointer uses this value.
1352 MallocBlock *fake_hdr = reinterpret_cast<MallocBlock *>(
1353 reinterpret_cast<char *>(p) - data_offset);
1354 // offset_ is distance between real and fake headers.
1355 // p is now end of fake header (beginning of client area),
1356 // and orig_p is the end of the real header, so offset_
1357 // is their difference.
1358 //
1359 // Note that other fields of fake_hdr are initialized with
1360 // kMagicUninitializedByte
1361 fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
1362 }
1363 return p;
1364}
1365
1366struct memalign_retry_data {
1367 size_t align;
1368 size_t size;
1369};
1370
1371static void *retry_debug_memalign(void *arg) {
1372 memalign_retry_data *data = static_cast<memalign_retry_data *>(arg);
1373 return do_debug_memalign(data->align, data->size);
1374}
1375
1376inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
1377 size_t size) {
1378 void* p = do_debug_memalign(align, size);
1379 if (p != NULL) {
1380 return p;
1381 }
1382
1383 struct memalign_retry_data data;
1384 data.align = align;
1385 data.size = size;
1386 return handle_oom(retry_debug_memalign, &data,
1387 false, true);
1388}
1389
1390extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) __THROW {
1391 void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
1392 MallocHook::InvokeNewHook(p, size);
1393 return p;
1394}
1395
1396// Implementation taken from tcmalloc/tcmalloc.cc
1397extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
1398 __THROW {
1399 if (((align % sizeof(void*)) != 0) ||
1400 ((align & (align - 1)) != 0) ||
1401 (align == 0)) {
1402 return EINVAL;
1403 }
1404
1405 void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
1406 MallocHook::InvokeNewHook(result, size);
1407 if (result == NULL) {
1408 return ENOMEM;
1409 } else {
1410 *result_ptr = result;
1411 return 0;
1412 }
1413}
1414
1415extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
1416 // Allocate >= size bytes starting on a page boundary
1417 void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
1418 MallocHook::InvokeNewHook(p, size);
1419 return p;
1420}
1421
1422extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
1423 // Round size up to a multiple of pages
1424 // then allocate memory on a page boundary
1425 int pagesize = getpagesize();
1426 size = RoundUp(size, pagesize);
1427 if (size == 0) { // pvalloc(0) should allocate one page, according to
1428 size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
1429 }
1430 void *p = do_debug_memalign_or_debug_cpp_memalign(pagesize, size);
1431 MallocHook::InvokeNewHook(p, size);
1432 return p;
1433}
1434
1435// malloc_stats just falls through to the base implementation.
1436extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
1437 do_malloc_stats();
1438}
1439
1440extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
1441 return do_mallopt(cmd, value);
1442}
1443
1444#ifdef HAVE_STRUCT_MALLINFO
1445extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
1446 return do_mallinfo();
1447}
1448#endif
1449
1450extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
1451 return MallocExtension::instance()->GetAllocatedSize(ptr);
1452}
1453
1454extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) __THROW {
1455 void* result = DebugAllocate(size, MallocBlock::kMallocType);
1456 MallocHook::InvokeNewHook(result, size);
1457 return result;
1458}