18b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris/* 28b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * Copyright (C) 2015 The Android Open Source Project 38b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * All rights reserved. 48b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * 58b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * Redistribution and use in source and binary forms, with or without 68b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * modification, are permitted provided that the following conditions 78b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * are met: 88b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * * Redistributions of source code must retain the above copyright 98b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * notice, this list of conditions and the following disclaimer. 108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * * Redistributions in binary form must reproduce the above copyright 118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * notice, this list of conditions and the following disclaimer in 128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * the documentation and/or other materials provided with the 138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * distribution. 148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * 158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris * SUCH DAMAGE. 278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris */ 288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <errno.h> 308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <inttypes.h> 318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <signal.h> 328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <stdint.h> 338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <stdlib.h> 348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <string.h> 358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <sys/types.h> 368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <unistd.h> 378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <mutex> 398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <string> 408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <unordered_map> 418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <utility> 428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <vector> 438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <android-base/stringprintf.h> 458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <android-base/thread_annotations.h> 468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include <private/bionic_macros.h> 478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "Config.h" 498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "DebugData.h" 508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "PointerData.h" 518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "backtrace.h" 528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "debug_log.h" 538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "malloc_debug.h" 548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::atomic_uint8_t PointerData::backtrace_enabled_; 568b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::atomic_bool PointerData::backtrace_dump_; 578b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 588b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::mutex PointerData::pointer_mutex_; 598b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::unordered_map<uintptr_t, PointerInfoType> PointerData::pointers_ GUARDED_BY( 608b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris PointerData::pointer_mutex_); 618b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 628b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::mutex PointerData::frame_mutex_; 638b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY( 648b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris PointerData::frame_mutex_); 658b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_); 668b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisconstexpr size_t kBacktraceEmptyIndex = 1; 678b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrissize_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_); 688b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 698b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::mutex PointerData::free_pointer_mutex_; 708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstd::deque<FreePointerInfoType> PointerData::free_pointers_ GUARDED_BY( 718b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris PointerData::free_pointer_mutex_); 728b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 738b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris// Buffer to use for comparison. 748b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstatic constexpr size_t kCompareBufferSize = 512 * 1024; 758b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstatic std::vector<uint8_t> g_cmp_mem(0); 768b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstatic void ToggleBacktraceEnable(int, siginfo_t*, void*) { 788b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris g_debug->pointer->ToggleBacktraceEnabled(); 798b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 818b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisstatic void EnableDump(int, siginfo_t*, void*) { 828b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris g_debug->pointer->EnableDumping(); 838b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 848b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 858b70a0266d42297e9b38e6209588eb3621843e95Christopher FerrisPointerData::PointerData(DebugData* debug_data) : OptionData(debug_data) {} 868b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 878b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisbool PointerData::Initialize(const Config& config) NO_THREAD_SAFETY_ANALYSIS { 888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointers_.clear(); 898b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris key_to_index_.clear(); 908b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frames_.clear(); 918b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointers_.clear(); 928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // A hash index of kBacktraceEmptyIndex indicates that we tried to get 938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // a backtrace, but there was nothing recorded. 948b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris cur_hash_index_ = kBacktraceEmptyIndex + 1; 958b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 968b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris backtrace_enabled_ = config.backtrace_enabled(); 978b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (config.backtrace_enable_on_signal()) { 988b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris struct sigaction64 enable_act = {}; 998b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris enable_act.sa_sigaction = ToggleBacktraceEnable; 1008b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 1018b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (sigaction64(config.backtrace_signal(), &enable_act, nullptr) != 0) { 1028b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Unable to set up backtrace signal enable function: %s", strerror(errno)); 1038b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return false; 1048b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1058b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris info_log("%s: Run: 'kill -%d %d' to enable backtracing.", getprogname(), 1068b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris config.backtrace_signal(), getpid()); 1078b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1088b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1098b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (config.options() & BACKTRACE) { 1108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris struct sigaction64 act = {}; 1118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris act.sa_sigaction = EnableDump; 1128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 1138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (sigaction64(config.backtrace_dump_signal(), &act, nullptr) != 0) { 1148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Unable to set up backtrace dump signal function: %s", strerror(errno)); 1158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return false; 1168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris info_log("%s: Run: 'kill -%d %d' to dump the backtrace.", getprogname(), 1188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris config.backtrace_dump_signal(), getpid()); 1198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris backtrace_dump_ = false; 1228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (config.options() & FREE_TRACK) { 1248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris g_cmp_mem.resize(kCompareBufferSize, config.fill_free_value()); 1258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return true; 1278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 1288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrissize_t PointerData::AddBacktrace(size_t num_frames) { 1308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::vector<uintptr_t> frames(num_frames); 1318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris num_frames = backtrace_get(frames.data(), frames.size()); 1328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (num_frames == 0) { 1338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return kBacktraceEmptyIndex; 1348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameKeyType key{.num_frames = num_frames, .frames = frames.data()}; 1378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index; 1388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 1398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto entry = key_to_index_.find(key); 1408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (entry == key_to_index_.end()) { 1418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frames.resize(num_frames); 1428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = cur_hash_index_++; 1438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris key.frames = frames.data(); 1448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris key_to_index_.emplace(key, hash_index); 1458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frames_.emplace(hash_index, FrameInfoType{.references = 1, .frames = std::move(frames)}); 1478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } else { 1488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = entry->second; 1498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = &frames_[hash_index]; 1508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_info->references++; 1518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return hash_index; 1538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 1548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::RemoveBacktrace(size_t hash_index) { 1568b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (hash_index <= kBacktraceEmptyIndex) { 1578b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 1588b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1598b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1608b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 1618b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto frame_entry = frames_.find(hash_index); 1628b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_entry == frames_.end()) { 1638b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("hash_index %zu does not have matching frame data.", hash_index); 1648b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 1658b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1668b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = &frame_entry->second; 1678b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (--frame_info->references == 0) { 1688b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameKeyType key{.num_frames = frame_info->frames.size(), .frames = frame_info->frames.data()}; 1698b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris key_to_index_.erase(key); 1708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frames_.erase(hash_index); 1718b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1728b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 1738b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1748b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::Add(const void* ptr, size_t pointer_size) { 1758b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 1768b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index = 0; 1778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (backtrace_enabled_) { 1788b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = AddBacktrace(g_debug->config().backtrace_frames()); 1798b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1818b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 1828b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointers_[pointer] = PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index}; 1838b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 1848b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 1858b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::Remove(const void* ptr) { 1868b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 1878b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index; 1888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris { 1898b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 1908b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto entry = pointers_.find(pointer); 1918b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (entry == pointers_.end()) { 1928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Error. 1938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("No tracked pointer found for 0x%" PRIxPTR, pointer); 1948b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 1958b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1968b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = entry->second.hash_index; 1978b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointers_.erase(pointer); 1988b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 1998b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2008b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris RemoveBacktrace(hash_index); 2018b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 2028b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2038b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrissize_t PointerData::GetFrames(const void* ptr, uintptr_t* frames, size_t max_frames) { 2048b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 2058b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index; 2068b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris { 2078b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 2088b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto entry = pointers_.find(pointer); 2098b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (entry == pointers_.end()) { 2108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return 0; 2118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = entry->second.hash_index; 2138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (hash_index <= kBacktraceEmptyIndex) { 2168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return 0; 2178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 2208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto frame_entry = frames_.find(hash_index); 2218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_entry == frames_.end()) { 2228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return 0; 2238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = &frame_entry->second; 2258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (max_frames > frame_info->frames.size()) { 2268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris max_frames = frame_info->frames.size(); 2278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris memcpy(frames, &frame_info->frames[0], max_frames * sizeof(uintptr_t)); 2298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return max_frames; 2318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 2328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::LogFreeError(const FreePointerInfoType& info, size_t usable_size) { 2348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log(LOG_DIVIDER); 2358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer); 2368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("+++ ALLOCATION %p USED AFTER FREE", memory); 2378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uint8_t fill_free_value = g_debug->config().fill_free_value(); 2388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (size_t i = 0; i < usable_size; i++) { 2398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (memory[i] != fill_free_value) { 2408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log(" allocation[%zu] = 0x%02x (expected 0x%02x)", i, memory[i], fill_free_value); 2418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (info.hash_index > kBacktraceEmptyIndex) { 2458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 2468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto frame_entry = frames_.find(info.hash_index); 2478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_entry != frames_.end()) { 2488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = &frame_entry->second; 2498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Backtrace at time of free:"); 2508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris backtrace_log(frame_info->frames.data(), frame_info->frames.size()); 2518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log(LOG_DIVIDER); 2558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 2568b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2578b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::VerifyFreedPointer(const FreePointerInfoType& info) { 2588b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t usable_size; 2598b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (g_debug->HeaderEnabled()) { 2608b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Check to see if the tag data has been damaged. 2618b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(info.pointer)); 2628b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (header->tag != DEBUG_FREE_TAG) { 2638b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log(LOG_DIVIDER); 2648b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", 2658b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris info.pointer, header->tag); 2668b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log(LOG_DIVIDER); 2678b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2688b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Stop processing here, it is impossible to tell how the header 2698b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // may have been damaged. 2708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 2718b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2728b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris usable_size = header->usable_size; 2738b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } else { 2748b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(info.pointer)); 2758b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2768b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes()) 2788b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris ? usable_size 2798b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris : g_debug->config().fill_on_free_bytes(); 2808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris const uint8_t* memory = reinterpret_cast<const uint8_t*>(info.pointer); 2818b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris while (bytes > 0) { 2828b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size(); 2838b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) { 2848b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris LogFreeError(info, usable_size); 2858b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2868b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris bytes -= bytes_to_cmp; 2878b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris memory = &memory[bytes_to_cmp]; 2888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2898b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 2908b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2918b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid* PointerData::AddFreed(const void* ptr) { 2928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 2938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 2948b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index = 0; 2958b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t num_frames = g_debug->config().free_track_backtrace_num_frames(); 2968b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (num_frames) { 2978b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = AddBacktrace(num_frames); 2988b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 2998b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3008b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris void* last = nullptr; 3018b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_); 3028b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (free_pointers_.size() == g_debug->config().free_track_allocations()) { 3038b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FreePointerInfoType info(free_pointers_.front()); 3048b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointers_.pop_front(); 3058b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris VerifyFreedPointer(info); 3068b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris RemoveBacktrace(info.hash_index); 3078b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris last = reinterpret_cast<void*>(info.pointer); 3088b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3098b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointers_.emplace_back(FreePointerInfoType{pointer, hash_index}); 3118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return last; 3128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 3138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::LogFreeBacktrace(const void* ptr) { 3158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index = 0; 3168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris { 3178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 3188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_); 3198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& info : free_pointers_) { 3208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (info.pointer == pointer) { 3218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris hash_index = info.hash_index; 3228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris break; 3238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (hash_index <= kBacktraceEmptyIndex) { 3288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 3298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 3328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto frame_entry = frames_.find(hash_index); 3338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_entry == frames_.end()) { 3348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Freed pointer hash_index %zu does not have matching frame data.", hash_index); 3358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 3368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = &frame_entry->second; 3388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Backtrace of original free:"); 3398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris backtrace_log(frame_info->frames.data(), frame_info->frames.size()); 3408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 3418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::VerifyAllFreed() { 3438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_); 3448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (auto& free_info : free_pointers_) { 3458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris VerifyFreedPointer(free_info); 3468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 3488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::GetList(std::vector<ListInfoType>* list, bool only_with_backtrace) 3508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris REQUIRES(pointer_mutex_, frame_mutex_) { 3518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& entry : pointers_) { 3528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = nullptr; 3538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t hash_index = entry.second.hash_index; 3548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (hash_index > kBacktraceEmptyIndex) { 3558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_info = &frames_[hash_index]; 3568b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_info->references == 0) { 3578b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Somehow wound up with a pointer with a valid hash_index, but 3588b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // no frame data. This should not be possible since adding a pointer 3598b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // occurs after the hash_index and frame data have been added. 3608b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // When removing a pointer, the pointer is deleted before the frame 3618b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // data. 3628b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frames_.erase(hash_index); 3638b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index); 3648b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_info = nullptr; 3658b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3668b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3678b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (hash_index == 0 && only_with_backtrace) { 3688b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris continue; 3698b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3718b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(), 3728b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris entry.second.ZygoteChildAlloc(), frame_info}); 3738b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3748b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3758b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Sort by the size of the allocation. 3768b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::sort(list->begin(), list->end(), [](const ListInfoType& a, const ListInfoType& b) { 3778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Put zygote child allocations first. 3788b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris bool a_zygote_child_alloc = a.zygote_child_alloc; 3798b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris bool b_zygote_child_alloc = b.zygote_child_alloc; 3808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (a_zygote_child_alloc && !b_zygote_child_alloc) { 3818b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return false; 3828b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3838b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (!a_zygote_child_alloc && b_zygote_child_alloc) { 3848b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return true; 3858b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 3868b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3878b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Sort by size, descending order. 3888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (a.size != b.size) return a.size > b.size; 3898b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 3908b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Put pointers with no backtrace last. 3918b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* a_frame = a.frame_info; 3928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* b_frame = b.frame_info; 3938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (a_frame == nullptr && b_frame != nullptr) { 3948b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return false; 395a9001ceb0a5083f9786652918d16cafbdabcf459Christopher Ferris } else if (a_frame != nullptr && b_frame == nullptr) { 3968b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return true; 397a9001ceb0a5083f9786652918d16cafbdabcf459Christopher Ferris } else if (a_frame == nullptr && b_frame == nullptr) { 398a9001ceb0a5083f9786652918d16cafbdabcf459Christopher Ferris return a.pointer < b.pointer; 3998b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 400a9001ceb0a5083f9786652918d16cafbdabcf459Christopher Ferris 4018b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Put the pointers with longest backtrace first. 4028b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (a_frame->frames.size() != b_frame->frames.size()) { 4038b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return a_frame->frames.size() > b_frame->frames.size(); 4048b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4058b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4068b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Last sort by pointer. 4078b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return a.pointer < b.pointer; 4088b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris }); 4098b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 4108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace) 4128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris REQUIRES(pointer_mutex_, frame_mutex_) { 4138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris GetList(list, only_with_backtrace); 4148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Remove duplicates of size/backtraces. 4168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (auto iter = list->begin(); iter != list->end();) { 4178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris auto dup_iter = iter + 1; 4188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris bool zygote_child_alloc = iter->zygote_child_alloc; 4198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t size = iter->size; 4208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = iter->frame_info; 4218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (; dup_iter != list->end(); ++dup_iter) { 4228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (zygote_child_alloc != dup_iter->zygote_child_alloc || size != dup_iter->size || 4238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_info != dup_iter->frame_info) { 4248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris break; 4258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris iter->num_allocations++; 4278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris iter = list->erase(iter + 1, dup_iter); 4298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 4318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::LogLeaks() { 4338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::vector<ListInfoType> list; 4348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 4368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 4378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris GetList(&list, false); 4388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t track_count = 0; 4408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& list_info : list) { 4418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("+++ %s leaked block of size %zu at 0x%" PRIxPTR " (leak %zu of %zu)", getprogname(), 4428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris list_info.size, list_info.pointer, ++track_count, list.size()); 4438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (list_info.frame_info != nullptr) { 4448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris error_log("Backtrace at time of allocation:"); 4458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris backtrace_log(list_info.frame_info->frames.data(), list_info.frame_info->frames.size()); 4468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Do not bother to free the pointers, we are about to exit any way. 4488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 4508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, 4528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t* total_memory, size_t* backtrace_size) { 4538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 4548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 4558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4568b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (pointers_.empty()) { 4578b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 4588b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4598b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4608b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::vector<ListInfoType> list; 4618b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris GetUniqueList(&list, true); 4628b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (list.empty()) { 4638b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 4648b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4658b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4668b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *backtrace_size = g_debug->config().backtrace_frames(); 4678b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size; 4688b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *overall_size = *info_size * list.size(); 4698b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, list.size())); 4708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (*info == nullptr) { 4718b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return; 4728b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4738b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4748b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uint8_t* data = *info; 4758b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *total_memory = 0; 4768b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& list_info : list) { 4778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = list_info.frame_info; 4788b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris *total_memory += list_info.size * list_info.num_allocations; 4798b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t allocation_size = 4808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris PointerInfoType::GetEncodedSize(list_info.zygote_child_alloc, list_info.size); 4818b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris memcpy(data, &allocation_size, sizeof(size_t)); 4828b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris memcpy(&data[sizeof(size_t)], &list_info.num_allocations, sizeof(size_t)); 4838b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_info != nullptr) { 4848b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris memcpy(&data[2 * sizeof(size_t)], frame_info->frames.data(), 4858b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_info->frames.size() * sizeof(uintptr_t)); 4868b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4878b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris data += *info_size; 4888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 4898b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 4908b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4918b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisbool PointerData::Exists(const void* ptr) { 4928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 4938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 4948b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return pointers_.count(pointer) != 0; 4958b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 4968b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 4978b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::DumpLiveToFile(FILE* fp) { 4988b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::vector<ListInfoType> list; 4998b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5008b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 5018b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris std::lock_guard<std::mutex> frame_guard(frame_mutex_); 5028b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris GetUniqueList(&list, false); 5038b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5048b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris size_t total_memory = 0; 5058b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& info : list) { 5068b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris total_memory += info.size * info.num_allocations; 5078b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 5088b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5098b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "Total memory: %zu\n", total_memory); 5108b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "Allocation records: %zd\n", list.size()); 5118b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "Backtrace size: %zu\n", g_debug->config().backtrace_frames()); 5128b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "\n"); 5138b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5148b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (const auto& info : list) { 5158b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "z %d sz %8zu num %zu bt", (info.zygote_child_alloc) ? 1 : 0, info.size, 5168b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris info.num_allocations); 5178b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris FrameInfoType* frame_info = info.frame_info; 5188b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_info != nullptr) { 5198b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris for (size_t i = 0; i < frame_info->frames.size(); i++) { 5208b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris if (frame_info->frames[i] == 0) { 5218b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris break; 5228b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 5238b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#if defined(__LP64__) 5248b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, " %016" PRIxPTR, frame_info->frames[i]); 5258b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#else 5268b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, " %08" PRIxPTR, frame_info->frames[i]); 5278b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#endif 5288b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 5298b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 5308b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris fprintf(fp, "\n"); 5318b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris } 5328b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 5338b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5348b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::PrepareFork() NO_THREAD_SAFETY_ANALYSIS { 5358b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointer_mutex_.lock(); 5368b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_mutex_.lock(); 5378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointer_mutex_.lock(); 5388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 5398b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5408b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::PostForkParent() NO_THREAD_SAFETY_ANALYSIS { 5418b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_mutex_.unlock(); 5428b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointer_mutex_.unlock(); 5438b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointer_mutex_.unlock(); 5448b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 5458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris 5468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferrisvoid PointerData::PostForkChild() __attribute__((no_thread_safety_analysis)) { 5478b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // Make sure that any potential mutexes have been released and are back 5488b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris // to an initial state. 5498b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_mutex_.try_lock(); 5508b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris frame_mutex_.unlock(); 5518b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointer_mutex_.try_lock(); 5528b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris pointer_mutex_.unlock(); 5538b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointer_mutex_.try_lock(); 5548b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris free_pointer_mutex_.unlock(); 5558b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris} 556