xref: /aosp_15_r20/bionic/libc/malloc_debug/PointerData.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker  *
5*8d67ca89SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker  * are met:
8*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker  *    distribution.
14*8d67ca89SAndroid Build Coastguard Worker  *
15*8d67ca89SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker  */
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include <cxxabi.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
31*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <signal.h>
33*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
34*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
36*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
37*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
38*8d67ca89SAndroid Build Coastguard Worker 
39*8d67ca89SAndroid Build Coastguard Worker #include <functional>
40*8d67ca89SAndroid Build Coastguard Worker #include <mutex>
41*8d67ca89SAndroid Build Coastguard Worker #include <string>
42*8d67ca89SAndroid Build Coastguard Worker #include <unordered_map>
43*8d67ca89SAndroid Build Coastguard Worker #include <utility>
44*8d67ca89SAndroid Build Coastguard Worker #include <vector>
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
47*8d67ca89SAndroid Build Coastguard Worker #include <android-base/thread_annotations.h>
48*8d67ca89SAndroid Build Coastguard Worker #include <platform/bionic/macros.h>
49*8d67ca89SAndroid Build Coastguard Worker 
50*8d67ca89SAndroid Build Coastguard Worker #include "Config.h"
51*8d67ca89SAndroid Build Coastguard Worker #include "DebugData.h"
52*8d67ca89SAndroid Build Coastguard Worker #include "PointerData.h"
53*8d67ca89SAndroid Build Coastguard Worker #include "backtrace.h"
54*8d67ca89SAndroid Build Coastguard Worker #include "debug_log.h"
55*8d67ca89SAndroid Build Coastguard Worker #include "malloc_debug.h"
56*8d67ca89SAndroid Build Coastguard Worker #include "UnwindBacktrace.h"
57*8d67ca89SAndroid Build Coastguard Worker 
58*8d67ca89SAndroid Build Coastguard Worker std::atomic_uint8_t PointerData::backtrace_enabled_;
59*8d67ca89SAndroid Build Coastguard Worker std::atomic_bool PointerData::backtrace_dump_;
60*8d67ca89SAndroid Build Coastguard Worker 
61*8d67ca89SAndroid Build Coastguard Worker std::mutex PointerData::pointer_mutex_;
62*8d67ca89SAndroid Build Coastguard Worker std::unordered_map<uintptr_t, PointerInfoType> PointerData::pointers_ GUARDED_BY(
63*8d67ca89SAndroid Build Coastguard Worker     PointerData::pointer_mutex_);
64*8d67ca89SAndroid Build Coastguard Worker 
65*8d67ca89SAndroid Build Coastguard Worker std::mutex PointerData::frame_mutex_;
66*8d67ca89SAndroid Build Coastguard Worker std::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY(
67*8d67ca89SAndroid Build Coastguard Worker     PointerData::frame_mutex_);
68*8d67ca89SAndroid Build Coastguard Worker std::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_);
69*8d67ca89SAndroid Build Coastguard Worker std::unordered_map<size_t, std::vector<unwindstack::FrameData>> PointerData::backtraces_info_
70*8d67ca89SAndroid Build Coastguard Worker     GUARDED_BY(PointerData::frame_mutex_);
71*8d67ca89SAndroid Build Coastguard Worker constexpr size_t kBacktraceEmptyIndex = 1;
72*8d67ca89SAndroid Build Coastguard Worker size_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_);
73*8d67ca89SAndroid Build Coastguard Worker 
74*8d67ca89SAndroid Build Coastguard Worker std::mutex PointerData::free_pointer_mutex_;
75*8d67ca89SAndroid Build Coastguard Worker std::deque<FreePointerInfoType> PointerData::free_pointers_ GUARDED_BY(
76*8d67ca89SAndroid Build Coastguard Worker     PointerData::free_pointer_mutex_);
77*8d67ca89SAndroid Build Coastguard Worker 
78*8d67ca89SAndroid Build Coastguard Worker // Buffer to use for comparison.
79*8d67ca89SAndroid Build Coastguard Worker static constexpr size_t kCompareBufferSize = 512 * 1024;
80*8d67ca89SAndroid Build Coastguard Worker static std::vector<uint8_t> g_cmp_mem(0);
81*8d67ca89SAndroid Build Coastguard Worker 
ToggleBacktraceEnable(int,siginfo_t *,void *)82*8d67ca89SAndroid Build Coastguard Worker static void ToggleBacktraceEnable(int, siginfo_t*, void*) {
83*8d67ca89SAndroid Build Coastguard Worker   g_debug->pointer->ToggleBacktraceEnabled();
84*8d67ca89SAndroid Build Coastguard Worker }
85*8d67ca89SAndroid Build Coastguard Worker 
EnableDump(int,siginfo_t *,void *)86*8d67ca89SAndroid Build Coastguard Worker static void EnableDump(int, siginfo_t*, void*) {
87*8d67ca89SAndroid Build Coastguard Worker   g_debug->pointer->EnableDumping();
88*8d67ca89SAndroid Build Coastguard Worker }
89*8d67ca89SAndroid Build Coastguard Worker 
PointerData(DebugData * debug_data)90*8d67ca89SAndroid Build Coastguard Worker PointerData::PointerData(DebugData* debug_data) : OptionData(debug_data) {}
91*8d67ca89SAndroid Build Coastguard Worker 
Initialize(const Config & config)92*8d67ca89SAndroid Build Coastguard Worker bool PointerData::Initialize(const Config& config) NO_THREAD_SAFETY_ANALYSIS {
93*8d67ca89SAndroid Build Coastguard Worker   pointers_.clear();
94*8d67ca89SAndroid Build Coastguard Worker   key_to_index_.clear();
95*8d67ca89SAndroid Build Coastguard Worker   frames_.clear();
96*8d67ca89SAndroid Build Coastguard Worker   free_pointers_.clear();
97*8d67ca89SAndroid Build Coastguard Worker   // A hash index of kBacktraceEmptyIndex indicates that we tried to get
98*8d67ca89SAndroid Build Coastguard Worker   // a backtrace, but there was nothing recorded.
99*8d67ca89SAndroid Build Coastguard Worker   cur_hash_index_ = kBacktraceEmptyIndex + 1;
100*8d67ca89SAndroid Build Coastguard Worker 
101*8d67ca89SAndroid Build Coastguard Worker   backtrace_enabled_ = config.backtrace_enabled();
102*8d67ca89SAndroid Build Coastguard Worker   if (config.backtrace_enable_on_signal()) {
103*8d67ca89SAndroid Build Coastguard Worker     struct sigaction64 enable_act = {};
104*8d67ca89SAndroid Build Coastguard Worker     enable_act.sa_sigaction = ToggleBacktraceEnable;
105*8d67ca89SAndroid Build Coastguard Worker     enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
106*8d67ca89SAndroid Build Coastguard Worker     if (sigaction64(config.backtrace_signal(), &enable_act, nullptr) != 0) {
107*8d67ca89SAndroid Build Coastguard Worker       error_log("Unable to set up backtrace signal enable function: %s", strerror(errno));
108*8d67ca89SAndroid Build Coastguard Worker       return false;
109*8d67ca89SAndroid Build Coastguard Worker     }
110*8d67ca89SAndroid Build Coastguard Worker     if (config.options() & VERBOSE) {
111*8d67ca89SAndroid Build Coastguard Worker       info_log("%s: Run: 'kill -%d %d' to enable backtracing.", getprogname(),
112*8d67ca89SAndroid Build Coastguard Worker                config.backtrace_signal(), getpid());
113*8d67ca89SAndroid Build Coastguard Worker     }
114*8d67ca89SAndroid Build Coastguard Worker   }
115*8d67ca89SAndroid Build Coastguard Worker 
116*8d67ca89SAndroid Build Coastguard Worker   if (config.options() & BACKTRACE) {
117*8d67ca89SAndroid Build Coastguard Worker     struct sigaction64 act = {};
118*8d67ca89SAndroid Build Coastguard Worker     act.sa_sigaction = EnableDump;
119*8d67ca89SAndroid Build Coastguard Worker     act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
120*8d67ca89SAndroid Build Coastguard Worker     if (sigaction64(config.backtrace_dump_signal(), &act, nullptr) != 0) {
121*8d67ca89SAndroid Build Coastguard Worker       error_log("Unable to set up backtrace dump signal function: %s", strerror(errno));
122*8d67ca89SAndroid Build Coastguard Worker       return false;
123*8d67ca89SAndroid Build Coastguard Worker     }
124*8d67ca89SAndroid Build Coastguard Worker     if (config.options() & VERBOSE) {
125*8d67ca89SAndroid Build Coastguard Worker       info_log("%s: Run: 'kill -%d %d' to dump the backtrace.", getprogname(),
126*8d67ca89SAndroid Build Coastguard Worker                config.backtrace_dump_signal(), getpid());
127*8d67ca89SAndroid Build Coastguard Worker     }
128*8d67ca89SAndroid Build Coastguard Worker   }
129*8d67ca89SAndroid Build Coastguard Worker 
130*8d67ca89SAndroid Build Coastguard Worker   backtrace_dump_ = false;
131*8d67ca89SAndroid Build Coastguard Worker 
132*8d67ca89SAndroid Build Coastguard Worker   if (config.options() & FREE_TRACK) {
133*8d67ca89SAndroid Build Coastguard Worker     g_cmp_mem.resize(kCompareBufferSize, config.fill_free_value());
134*8d67ca89SAndroid Build Coastguard Worker   }
135*8d67ca89SAndroid Build Coastguard Worker   return true;
136*8d67ca89SAndroid Build Coastguard Worker }
137*8d67ca89SAndroid Build Coastguard Worker 
ShouldBacktraceAllocSize(size_t size_bytes)138*8d67ca89SAndroid Build Coastguard Worker static inline bool ShouldBacktraceAllocSize(size_t size_bytes) {
139*8d67ca89SAndroid Build Coastguard Worker   static bool only_backtrace_specific_sizes =
140*8d67ca89SAndroid Build Coastguard Worker       g_debug->config().options() & BACKTRACE_SPECIFIC_SIZES;
141*8d67ca89SAndroid Build Coastguard Worker   if (!only_backtrace_specific_sizes) {
142*8d67ca89SAndroid Build Coastguard Worker     return true;
143*8d67ca89SAndroid Build Coastguard Worker   }
144*8d67ca89SAndroid Build Coastguard Worker   static size_t min_size_bytes = g_debug->config().backtrace_min_size_bytes();
145*8d67ca89SAndroid Build Coastguard Worker   static size_t max_size_bytes = g_debug->config().backtrace_max_size_bytes();
146*8d67ca89SAndroid Build Coastguard Worker   return size_bytes >= min_size_bytes && size_bytes <= max_size_bytes;
147*8d67ca89SAndroid Build Coastguard Worker }
148*8d67ca89SAndroid Build Coastguard Worker 
AddBacktrace(size_t num_frames,size_t size_bytes)149*8d67ca89SAndroid Build Coastguard Worker size_t PointerData::AddBacktrace(size_t num_frames, size_t size_bytes) {
150*8d67ca89SAndroid Build Coastguard Worker   if (!ShouldBacktraceAllocSize(size_bytes)) {
151*8d67ca89SAndroid Build Coastguard Worker     return kBacktraceEmptyIndex;
152*8d67ca89SAndroid Build Coastguard Worker   }
153*8d67ca89SAndroid Build Coastguard Worker 
154*8d67ca89SAndroid Build Coastguard Worker   std::vector<uintptr_t> frames;
155*8d67ca89SAndroid Build Coastguard Worker   std::vector<unwindstack::FrameData> frames_info;
156*8d67ca89SAndroid Build Coastguard Worker   if (g_debug->config().options() & BACKTRACE_FULL) {
157*8d67ca89SAndroid Build Coastguard Worker     if (!Unwind(&frames, &frames_info, num_frames)) {
158*8d67ca89SAndroid Build Coastguard Worker       return kBacktraceEmptyIndex;
159*8d67ca89SAndroid Build Coastguard Worker     }
160*8d67ca89SAndroid Build Coastguard Worker   } else {
161*8d67ca89SAndroid Build Coastguard Worker     frames.resize(num_frames);
162*8d67ca89SAndroid Build Coastguard Worker     num_frames = backtrace_get(frames.data(), frames.size());
163*8d67ca89SAndroid Build Coastguard Worker     if (num_frames == 0) {
164*8d67ca89SAndroid Build Coastguard Worker       return kBacktraceEmptyIndex;
165*8d67ca89SAndroid Build Coastguard Worker     }
166*8d67ca89SAndroid Build Coastguard Worker     frames.resize(num_frames);
167*8d67ca89SAndroid Build Coastguard Worker   }
168*8d67ca89SAndroid Build Coastguard Worker 
169*8d67ca89SAndroid Build Coastguard Worker   FrameKeyType key{.num_frames = frames.size(), .frames = frames.data()};
170*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index;
171*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
172*8d67ca89SAndroid Build Coastguard Worker   auto entry = key_to_index_.find(key);
173*8d67ca89SAndroid Build Coastguard Worker   if (entry == key_to_index_.end()) {
174*8d67ca89SAndroid Build Coastguard Worker     hash_index = cur_hash_index_++;
175*8d67ca89SAndroid Build Coastguard Worker     key.frames = frames.data();
176*8d67ca89SAndroid Build Coastguard Worker     key_to_index_.emplace(key, hash_index);
177*8d67ca89SAndroid Build Coastguard Worker 
178*8d67ca89SAndroid Build Coastguard Worker     frames_.emplace(hash_index, FrameInfoType{.references = 1, .frames = std::move(frames)});
179*8d67ca89SAndroid Build Coastguard Worker     if (g_debug->config().options() & BACKTRACE_FULL) {
180*8d67ca89SAndroid Build Coastguard Worker       backtraces_info_.emplace(hash_index, std::move(frames_info));
181*8d67ca89SAndroid Build Coastguard Worker     }
182*8d67ca89SAndroid Build Coastguard Worker   } else {
183*8d67ca89SAndroid Build Coastguard Worker     hash_index = entry->second;
184*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* frame_info = &frames_[hash_index];
185*8d67ca89SAndroid Build Coastguard Worker     frame_info->references++;
186*8d67ca89SAndroid Build Coastguard Worker   }
187*8d67ca89SAndroid Build Coastguard Worker   return hash_index;
188*8d67ca89SAndroid Build Coastguard Worker }
189*8d67ca89SAndroid Build Coastguard Worker 
RemoveBacktrace(size_t hash_index)190*8d67ca89SAndroid Build Coastguard Worker void PointerData::RemoveBacktrace(size_t hash_index) {
191*8d67ca89SAndroid Build Coastguard Worker   if (hash_index <= kBacktraceEmptyIndex) {
192*8d67ca89SAndroid Build Coastguard Worker     return;
193*8d67ca89SAndroid Build Coastguard Worker   }
194*8d67ca89SAndroid Build Coastguard Worker 
195*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
196*8d67ca89SAndroid Build Coastguard Worker   auto frame_entry = frames_.find(hash_index);
197*8d67ca89SAndroid Build Coastguard Worker   if (frame_entry == frames_.end()) {
198*8d67ca89SAndroid Build Coastguard Worker     error_log("hash_index %zu does not have matching frame data.", hash_index);
199*8d67ca89SAndroid Build Coastguard Worker     return;
200*8d67ca89SAndroid Build Coastguard Worker   }
201*8d67ca89SAndroid Build Coastguard Worker   FrameInfoType* frame_info = &frame_entry->second;
202*8d67ca89SAndroid Build Coastguard Worker   if (--frame_info->references == 0) {
203*8d67ca89SAndroid Build Coastguard Worker     FrameKeyType key{.num_frames = frame_info->frames.size(), .frames = frame_info->frames.data()};
204*8d67ca89SAndroid Build Coastguard Worker     key_to_index_.erase(key);
205*8d67ca89SAndroid Build Coastguard Worker     frames_.erase(hash_index);
206*8d67ca89SAndroid Build Coastguard Worker     if (g_debug->config().options() & BACKTRACE_FULL) {
207*8d67ca89SAndroid Build Coastguard Worker       backtraces_info_.erase(hash_index);
208*8d67ca89SAndroid Build Coastguard Worker     }
209*8d67ca89SAndroid Build Coastguard Worker   }
210*8d67ca89SAndroid Build Coastguard Worker }
211*8d67ca89SAndroid Build Coastguard Worker 
Add(const void * ptr,size_t pointer_size)212*8d67ca89SAndroid Build Coastguard Worker void PointerData::Add(const void* ptr, size_t pointer_size) {
213*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index = 0;
214*8d67ca89SAndroid Build Coastguard Worker   if (backtrace_enabled_) {
215*8d67ca89SAndroid Build Coastguard Worker     hash_index = AddBacktrace(g_debug->config().backtrace_frames(), pointer_size);
216*8d67ca89SAndroid Build Coastguard Worker   }
217*8d67ca89SAndroid Build Coastguard Worker 
218*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
219*8d67ca89SAndroid Build Coastguard Worker   uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
220*8d67ca89SAndroid Build Coastguard Worker   pointers_[mangled_ptr] =
221*8d67ca89SAndroid Build Coastguard Worker       PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
222*8d67ca89SAndroid Build Coastguard Worker }
223*8d67ca89SAndroid Build Coastguard Worker 
Remove(const void * ptr)224*8d67ca89SAndroid Build Coastguard Worker void PointerData::Remove(const void* ptr) {
225*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index;
226*8d67ca89SAndroid Build Coastguard Worker   {
227*8d67ca89SAndroid Build Coastguard Worker     std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
228*8d67ca89SAndroid Build Coastguard Worker     uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
229*8d67ca89SAndroid Build Coastguard Worker     auto entry = pointers_.find(mangled_ptr);
230*8d67ca89SAndroid Build Coastguard Worker     if (entry == pointers_.end()) {
231*8d67ca89SAndroid Build Coastguard Worker       // Attempt to remove unknown pointer.
232*8d67ca89SAndroid Build Coastguard Worker       error_log("No tracked pointer found for 0x%" PRIxPTR, DemanglePointer(mangled_ptr));
233*8d67ca89SAndroid Build Coastguard Worker       return;
234*8d67ca89SAndroid Build Coastguard Worker     }
235*8d67ca89SAndroid Build Coastguard Worker     hash_index = entry->second.hash_index;
236*8d67ca89SAndroid Build Coastguard Worker     pointers_.erase(mangled_ptr);
237*8d67ca89SAndroid Build Coastguard Worker   }
238*8d67ca89SAndroid Build Coastguard Worker 
239*8d67ca89SAndroid Build Coastguard Worker   RemoveBacktrace(hash_index);
240*8d67ca89SAndroid Build Coastguard Worker }
241*8d67ca89SAndroid Build Coastguard Worker 
GetFrames(const void * ptr,uintptr_t * frames,size_t max_frames)242*8d67ca89SAndroid Build Coastguard Worker size_t PointerData::GetFrames(const void* ptr, uintptr_t* frames, size_t max_frames) {
243*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index;
244*8d67ca89SAndroid Build Coastguard Worker   {
245*8d67ca89SAndroid Build Coastguard Worker     std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
246*8d67ca89SAndroid Build Coastguard Worker     uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
247*8d67ca89SAndroid Build Coastguard Worker     auto entry = pointers_.find(mangled_ptr);
248*8d67ca89SAndroid Build Coastguard Worker     if (entry == pointers_.end()) {
249*8d67ca89SAndroid Build Coastguard Worker       return 0;
250*8d67ca89SAndroid Build Coastguard Worker     }
251*8d67ca89SAndroid Build Coastguard Worker     hash_index = entry->second.hash_index;
252*8d67ca89SAndroid Build Coastguard Worker   }
253*8d67ca89SAndroid Build Coastguard Worker 
254*8d67ca89SAndroid Build Coastguard Worker   if (hash_index <= kBacktraceEmptyIndex) {
255*8d67ca89SAndroid Build Coastguard Worker     return 0;
256*8d67ca89SAndroid Build Coastguard Worker   }
257*8d67ca89SAndroid Build Coastguard Worker 
258*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
259*8d67ca89SAndroid Build Coastguard Worker   auto frame_entry = frames_.find(hash_index);
260*8d67ca89SAndroid Build Coastguard Worker   if (frame_entry == frames_.end()) {
261*8d67ca89SAndroid Build Coastguard Worker     return 0;
262*8d67ca89SAndroid Build Coastguard Worker   }
263*8d67ca89SAndroid Build Coastguard Worker   FrameInfoType* frame_info = &frame_entry->second;
264*8d67ca89SAndroid Build Coastguard Worker   if (max_frames > frame_info->frames.size()) {
265*8d67ca89SAndroid Build Coastguard Worker     max_frames = frame_info->frames.size();
266*8d67ca89SAndroid Build Coastguard Worker   }
267*8d67ca89SAndroid Build Coastguard Worker   memcpy(frames, &frame_info->frames[0], max_frames * sizeof(uintptr_t));
268*8d67ca89SAndroid Build Coastguard Worker 
269*8d67ca89SAndroid Build Coastguard Worker   return max_frames;
270*8d67ca89SAndroid Build Coastguard Worker }
271*8d67ca89SAndroid Build Coastguard Worker 
LogBacktrace(size_t hash_index)272*8d67ca89SAndroid Build Coastguard Worker void PointerData::LogBacktrace(size_t hash_index) {
273*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
274*8d67ca89SAndroid Build Coastguard Worker   if (g_debug->config().options() & BACKTRACE_FULL) {
275*8d67ca89SAndroid Build Coastguard Worker     auto backtrace_info_entry = backtraces_info_.find(hash_index);
276*8d67ca89SAndroid Build Coastguard Worker     if (backtrace_info_entry != backtraces_info_.end()) {
277*8d67ca89SAndroid Build Coastguard Worker       UnwindLog(backtrace_info_entry->second);
278*8d67ca89SAndroid Build Coastguard Worker       return;
279*8d67ca89SAndroid Build Coastguard Worker     }
280*8d67ca89SAndroid Build Coastguard Worker   } else {
281*8d67ca89SAndroid Build Coastguard Worker     auto frame_entry = frames_.find(hash_index);
282*8d67ca89SAndroid Build Coastguard Worker     if (frame_entry != frames_.end()) {
283*8d67ca89SAndroid Build Coastguard Worker       FrameInfoType* frame_info = &frame_entry->second;
284*8d67ca89SAndroid Build Coastguard Worker       backtrace_log(frame_info->frames.data(), frame_info->frames.size());
285*8d67ca89SAndroid Build Coastguard Worker       return;
286*8d67ca89SAndroid Build Coastguard Worker     }
287*8d67ca89SAndroid Build Coastguard Worker   }
288*8d67ca89SAndroid Build Coastguard Worker   error_log("  hash_index %zu does not have matching frame data.", hash_index);
289*8d67ca89SAndroid Build Coastguard Worker }
290*8d67ca89SAndroid Build Coastguard Worker 
LogFreeError(const FreePointerInfoType & info,size_t max_cmp_bytes)291*8d67ca89SAndroid Build Coastguard Worker void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
292*8d67ca89SAndroid Build Coastguard Worker   error_log(LOG_DIVIDER);
293*8d67ca89SAndroid Build Coastguard Worker   uintptr_t pointer = DemanglePointer(info.mangled_ptr);
294*8d67ca89SAndroid Build Coastguard Worker   uint8_t* memory = reinterpret_cast<uint8_t*>(pointer);
295*8d67ca89SAndroid Build Coastguard Worker   error_log("+++ ALLOCATION %p USED AFTER FREE", memory);
296*8d67ca89SAndroid Build Coastguard Worker   uint8_t fill_free_value = g_debug->config().fill_free_value();
297*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < max_cmp_bytes; i++) {
298*8d67ca89SAndroid Build Coastguard Worker     if (memory[i] != fill_free_value) {
299*8d67ca89SAndroid Build Coastguard Worker       error_log("  allocation[%zu] = 0x%02x (expected 0x%02x)", i, memory[i], fill_free_value);
300*8d67ca89SAndroid Build Coastguard Worker     }
301*8d67ca89SAndroid Build Coastguard Worker   }
302*8d67ca89SAndroid Build Coastguard Worker 
303*8d67ca89SAndroid Build Coastguard Worker   if (info.hash_index > kBacktraceEmptyIndex) {
304*8d67ca89SAndroid Build Coastguard Worker     error_log("Backtrace at time of free:");
305*8d67ca89SAndroid Build Coastguard Worker     LogBacktrace(info.hash_index);
306*8d67ca89SAndroid Build Coastguard Worker   }
307*8d67ca89SAndroid Build Coastguard Worker 
308*8d67ca89SAndroid Build Coastguard Worker   error_log(LOG_DIVIDER);
309*8d67ca89SAndroid Build Coastguard Worker   if (g_debug->config().options() & ABORT_ON_ERROR) {
310*8d67ca89SAndroid Build Coastguard Worker     abort();
311*8d67ca89SAndroid Build Coastguard Worker   }
312*8d67ca89SAndroid Build Coastguard Worker }
313*8d67ca89SAndroid Build Coastguard Worker 
VerifyFreedPointer(const FreePointerInfoType & info)314*8d67ca89SAndroid Build Coastguard Worker void PointerData::VerifyFreedPointer(const FreePointerInfoType& info) {
315*8d67ca89SAndroid Build Coastguard Worker   size_t usable_size;
316*8d67ca89SAndroid Build Coastguard Worker   uintptr_t pointer = DemanglePointer(info.mangled_ptr);
317*8d67ca89SAndroid Build Coastguard Worker   if (g_debug->HeaderEnabled()) {
318*8d67ca89SAndroid Build Coastguard Worker     // Check to see if the tag data has been damaged.
319*8d67ca89SAndroid Build Coastguard Worker     Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(pointer));
320*8d67ca89SAndroid Build Coastguard Worker     if (header->tag != DEBUG_FREE_TAG) {
321*8d67ca89SAndroid Build Coastguard Worker       error_log(LOG_DIVIDER);
322*8d67ca89SAndroid Build Coastguard Worker       error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer,
323*8d67ca89SAndroid Build Coastguard Worker                 header->tag);
324*8d67ca89SAndroid Build Coastguard Worker       error_log(LOG_DIVIDER);
325*8d67ca89SAndroid Build Coastguard Worker       if (g_debug->config().options() & ABORT_ON_ERROR) {
326*8d67ca89SAndroid Build Coastguard Worker         abort();
327*8d67ca89SAndroid Build Coastguard Worker       }
328*8d67ca89SAndroid Build Coastguard Worker 
329*8d67ca89SAndroid Build Coastguard Worker       // Stop processing here, it is impossible to tell how the header
330*8d67ca89SAndroid Build Coastguard Worker       // may have been damaged.
331*8d67ca89SAndroid Build Coastguard Worker       return;
332*8d67ca89SAndroid Build Coastguard Worker     }
333*8d67ca89SAndroid Build Coastguard Worker     usable_size = header->usable_size;
334*8d67ca89SAndroid Build Coastguard Worker   } else {
335*8d67ca89SAndroid Build Coastguard Worker     usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(pointer));
336*8d67ca89SAndroid Build Coastguard Worker   }
337*8d67ca89SAndroid Build Coastguard Worker 
338*8d67ca89SAndroid Build Coastguard Worker   size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes())
339*8d67ca89SAndroid Build Coastguard Worker                      ? usable_size
340*8d67ca89SAndroid Build Coastguard Worker                      : g_debug->config().fill_on_free_bytes();
341*8d67ca89SAndroid Build Coastguard Worker   size_t max_cmp_bytes = bytes;
342*8d67ca89SAndroid Build Coastguard Worker   const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
343*8d67ca89SAndroid Build Coastguard Worker   while (bytes > 0) {
344*8d67ca89SAndroid Build Coastguard Worker     size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size();
345*8d67ca89SAndroid Build Coastguard Worker     if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) {
346*8d67ca89SAndroid Build Coastguard Worker       LogFreeError(info, max_cmp_bytes);
347*8d67ca89SAndroid Build Coastguard Worker     }
348*8d67ca89SAndroid Build Coastguard Worker     bytes -= bytes_to_cmp;
349*8d67ca89SAndroid Build Coastguard Worker     memory = &memory[bytes_to_cmp];
350*8d67ca89SAndroid Build Coastguard Worker   }
351*8d67ca89SAndroid Build Coastguard Worker }
352*8d67ca89SAndroid Build Coastguard Worker 
AddFreed(const void * ptr,size_t size_bytes)353*8d67ca89SAndroid Build Coastguard Worker void* PointerData::AddFreed(const void* ptr, size_t size_bytes) {
354*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index = 0;
355*8d67ca89SAndroid Build Coastguard Worker   size_t num_frames = g_debug->config().free_track_backtrace_num_frames();
356*8d67ca89SAndroid Build Coastguard Worker   if (num_frames) {
357*8d67ca89SAndroid Build Coastguard Worker     hash_index = AddBacktrace(num_frames, size_bytes);
358*8d67ca89SAndroid Build Coastguard Worker   }
359*8d67ca89SAndroid Build Coastguard Worker 
360*8d67ca89SAndroid Build Coastguard Worker   void* last = nullptr;
361*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
362*8d67ca89SAndroid Build Coastguard Worker   if (free_pointers_.size() == g_debug->config().free_track_allocations()) {
363*8d67ca89SAndroid Build Coastguard Worker     FreePointerInfoType info(free_pointers_.front());
364*8d67ca89SAndroid Build Coastguard Worker     free_pointers_.pop_front();
365*8d67ca89SAndroid Build Coastguard Worker     VerifyFreedPointer(info);
366*8d67ca89SAndroid Build Coastguard Worker     RemoveBacktrace(info.hash_index);
367*8d67ca89SAndroid Build Coastguard Worker     last = reinterpret_cast<void*>(DemanglePointer(info.mangled_ptr));
368*8d67ca89SAndroid Build Coastguard Worker   }
369*8d67ca89SAndroid Build Coastguard Worker 
370*8d67ca89SAndroid Build Coastguard Worker   uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
371*8d67ca89SAndroid Build Coastguard Worker   free_pointers_.emplace_back(FreePointerInfoType{mangled_ptr, hash_index});
372*8d67ca89SAndroid Build Coastguard Worker   return last;
373*8d67ca89SAndroid Build Coastguard Worker }
374*8d67ca89SAndroid Build Coastguard Worker 
LogFreeBacktrace(const void * ptr)375*8d67ca89SAndroid Build Coastguard Worker void PointerData::LogFreeBacktrace(const void* ptr) {
376*8d67ca89SAndroid Build Coastguard Worker   size_t hash_index = 0;
377*8d67ca89SAndroid Build Coastguard Worker   {
378*8d67ca89SAndroid Build Coastguard Worker     uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
379*8d67ca89SAndroid Build Coastguard Worker     std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
380*8d67ca89SAndroid Build Coastguard Worker     for (const auto& info : free_pointers_) {
381*8d67ca89SAndroid Build Coastguard Worker       if (DemanglePointer(info.mangled_ptr) == pointer) {
382*8d67ca89SAndroid Build Coastguard Worker         hash_index = info.hash_index;
383*8d67ca89SAndroid Build Coastguard Worker         break;
384*8d67ca89SAndroid Build Coastguard Worker       }
385*8d67ca89SAndroid Build Coastguard Worker     }
386*8d67ca89SAndroid Build Coastguard Worker   }
387*8d67ca89SAndroid Build Coastguard Worker 
388*8d67ca89SAndroid Build Coastguard Worker   if (hash_index <= kBacktraceEmptyIndex) {
389*8d67ca89SAndroid Build Coastguard Worker     return;
390*8d67ca89SAndroid Build Coastguard Worker   }
391*8d67ca89SAndroid Build Coastguard Worker 
392*8d67ca89SAndroid Build Coastguard Worker   error_log("Backtrace of original free:");
393*8d67ca89SAndroid Build Coastguard Worker   LogBacktrace(hash_index);
394*8d67ca89SAndroid Build Coastguard Worker }
395*8d67ca89SAndroid Build Coastguard Worker 
VerifyAllFreed()396*8d67ca89SAndroid Build Coastguard Worker void PointerData::VerifyAllFreed() {
397*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
398*8d67ca89SAndroid Build Coastguard Worker   for (auto& free_info : free_pointers_) {
399*8d67ca89SAndroid Build Coastguard Worker     VerifyFreedPointer(free_info);
400*8d67ca89SAndroid Build Coastguard Worker   }
401*8d67ca89SAndroid Build Coastguard Worker }
402*8d67ca89SAndroid Build Coastguard Worker 
GetList(std::vector<ListInfoType> * list,bool only_with_backtrace)403*8d67ca89SAndroid Build Coastguard Worker void PointerData::GetList(std::vector<ListInfoType>* list, bool only_with_backtrace)
404*8d67ca89SAndroid Build Coastguard Worker     REQUIRES(pointer_mutex_, frame_mutex_) {
405*8d67ca89SAndroid Build Coastguard Worker   for (const auto& entry : pointers_) {
406*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* frame_info = nullptr;
407*8d67ca89SAndroid Build Coastguard Worker     std::vector<unwindstack::FrameData>* backtrace_info = nullptr;
408*8d67ca89SAndroid Build Coastguard Worker     uintptr_t pointer = DemanglePointer(entry.first);
409*8d67ca89SAndroid Build Coastguard Worker     size_t hash_index = entry.second.hash_index;
410*8d67ca89SAndroid Build Coastguard Worker     if (hash_index > kBacktraceEmptyIndex) {
411*8d67ca89SAndroid Build Coastguard Worker       auto frame_entry = frames_.find(hash_index);
412*8d67ca89SAndroid Build Coastguard Worker       if (frame_entry == frames_.end()) {
413*8d67ca89SAndroid Build Coastguard Worker         // Somehow wound up with a pointer with a valid hash_index, but
414*8d67ca89SAndroid Build Coastguard Worker         // no frame data. This should not be possible since adding a pointer
415*8d67ca89SAndroid Build Coastguard Worker         // occurs after the hash_index and frame data have been added.
416*8d67ca89SAndroid Build Coastguard Worker         // When removing a pointer, the pointer is deleted before the frame
417*8d67ca89SAndroid Build Coastguard Worker         // data.
418*8d67ca89SAndroid Build Coastguard Worker         error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
419*8d67ca89SAndroid Build Coastguard Worker       } else {
420*8d67ca89SAndroid Build Coastguard Worker         frame_info = &frame_entry->second;
421*8d67ca89SAndroid Build Coastguard Worker       }
422*8d67ca89SAndroid Build Coastguard Worker 
423*8d67ca89SAndroid Build Coastguard Worker       if (g_debug->config().options() & BACKTRACE_FULL) {
424*8d67ca89SAndroid Build Coastguard Worker         auto backtrace_entry = backtraces_info_.find(hash_index);
425*8d67ca89SAndroid Build Coastguard Worker         if (backtrace_entry == backtraces_info_.end()) {
426*8d67ca89SAndroid Build Coastguard Worker           error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
427*8d67ca89SAndroid Build Coastguard Worker         } else {
428*8d67ca89SAndroid Build Coastguard Worker           backtrace_info = &backtrace_entry->second;
429*8d67ca89SAndroid Build Coastguard Worker         }
430*8d67ca89SAndroid Build Coastguard Worker       }
431*8d67ca89SAndroid Build Coastguard Worker     }
432*8d67ca89SAndroid Build Coastguard Worker     if (hash_index == 0 && only_with_backtrace) {
433*8d67ca89SAndroid Build Coastguard Worker       continue;
434*8d67ca89SAndroid Build Coastguard Worker     }
435*8d67ca89SAndroid Build Coastguard Worker 
436*8d67ca89SAndroid Build Coastguard Worker     list->emplace_back(ListInfoType{pointer, 1, entry.second.RealSize(),
437*8d67ca89SAndroid Build Coastguard Worker                                     entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
438*8d67ca89SAndroid Build Coastguard Worker   }
439*8d67ca89SAndroid Build Coastguard Worker 
440*8d67ca89SAndroid Build Coastguard Worker   // Sort by the size of the allocation.
441*8d67ca89SAndroid Build Coastguard Worker   std::sort(list->begin(), list->end(), [](const ListInfoType& a, const ListInfoType& b) {
442*8d67ca89SAndroid Build Coastguard Worker     // Put zygote child allocations first.
443*8d67ca89SAndroid Build Coastguard Worker     bool a_zygote_child_alloc = a.zygote_child_alloc;
444*8d67ca89SAndroid Build Coastguard Worker     bool b_zygote_child_alloc = b.zygote_child_alloc;
445*8d67ca89SAndroid Build Coastguard Worker     if (a_zygote_child_alloc && !b_zygote_child_alloc) {
446*8d67ca89SAndroid Build Coastguard Worker       return false;
447*8d67ca89SAndroid Build Coastguard Worker     }
448*8d67ca89SAndroid Build Coastguard Worker     if (!a_zygote_child_alloc && b_zygote_child_alloc) {
449*8d67ca89SAndroid Build Coastguard Worker       return true;
450*8d67ca89SAndroid Build Coastguard Worker     }
451*8d67ca89SAndroid Build Coastguard Worker 
452*8d67ca89SAndroid Build Coastguard Worker     // Sort by size, descending order.
453*8d67ca89SAndroid Build Coastguard Worker     if (a.size != b.size) return a.size > b.size;
454*8d67ca89SAndroid Build Coastguard Worker 
455*8d67ca89SAndroid Build Coastguard Worker     // Put pointers with no backtrace last.
456*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* a_frame = a.frame_info;
457*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* b_frame = b.frame_info;
458*8d67ca89SAndroid Build Coastguard Worker     if (a_frame == nullptr && b_frame != nullptr) {
459*8d67ca89SAndroid Build Coastguard Worker       return false;
460*8d67ca89SAndroid Build Coastguard Worker     } else if (a_frame != nullptr && b_frame == nullptr) {
461*8d67ca89SAndroid Build Coastguard Worker       return true;
462*8d67ca89SAndroid Build Coastguard Worker     } else if (a_frame == nullptr && b_frame == nullptr) {
463*8d67ca89SAndroid Build Coastguard Worker       return a.pointer < b.pointer;
464*8d67ca89SAndroid Build Coastguard Worker     }
465*8d67ca89SAndroid Build Coastguard Worker 
466*8d67ca89SAndroid Build Coastguard Worker     // Put the pointers with longest backtrace first.
467*8d67ca89SAndroid Build Coastguard Worker     if (a_frame->frames.size() != b_frame->frames.size()) {
468*8d67ca89SAndroid Build Coastguard Worker       return a_frame->frames.size() > b_frame->frames.size();
469*8d67ca89SAndroid Build Coastguard Worker     }
470*8d67ca89SAndroid Build Coastguard Worker 
471*8d67ca89SAndroid Build Coastguard Worker     // Last sort by pointer.
472*8d67ca89SAndroid Build Coastguard Worker     return a.pointer < b.pointer;
473*8d67ca89SAndroid Build Coastguard Worker   });
474*8d67ca89SAndroid Build Coastguard Worker }
475*8d67ca89SAndroid Build Coastguard Worker 
GetUniqueList(std::vector<ListInfoType> * list,bool only_with_backtrace)476*8d67ca89SAndroid Build Coastguard Worker void PointerData::GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace)
477*8d67ca89SAndroid Build Coastguard Worker     REQUIRES(pointer_mutex_, frame_mutex_) {
478*8d67ca89SAndroid Build Coastguard Worker   GetList(list, only_with_backtrace);
479*8d67ca89SAndroid Build Coastguard Worker 
480*8d67ca89SAndroid Build Coastguard Worker   // Remove duplicates of size/backtraces.
481*8d67ca89SAndroid Build Coastguard Worker   for (auto iter = list->begin(); iter != list->end();) {
482*8d67ca89SAndroid Build Coastguard Worker     auto dup_iter = iter + 1;
483*8d67ca89SAndroid Build Coastguard Worker     bool zygote_child_alloc = iter->zygote_child_alloc;
484*8d67ca89SAndroid Build Coastguard Worker     size_t size = iter->size;
485*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* frame_info = iter->frame_info;
486*8d67ca89SAndroid Build Coastguard Worker     for (; dup_iter != list->end(); ++dup_iter) {
487*8d67ca89SAndroid Build Coastguard Worker       if (zygote_child_alloc != dup_iter->zygote_child_alloc || size != dup_iter->size ||
488*8d67ca89SAndroid Build Coastguard Worker           frame_info != dup_iter->frame_info) {
489*8d67ca89SAndroid Build Coastguard Worker         break;
490*8d67ca89SAndroid Build Coastguard Worker       }
491*8d67ca89SAndroid Build Coastguard Worker       iter->num_allocations++;
492*8d67ca89SAndroid Build Coastguard Worker     }
493*8d67ca89SAndroid Build Coastguard Worker     iter = list->erase(iter + 1, dup_iter);
494*8d67ca89SAndroid Build Coastguard Worker   }
495*8d67ca89SAndroid Build Coastguard Worker }
496*8d67ca89SAndroid Build Coastguard Worker 
LogLeaks()497*8d67ca89SAndroid Build Coastguard Worker void PointerData::LogLeaks() {
498*8d67ca89SAndroid Build Coastguard Worker   std::vector<ListInfoType> list;
499*8d67ca89SAndroid Build Coastguard Worker 
500*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
501*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
502*8d67ca89SAndroid Build Coastguard Worker   GetList(&list, false);
503*8d67ca89SAndroid Build Coastguard Worker 
504*8d67ca89SAndroid Build Coastguard Worker   size_t track_count = 0;
505*8d67ca89SAndroid Build Coastguard Worker   for (const auto& list_info : list) {
506*8d67ca89SAndroid Build Coastguard Worker     error_log("+++ %s leaked block of size %zu at 0x%" PRIxPTR " (leak %zu of %zu)", getprogname(),
507*8d67ca89SAndroid Build Coastguard Worker               list_info.size, list_info.pointer, ++track_count, list.size());
508*8d67ca89SAndroid Build Coastguard Worker     if (list_info.backtrace_info != nullptr) {
509*8d67ca89SAndroid Build Coastguard Worker       error_log("Backtrace at time of allocation:");
510*8d67ca89SAndroid Build Coastguard Worker       UnwindLog(*list_info.backtrace_info);
511*8d67ca89SAndroid Build Coastguard Worker     } else if (list_info.frame_info != nullptr) {
512*8d67ca89SAndroid Build Coastguard Worker       error_log("Backtrace at time of allocation:");
513*8d67ca89SAndroid Build Coastguard Worker       backtrace_log(list_info.frame_info->frames.data(), list_info.frame_info->frames.size());
514*8d67ca89SAndroid Build Coastguard Worker     }
515*8d67ca89SAndroid Build Coastguard Worker     // Do not bother to free the pointers, we are about to exit any way.
516*8d67ca89SAndroid Build Coastguard Worker   }
517*8d67ca89SAndroid Build Coastguard Worker }
518*8d67ca89SAndroid Build Coastguard Worker 
GetAllocList(std::vector<ListInfoType> * list)519*8d67ca89SAndroid Build Coastguard Worker void PointerData::GetAllocList(std::vector<ListInfoType>* list) {
520*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
521*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
522*8d67ca89SAndroid Build Coastguard Worker 
523*8d67ca89SAndroid Build Coastguard Worker   if (pointers_.empty()) {
524*8d67ca89SAndroid Build Coastguard Worker     return;
525*8d67ca89SAndroid Build Coastguard Worker   }
526*8d67ca89SAndroid Build Coastguard Worker 
527*8d67ca89SAndroid Build Coastguard Worker   GetList(list, false);
528*8d67ca89SAndroid Build Coastguard Worker }
529*8d67ca89SAndroid Build Coastguard Worker 
GetInfo(uint8_t ** info,size_t * overall_size,size_t * info_size,size_t * total_memory,size_t * backtrace_size)530*8d67ca89SAndroid Build Coastguard Worker void PointerData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
531*8d67ca89SAndroid Build Coastguard Worker                           size_t* total_memory, size_t* backtrace_size) {
532*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
533*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
534*8d67ca89SAndroid Build Coastguard Worker 
535*8d67ca89SAndroid Build Coastguard Worker   if (pointers_.empty()) {
536*8d67ca89SAndroid Build Coastguard Worker     return;
537*8d67ca89SAndroid Build Coastguard Worker   }
538*8d67ca89SAndroid Build Coastguard Worker 
539*8d67ca89SAndroid Build Coastguard Worker   std::vector<ListInfoType> list;
540*8d67ca89SAndroid Build Coastguard Worker   GetUniqueList(&list, true);
541*8d67ca89SAndroid Build Coastguard Worker   if (list.empty()) {
542*8d67ca89SAndroid Build Coastguard Worker     return;
543*8d67ca89SAndroid Build Coastguard Worker   }
544*8d67ca89SAndroid Build Coastguard Worker 
545*8d67ca89SAndroid Build Coastguard Worker   *backtrace_size = g_debug->config().backtrace_frames();
546*8d67ca89SAndroid Build Coastguard Worker   *info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size;
547*8d67ca89SAndroid Build Coastguard Worker   *overall_size = *info_size * list.size();
548*8d67ca89SAndroid Build Coastguard Worker   *info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, list.size()));
549*8d67ca89SAndroid Build Coastguard Worker   if (*info == nullptr) {
550*8d67ca89SAndroid Build Coastguard Worker     return;
551*8d67ca89SAndroid Build Coastguard Worker   }
552*8d67ca89SAndroid Build Coastguard Worker 
553*8d67ca89SAndroid Build Coastguard Worker   uint8_t* data = *info;
554*8d67ca89SAndroid Build Coastguard Worker   *total_memory = 0;
555*8d67ca89SAndroid Build Coastguard Worker   for (const auto& list_info : list) {
556*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* frame_info = list_info.frame_info;
557*8d67ca89SAndroid Build Coastguard Worker     *total_memory += list_info.size * list_info.num_allocations;
558*8d67ca89SAndroid Build Coastguard Worker     size_t allocation_size =
559*8d67ca89SAndroid Build Coastguard Worker         PointerInfoType::GetEncodedSize(list_info.zygote_child_alloc, list_info.size);
560*8d67ca89SAndroid Build Coastguard Worker     memcpy(data, &allocation_size, sizeof(size_t));
561*8d67ca89SAndroid Build Coastguard Worker     memcpy(&data[sizeof(size_t)], &list_info.num_allocations, sizeof(size_t));
562*8d67ca89SAndroid Build Coastguard Worker     if (frame_info != nullptr) {
563*8d67ca89SAndroid Build Coastguard Worker       memcpy(&data[2 * sizeof(size_t)], frame_info->frames.data(),
564*8d67ca89SAndroid Build Coastguard Worker              frame_info->frames.size() * sizeof(uintptr_t));
565*8d67ca89SAndroid Build Coastguard Worker     }
566*8d67ca89SAndroid Build Coastguard Worker     data += *info_size;
567*8d67ca89SAndroid Build Coastguard Worker   }
568*8d67ca89SAndroid Build Coastguard Worker }
569*8d67ca89SAndroid Build Coastguard Worker 
Exists(const void * ptr)570*8d67ca89SAndroid Build Coastguard Worker bool PointerData::Exists(const void* ptr) {
571*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
572*8d67ca89SAndroid Build Coastguard Worker   uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
573*8d67ca89SAndroid Build Coastguard Worker   return pointers_.count(mangled_ptr) != 0;
574*8d67ca89SAndroid Build Coastguard Worker }
575*8d67ca89SAndroid Build Coastguard Worker 
DumpLiveToFile(int fd)576*8d67ca89SAndroid Build Coastguard Worker void PointerData::DumpLiveToFile(int fd) {
577*8d67ca89SAndroid Build Coastguard Worker   std::vector<ListInfoType> list;
578*8d67ca89SAndroid Build Coastguard Worker 
579*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
580*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> frame_guard(frame_mutex_);
581*8d67ca89SAndroid Build Coastguard Worker   GetUniqueList(&list, false);
582*8d67ca89SAndroid Build Coastguard Worker 
583*8d67ca89SAndroid Build Coastguard Worker   size_t total_memory = 0;
584*8d67ca89SAndroid Build Coastguard Worker   for (const auto& info : list) {
585*8d67ca89SAndroid Build Coastguard Worker     total_memory += info.size * info.num_allocations;
586*8d67ca89SAndroid Build Coastguard Worker   }
587*8d67ca89SAndroid Build Coastguard Worker 
588*8d67ca89SAndroid Build Coastguard Worker   dprintf(fd, "Total memory: %zu\n", total_memory);
589*8d67ca89SAndroid Build Coastguard Worker   dprintf(fd, "Allocation records: %zd\n", list.size());
590*8d67ca89SAndroid Build Coastguard Worker   dprintf(fd, "Backtrace size: %zu\n", g_debug->config().backtrace_frames());
591*8d67ca89SAndroid Build Coastguard Worker   dprintf(fd, "\n");
592*8d67ca89SAndroid Build Coastguard Worker 
593*8d67ca89SAndroid Build Coastguard Worker   for (const auto& info : list) {
594*8d67ca89SAndroid Build Coastguard Worker     dprintf(fd, "z %d  sz %8zu  num    %zu  bt", (info.zygote_child_alloc) ? 1 : 0, info.size,
595*8d67ca89SAndroid Build Coastguard Worker             info.num_allocations);
596*8d67ca89SAndroid Build Coastguard Worker     FrameInfoType* frame_info = info.frame_info;
597*8d67ca89SAndroid Build Coastguard Worker     if (frame_info != nullptr) {
598*8d67ca89SAndroid Build Coastguard Worker       for (size_t i = 0; i < frame_info->frames.size(); i++) {
599*8d67ca89SAndroid Build Coastguard Worker         if (frame_info->frames[i] == 0) {
600*8d67ca89SAndroid Build Coastguard Worker           break;
601*8d67ca89SAndroid Build Coastguard Worker         }
602*8d67ca89SAndroid Build Coastguard Worker         dprintf(fd, " %" PRIxPTR, frame_info->frames[i]);
603*8d67ca89SAndroid Build Coastguard Worker       }
604*8d67ca89SAndroid Build Coastguard Worker     }
605*8d67ca89SAndroid Build Coastguard Worker     dprintf(fd, "\n");
606*8d67ca89SAndroid Build Coastguard Worker     if (info.backtrace_info != nullptr) {
607*8d67ca89SAndroid Build Coastguard Worker       dprintf(fd, "  bt_info");
608*8d67ca89SAndroid Build Coastguard Worker       for (const auto& frame : *info.backtrace_info) {
609*8d67ca89SAndroid Build Coastguard Worker         dprintf(fd, " {");
610*8d67ca89SAndroid Build Coastguard Worker         if (frame.map_info != nullptr && !frame.map_info->name().empty()) {
611*8d67ca89SAndroid Build Coastguard Worker           dprintf(fd, "\"%s\"", frame.map_info->name().c_str());
612*8d67ca89SAndroid Build Coastguard Worker         } else {
613*8d67ca89SAndroid Build Coastguard Worker           dprintf(fd, "\"\"");
614*8d67ca89SAndroid Build Coastguard Worker         }
615*8d67ca89SAndroid Build Coastguard Worker         dprintf(fd, " %" PRIx64, frame.rel_pc);
616*8d67ca89SAndroid Build Coastguard Worker         if (frame.function_name.empty()) {
617*8d67ca89SAndroid Build Coastguard Worker           dprintf(fd, " \"\" 0}");
618*8d67ca89SAndroid Build Coastguard Worker         } else {
619*8d67ca89SAndroid Build Coastguard Worker           char* demangled_name =
620*8d67ca89SAndroid Build Coastguard Worker               abi::__cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
621*8d67ca89SAndroid Build Coastguard Worker           const char* name;
622*8d67ca89SAndroid Build Coastguard Worker           if (demangled_name != nullptr) {
623*8d67ca89SAndroid Build Coastguard Worker             name = demangled_name;
624*8d67ca89SAndroid Build Coastguard Worker           } else {
625*8d67ca89SAndroid Build Coastguard Worker             name = frame.function_name.c_str();
626*8d67ca89SAndroid Build Coastguard Worker           }
627*8d67ca89SAndroid Build Coastguard Worker           dprintf(fd, " \"%s\" %" PRIx64 "}", name, frame.function_offset);
628*8d67ca89SAndroid Build Coastguard Worker           free(demangled_name);
629*8d67ca89SAndroid Build Coastguard Worker         }
630*8d67ca89SAndroid Build Coastguard Worker       }
631*8d67ca89SAndroid Build Coastguard Worker       dprintf(fd, "\n");
632*8d67ca89SAndroid Build Coastguard Worker     }
633*8d67ca89SAndroid Build Coastguard Worker   }
634*8d67ca89SAndroid Build Coastguard Worker }
635*8d67ca89SAndroid Build Coastguard Worker 
PrepareFork()636*8d67ca89SAndroid Build Coastguard Worker void PointerData::PrepareFork() NO_THREAD_SAFETY_ANALYSIS {
637*8d67ca89SAndroid Build Coastguard Worker   free_pointer_mutex_.lock();
638*8d67ca89SAndroid Build Coastguard Worker   pointer_mutex_.lock();
639*8d67ca89SAndroid Build Coastguard Worker   frame_mutex_.lock();
640*8d67ca89SAndroid Build Coastguard Worker }
641*8d67ca89SAndroid Build Coastguard Worker 
PostForkParent()642*8d67ca89SAndroid Build Coastguard Worker void PointerData::PostForkParent() NO_THREAD_SAFETY_ANALYSIS {
643*8d67ca89SAndroid Build Coastguard Worker   frame_mutex_.unlock();
644*8d67ca89SAndroid Build Coastguard Worker   pointer_mutex_.unlock();
645*8d67ca89SAndroid Build Coastguard Worker   free_pointer_mutex_.unlock();
646*8d67ca89SAndroid Build Coastguard Worker }
647*8d67ca89SAndroid Build Coastguard Worker 
PostForkChild()648*8d67ca89SAndroid Build Coastguard Worker void PointerData::PostForkChild() __attribute__((no_thread_safety_analysis)) {
649*8d67ca89SAndroid Build Coastguard Worker   // Make sure that any potential mutexes have been released and are back
650*8d67ca89SAndroid Build Coastguard Worker   // to an initial state.
651*8d67ca89SAndroid Build Coastguard Worker   frame_mutex_.try_lock();
652*8d67ca89SAndroid Build Coastguard Worker   frame_mutex_.unlock();
653*8d67ca89SAndroid Build Coastguard Worker   pointer_mutex_.try_lock();
654*8d67ca89SAndroid Build Coastguard Worker   pointer_mutex_.unlock();
655*8d67ca89SAndroid Build Coastguard Worker   free_pointer_mutex_.try_lock();
656*8d67ca89SAndroid Build Coastguard Worker   free_pointer_mutex_.unlock();
657*8d67ca89SAndroid Build Coastguard Worker }
658*8d67ca89SAndroid Build Coastguard Worker 
IteratePointers(std::function<void (uintptr_t pointer)> fn)659*8d67ca89SAndroid Build Coastguard Worker void PointerData::IteratePointers(std::function<void(uintptr_t pointer)> fn) {
660*8d67ca89SAndroid Build Coastguard Worker   std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
661*8d67ca89SAndroid Build Coastguard Worker   for (const auto entry : pointers_) {
662*8d67ca89SAndroid Build Coastguard Worker     fn(DemanglePointer(entry.first));
663*8d67ca89SAndroid Build Coastguard Worker   }
664*8d67ca89SAndroid Build Coastguard Worker }
665