1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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 7 * are met: 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 copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <pthread.h> 30 #include <stdint.h> 31 #include <stdlib.h> 32 33 #include <algorithm> 34 #include <vector> 35 36 #include <private/ScopedPthreadMutexLocker.h> 37 38 #include "backtrace.h" 39 #include "BacktraceData.h" 40 #include "Config.h" 41 #include "DebugData.h" 42 #include "debug_disable.h" 43 #include "debug_log.h" 44 #include "malloc_debug.h" 45 #include "TrackData.h" 46 47 TrackData::TrackData(DebugData* debug_data) : OptionData(debug_data) { 48 } 49 50 void TrackData::GetList(std::vector<const Header*>* list) { 51 for (const auto& header : headers_) { 52 list->push_back(header); 53 } 54 55 // Sort by the size of the allocation. 56 std::sort(list->begin(), list->end(), [](const Header* a, const Header* b) { 57 if (a->size == b->size) return a < b; 58 return a->size > b->size; 59 }); 60 } 61 62 void TrackData::Add(const Header* header, bool backtrace_found) { 63 pthread_mutex_lock(&mutex_); 64 if (backtrace_found) { 65 total_backtrace_allocs_++; 66 } 67 headers_.insert(header); 68 pthread_mutex_unlock(&mutex_); 69 } 70 71 void TrackData::Remove(const Header* header, bool backtrace_found) { 72 pthread_mutex_lock(&mutex_); 73 headers_.erase(header); 74 if (backtrace_found) { 75 total_backtrace_allocs_--; 76 } 77 pthread_mutex_unlock(&mutex_); 78 } 79 80 bool TrackData::Contains(const Header* header) { 81 pthread_mutex_lock(&mutex_); 82 bool found = headers_.count(header); 83 pthread_mutex_unlock(&mutex_); 84 return found; 85 } 86 87 void TrackData::DisplayLeaks() { 88 std::vector<const Header*> list; 89 GetList(&list); 90 91 size_t track_count = 0; 92 for (const auto& header : list) { 93 error_log("+++ %s leaked block of size %zu at %p (leak %zu of %zu)", getprogname(), 94 header->real_size(), debug_->GetPointer(header), ++track_count, list.size()); 95 if (debug_->config().options & BACKTRACE) { 96 BacktraceHeader* back_header = debug_->GetAllocBacktrace(header); 97 if (back_header->num_frames > 0) { 98 error_log("Backtrace at time of allocation:"); 99 backtrace_log(&back_header->frames[0], back_header->num_frames); 100 } 101 } 102 g_dispatch->free(header->orig_pointer); 103 } 104 } 105 106 void TrackData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, 107 size_t* total_memory, size_t* backtrace_size) { 108 ScopedPthreadMutexLocker scoped(&mutex_); 109 110 if (headers_.size() == 0 || total_backtrace_allocs_ == 0) { 111 return; 112 } 113 114 *backtrace_size = debug_->config().backtrace_frames; 115 *info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size; 116 *info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, total_backtrace_allocs_)); 117 if (*info == nullptr) { 118 return; 119 } 120 *overall_size = *info_size * total_backtrace_allocs_; 121 122 std::vector<const Header*> list; 123 GetList(&list); 124 125 uint8_t* data = *info; 126 size_t num_allocations = 1; 127 for (const auto& header : list) { 128 BacktraceHeader* back_header = debug_->GetAllocBacktrace(header); 129 if (back_header->num_frames > 0) { 130 memcpy(data, &header->size, sizeof(size_t)); 131 memcpy(&data[sizeof(size_t)], &num_allocations, sizeof(size_t)); 132 memcpy(&data[2 * sizeof(size_t)], &back_header->frames[0], 133 back_header->num_frames * sizeof(uintptr_t)); 134 135 *total_memory += header->real_size(); 136 137 data += *info_size; 138 } 139 } 140 } 141