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