1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2012 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 <errno.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
31*8d67ca89SAndroid Build Coastguard Worker #include <malloc.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <pthread.h>
33*8d67ca89SAndroid Build Coastguard Worker #include <signal.h>
34*8d67ca89SAndroid Build Coastguard Worker #include <stdio.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
36*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
37*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
38*8d67ca89SAndroid Build Coastguard Worker #include <sys/param.h>
39*8d67ca89SAndroid Build Coastguard Worker #include <sys/syscall.h>
40*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
41*8d67ca89SAndroid Build Coastguard Worker
42*8d67ca89SAndroid Build Coastguard Worker #include <mutex>
43*8d67ca89SAndroid Build Coastguard Worker #include <vector>
44*8d67ca89SAndroid Build Coastguard Worker
45*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
46*8d67ca89SAndroid Build Coastguard Worker #include <android-base/properties.h>
47*8d67ca89SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
48*8d67ca89SAndroid Build Coastguard Worker #include <bionic/malloc_tagged_pointers.h>
49*8d67ca89SAndroid Build Coastguard Worker #include <platform/bionic/reserved_signals.h>
50*8d67ca89SAndroid Build Coastguard Worker #include <private/MallocXmlElem.h>
51*8d67ca89SAndroid Build Coastguard Worker #include <private/bionic_malloc_dispatch.h>
52*8d67ca89SAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
53*8d67ca89SAndroid Build Coastguard Worker
54*8d67ca89SAndroid Build Coastguard Worker #include "Config.h"
55*8d67ca89SAndroid Build Coastguard Worker #include "DebugData.h"
56*8d67ca89SAndroid Build Coastguard Worker #include "LogAllocatorStats.h"
57*8d67ca89SAndroid Build Coastguard Worker #include "Nanotime.h"
58*8d67ca89SAndroid Build Coastguard Worker #include "Unreachable.h"
59*8d67ca89SAndroid Build Coastguard Worker #include "UnwindBacktrace.h"
60*8d67ca89SAndroid Build Coastguard Worker #include "backtrace.h"
61*8d67ca89SAndroid Build Coastguard Worker #include "debug_disable.h"
62*8d67ca89SAndroid Build Coastguard Worker #include "debug_log.h"
63*8d67ca89SAndroid Build Coastguard Worker #include "malloc_debug.h"
64*8d67ca89SAndroid Build Coastguard Worker
65*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
66*8d67ca89SAndroid Build Coastguard Worker // Global Data
67*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
68*8d67ca89SAndroid Build Coastguard Worker DebugData* g_debug;
69*8d67ca89SAndroid Build Coastguard Worker
70*8d67ca89SAndroid Build Coastguard Worker bool* g_zygote_child;
71*8d67ca89SAndroid Build Coastguard Worker
72*8d67ca89SAndroid Build Coastguard Worker const MallocDispatch* g_dispatch;
73*8d67ca89SAndroid Build Coastguard Worker
74*8d67ca89SAndroid Build Coastguard Worker namespace {
75*8d67ca89SAndroid Build Coastguard Worker // A TimedResult contains the result of from malloc end_ns al. functions and the
76*8d67ca89SAndroid Build Coastguard Worker // start/end timestamps.
77*8d67ca89SAndroid Build Coastguard Worker struct TimedResult {
78*8d67ca89SAndroid Build Coastguard Worker uint64_t start_ns = 0;
79*8d67ca89SAndroid Build Coastguard Worker uint64_t end_ns = 0;
80*8d67ca89SAndroid Build Coastguard Worker union {
81*8d67ca89SAndroid Build Coastguard Worker size_t s;
82*8d67ca89SAndroid Build Coastguard Worker int i;
83*8d67ca89SAndroid Build Coastguard Worker void* p;
84*8d67ca89SAndroid Build Coastguard Worker } v;
85*8d67ca89SAndroid Build Coastguard Worker
GetStartTimeNS__anonf491307d0111::TimedResult86*8d67ca89SAndroid Build Coastguard Worker uint64_t GetStartTimeNS() const { return start_ns; }
GetEndTimeNS__anonf491307d0111::TimedResult87*8d67ca89SAndroid Build Coastguard Worker uint64_t GetEndTimeNS() const { return end_ns; }
SetStartTimeNS__anonf491307d0111::TimedResult88*8d67ca89SAndroid Build Coastguard Worker void SetStartTimeNS(uint64_t t) { start_ns = t; }
SetEndTimeNS__anonf491307d0111::TimedResult89*8d67ca89SAndroid Build Coastguard Worker void SetEndTimeNS(uint64_t t) { end_ns = t; }
90*8d67ca89SAndroid Build Coastguard Worker
91*8d67ca89SAndroid Build Coastguard Worker template <typename T>
92*8d67ca89SAndroid Build Coastguard Worker void setValue(T);
93*8d67ca89SAndroid Build Coastguard Worker template <>
setValue__anonf491307d0111::TimedResult94*8d67ca89SAndroid Build Coastguard Worker void setValue(size_t s) {
95*8d67ca89SAndroid Build Coastguard Worker v.s = s;
96*8d67ca89SAndroid Build Coastguard Worker }
97*8d67ca89SAndroid Build Coastguard Worker template <>
setValue__anonf491307d0111::TimedResult98*8d67ca89SAndroid Build Coastguard Worker void setValue(int i) {
99*8d67ca89SAndroid Build Coastguard Worker v.i = i;
100*8d67ca89SAndroid Build Coastguard Worker }
101*8d67ca89SAndroid Build Coastguard Worker template <>
setValue__anonf491307d0111::TimedResult102*8d67ca89SAndroid Build Coastguard Worker void setValue(void* p) {
103*8d67ca89SAndroid Build Coastguard Worker v.p = p;
104*8d67ca89SAndroid Build Coastguard Worker }
105*8d67ca89SAndroid Build Coastguard Worker
106*8d67ca89SAndroid Build Coastguard Worker template <typename T>
107*8d67ca89SAndroid Build Coastguard Worker T getValue() const;
108*8d67ca89SAndroid Build Coastguard Worker template <>
getValue__anonf491307d0111::TimedResult109*8d67ca89SAndroid Build Coastguard Worker size_t getValue<size_t>() const {
110*8d67ca89SAndroid Build Coastguard Worker return v.s;
111*8d67ca89SAndroid Build Coastguard Worker }
112*8d67ca89SAndroid Build Coastguard Worker template <>
getValue__anonf491307d0111::TimedResult113*8d67ca89SAndroid Build Coastguard Worker int getValue<int>() const {
114*8d67ca89SAndroid Build Coastguard Worker return v.i;
115*8d67ca89SAndroid Build Coastguard Worker }
116*8d67ca89SAndroid Build Coastguard Worker template <>
getValue__anonf491307d0111::TimedResult117*8d67ca89SAndroid Build Coastguard Worker void* getValue<void*>() const {
118*8d67ca89SAndroid Build Coastguard Worker return v.p;
119*8d67ca89SAndroid Build Coastguard Worker }
120*8d67ca89SAndroid Build Coastguard Worker };
121*8d67ca89SAndroid Build Coastguard Worker
122*8d67ca89SAndroid Build Coastguard Worker class ScopedTimer {
123*8d67ca89SAndroid Build Coastguard Worker public:
ScopedTimer(TimedResult & res)124*8d67ca89SAndroid Build Coastguard Worker ScopedTimer(TimedResult& res) : res_(res) { res_.start_ns = Nanotime(); }
125*8d67ca89SAndroid Build Coastguard Worker
~ScopedTimer()126*8d67ca89SAndroid Build Coastguard Worker ~ScopedTimer() { res_.end_ns = Nanotime(); }
127*8d67ca89SAndroid Build Coastguard Worker
128*8d67ca89SAndroid Build Coastguard Worker private:
129*8d67ca89SAndroid Build Coastguard Worker TimedResult& res_;
130*8d67ca89SAndroid Build Coastguard Worker };
131*8d67ca89SAndroid Build Coastguard Worker
132*8d67ca89SAndroid Build Coastguard Worker } // namespace
133*8d67ca89SAndroid Build Coastguard Worker
134*8d67ca89SAndroid Build Coastguard Worker template <typename MallocFn, typename... Args>
TimerCall(MallocFn fn,Args...args)135*8d67ca89SAndroid Build Coastguard Worker static TimedResult TimerCall(MallocFn fn, Args... args) {
136*8d67ca89SAndroid Build Coastguard Worker TimedResult ret;
137*8d67ca89SAndroid Build Coastguard Worker decltype((g_dispatch->*fn)(args...)) r;
138*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
139*8d67ca89SAndroid Build Coastguard Worker ScopedTimer t(ret);
140*8d67ca89SAndroid Build Coastguard Worker r = (g_dispatch->*fn)(args...);
141*8d67ca89SAndroid Build Coastguard Worker } else {
142*8d67ca89SAndroid Build Coastguard Worker r = (g_dispatch->*fn)(args...);
143*8d67ca89SAndroid Build Coastguard Worker }
144*8d67ca89SAndroid Build Coastguard Worker ret.setValue<decltype(r)>(r);
145*8d67ca89SAndroid Build Coastguard Worker return ret;
146*8d67ca89SAndroid Build Coastguard Worker }
147*8d67ca89SAndroid Build Coastguard Worker
148*8d67ca89SAndroid Build Coastguard Worker template <typename MallocFn, typename... Args>
TimerCallVoid(MallocFn fn,Args...args)149*8d67ca89SAndroid Build Coastguard Worker static TimedResult TimerCallVoid(MallocFn fn, Args... args) {
150*8d67ca89SAndroid Build Coastguard Worker TimedResult ret;
151*8d67ca89SAndroid Build Coastguard Worker {
152*8d67ca89SAndroid Build Coastguard Worker ScopedTimer t(ret);
153*8d67ca89SAndroid Build Coastguard Worker (g_dispatch->*fn)(args...);
154*8d67ca89SAndroid Build Coastguard Worker }
155*8d67ca89SAndroid Build Coastguard Worker return ret;
156*8d67ca89SAndroid Build Coastguard Worker }
157*8d67ca89SAndroid Build Coastguard Worker
158*8d67ca89SAndroid Build Coastguard Worker #define TCALL(FUNC, ...) TimerCall(&MallocDispatch::FUNC, __VA_ARGS__);
159*8d67ca89SAndroid Build Coastguard Worker #define TCALLVOID(FUNC, ...) TimerCallVoid(&MallocDispatch::FUNC, __VA_ARGS__);
160*8d67ca89SAndroid Build Coastguard Worker
161*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
162*8d67ca89SAndroid Build Coastguard Worker
163*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
164*8d67ca89SAndroid Build Coastguard Worker // Use C style prototypes for all exported functions. This makes it easy
165*8d67ca89SAndroid Build Coastguard Worker // to do dlsym lookups during libc initialization when malloc debug
166*8d67ca89SAndroid Build Coastguard Worker // is enabled.
167*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
168*8d67ca89SAndroid Build Coastguard Worker __BEGIN_DECLS
169*8d67ca89SAndroid Build Coastguard Worker
170*8d67ca89SAndroid Build Coastguard Worker bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* malloc_zygote_child,
171*8d67ca89SAndroid Build Coastguard Worker const char* options);
172*8d67ca89SAndroid Build Coastguard Worker void debug_finalize();
173*8d67ca89SAndroid Build Coastguard Worker void debug_dump_heap(const char* file_name);
174*8d67ca89SAndroid Build Coastguard Worker void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
175*8d67ca89SAndroid Build Coastguard Worker size_t* total_memory, size_t* backtrace_size);
176*8d67ca89SAndroid Build Coastguard Worker bool debug_write_malloc_leak_info(FILE* fp);
177*8d67ca89SAndroid Build Coastguard Worker ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
178*8d67ca89SAndroid Build Coastguard Worker void debug_free_malloc_leak_info(uint8_t* info);
179*8d67ca89SAndroid Build Coastguard Worker size_t debug_malloc_usable_size(void* pointer);
180*8d67ca89SAndroid Build Coastguard Worker void* debug_malloc(size_t size);
181*8d67ca89SAndroid Build Coastguard Worker void debug_free(void* pointer);
182*8d67ca89SAndroid Build Coastguard Worker void* debug_aligned_alloc(size_t alignment, size_t size);
183*8d67ca89SAndroid Build Coastguard Worker void* debug_memalign(size_t alignment, size_t bytes);
184*8d67ca89SAndroid Build Coastguard Worker void* debug_realloc(void* pointer, size_t bytes);
185*8d67ca89SAndroid Build Coastguard Worker void* debug_calloc(size_t nmemb, size_t bytes);
186*8d67ca89SAndroid Build Coastguard Worker struct mallinfo debug_mallinfo();
187*8d67ca89SAndroid Build Coastguard Worker int debug_mallopt(int param, int value);
188*8d67ca89SAndroid Build Coastguard Worker int debug_malloc_info(int options, FILE* fp);
189*8d67ca89SAndroid Build Coastguard Worker int debug_posix_memalign(void** memptr, size_t alignment, size_t size);
190*8d67ca89SAndroid Build Coastguard Worker int debug_malloc_iterate(uintptr_t base, size_t size,
191*8d67ca89SAndroid Build Coastguard Worker void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
192*8d67ca89SAndroid Build Coastguard Worker void debug_malloc_disable();
193*8d67ca89SAndroid Build Coastguard Worker void debug_malloc_enable();
194*8d67ca89SAndroid Build Coastguard Worker
195*8d67ca89SAndroid Build Coastguard Worker #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
196*8d67ca89SAndroid Build Coastguard Worker void* debug_pvalloc(size_t bytes);
197*8d67ca89SAndroid Build Coastguard Worker void* debug_valloc(size_t size);
198*8d67ca89SAndroid Build Coastguard Worker #endif
199*8d67ca89SAndroid Build Coastguard Worker
200*8d67ca89SAndroid Build Coastguard Worker __END_DECLS
201*8d67ca89SAndroid Build Coastguard Worker // ------------------------------------------------------------------------
202*8d67ca89SAndroid Build Coastguard Worker
203*8d67ca89SAndroid Build Coastguard Worker class ScopedConcurrentLock {
204*8d67ca89SAndroid Build Coastguard Worker public:
ScopedConcurrentLock()205*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock() {
206*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_rdlock(&lock_);
207*8d67ca89SAndroid Build Coastguard Worker }
~ScopedConcurrentLock()208*8d67ca89SAndroid Build Coastguard Worker ~ScopedConcurrentLock() {
209*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_unlock(&lock_);
210*8d67ca89SAndroid Build Coastguard Worker }
211*8d67ca89SAndroid Build Coastguard Worker
Init()212*8d67ca89SAndroid Build Coastguard Worker static void Init() {
213*8d67ca89SAndroid Build Coastguard Worker pthread_rwlockattr_t attr;
214*8d67ca89SAndroid Build Coastguard Worker // Set the attribute so that when a write lock is pending, read locks are no
215*8d67ca89SAndroid Build Coastguard Worker // longer granted.
216*8d67ca89SAndroid Build Coastguard Worker pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
217*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_init(&lock_, &attr);
218*8d67ca89SAndroid Build Coastguard Worker }
219*8d67ca89SAndroid Build Coastguard Worker
BlockAllOperations()220*8d67ca89SAndroid Build Coastguard Worker static void BlockAllOperations() {
221*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_wrlock(&lock_);
222*8d67ca89SAndroid Build Coastguard Worker }
223*8d67ca89SAndroid Build Coastguard Worker
224*8d67ca89SAndroid Build Coastguard Worker private:
225*8d67ca89SAndroid Build Coastguard Worker static pthread_rwlock_t lock_;
226*8d67ca89SAndroid Build Coastguard Worker };
227*8d67ca89SAndroid Build Coastguard Worker pthread_rwlock_t ScopedConcurrentLock::lock_;
228*8d67ca89SAndroid Build Coastguard Worker
229*8d67ca89SAndroid Build Coastguard Worker // Use this because the sigprocmask* functions filter out the reserved bionic
230*8d67ca89SAndroid Build Coastguard Worker // signals including the signal this code blocks.
__rt_sigprocmask(int how,const sigset64_t * new_set,sigset64_t * old_set,size_t sigset_size)231*8d67ca89SAndroid Build Coastguard Worker static inline int __rt_sigprocmask(int how, const sigset64_t* new_set, sigset64_t* old_set,
232*8d67ca89SAndroid Build Coastguard Worker size_t sigset_size) {
233*8d67ca89SAndroid Build Coastguard Worker return syscall(SYS_rt_sigprocmask, how, new_set, old_set, sigset_size);
234*8d67ca89SAndroid Build Coastguard Worker }
235*8d67ca89SAndroid Build Coastguard Worker
236*8d67ca89SAndroid Build Coastguard Worker // Need to block the backtrace signal while in malloc debug routines
237*8d67ca89SAndroid Build Coastguard Worker // otherwise there is a chance of a deadlock and timeout when unwinding.
238*8d67ca89SAndroid Build Coastguard Worker // This can occur if a thread is paused while owning a malloc debug
239*8d67ca89SAndroid Build Coastguard Worker // internal lock.
240*8d67ca89SAndroid Build Coastguard Worker class ScopedBacktraceSignalBlocker {
241*8d67ca89SAndroid Build Coastguard Worker public:
ScopedBacktraceSignalBlocker()242*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker() {
243*8d67ca89SAndroid Build Coastguard Worker sigemptyset64(&backtrace_set_);
244*8d67ca89SAndroid Build Coastguard Worker sigaddset64(&backtrace_set_, BIONIC_SIGNAL_BACKTRACE);
245*8d67ca89SAndroid Build Coastguard Worker sigset64_t old_set;
246*8d67ca89SAndroid Build Coastguard Worker __rt_sigprocmask(SIG_BLOCK, &backtrace_set_, &old_set, sizeof(backtrace_set_));
247*8d67ca89SAndroid Build Coastguard Worker if (sigismember64(&old_set, BIONIC_SIGNAL_BACKTRACE)) {
248*8d67ca89SAndroid Build Coastguard Worker unblock_ = false;
249*8d67ca89SAndroid Build Coastguard Worker }
250*8d67ca89SAndroid Build Coastguard Worker }
251*8d67ca89SAndroid Build Coastguard Worker
~ScopedBacktraceSignalBlocker()252*8d67ca89SAndroid Build Coastguard Worker ~ScopedBacktraceSignalBlocker() {
253*8d67ca89SAndroid Build Coastguard Worker if (unblock_) {
254*8d67ca89SAndroid Build Coastguard Worker __rt_sigprocmask(SIG_UNBLOCK, &backtrace_set_, nullptr, sizeof(backtrace_set_));
255*8d67ca89SAndroid Build Coastguard Worker }
256*8d67ca89SAndroid Build Coastguard Worker }
257*8d67ca89SAndroid Build Coastguard Worker
258*8d67ca89SAndroid Build Coastguard Worker private:
259*8d67ca89SAndroid Build Coastguard Worker bool unblock_ = true;
260*8d67ca89SAndroid Build Coastguard Worker sigset64_t backtrace_set_;
261*8d67ca89SAndroid Build Coastguard Worker };
262*8d67ca89SAndroid Build Coastguard Worker
InitAtfork()263*8d67ca89SAndroid Build Coastguard Worker static void InitAtfork() {
264*8d67ca89SAndroid Build Coastguard Worker static pthread_once_t atfork_init = PTHREAD_ONCE_INIT;
265*8d67ca89SAndroid Build Coastguard Worker pthread_once(&atfork_init, []() {
266*8d67ca89SAndroid Build Coastguard Worker pthread_atfork(
267*8d67ca89SAndroid Build Coastguard Worker []() {
268*8d67ca89SAndroid Build Coastguard Worker if (g_debug != nullptr) {
269*8d67ca89SAndroid Build Coastguard Worker g_debug->PrepareFork();
270*8d67ca89SAndroid Build Coastguard Worker }
271*8d67ca89SAndroid Build Coastguard Worker },
272*8d67ca89SAndroid Build Coastguard Worker []() {
273*8d67ca89SAndroid Build Coastguard Worker if (g_debug != nullptr) {
274*8d67ca89SAndroid Build Coastguard Worker g_debug->PostForkParent();
275*8d67ca89SAndroid Build Coastguard Worker }
276*8d67ca89SAndroid Build Coastguard Worker },
277*8d67ca89SAndroid Build Coastguard Worker []() {
278*8d67ca89SAndroid Build Coastguard Worker if (g_debug != nullptr) {
279*8d67ca89SAndroid Build Coastguard Worker g_debug->PostForkChild();
280*8d67ca89SAndroid Build Coastguard Worker }
281*8d67ca89SAndroid Build Coastguard Worker });
282*8d67ca89SAndroid Build Coastguard Worker });
283*8d67ca89SAndroid Build Coastguard Worker }
284*8d67ca89SAndroid Build Coastguard Worker
BacktraceAndLog()285*8d67ca89SAndroid Build Coastguard Worker void BacktraceAndLog() {
286*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & BACKTRACE_FULL) {
287*8d67ca89SAndroid Build Coastguard Worker std::vector<uintptr_t> frames;
288*8d67ca89SAndroid Build Coastguard Worker std::vector<unwindstack::FrameData> frames_info;
289*8d67ca89SAndroid Build Coastguard Worker if (!Unwind(&frames, &frames_info, 256)) {
290*8d67ca89SAndroid Build Coastguard Worker error_log(" Backtrace failed to get any frames.");
291*8d67ca89SAndroid Build Coastguard Worker } else {
292*8d67ca89SAndroid Build Coastguard Worker UnwindLog(frames_info);
293*8d67ca89SAndroid Build Coastguard Worker }
294*8d67ca89SAndroid Build Coastguard Worker } else {
295*8d67ca89SAndroid Build Coastguard Worker std::vector<uintptr_t> frames(256);
296*8d67ca89SAndroid Build Coastguard Worker size_t num_frames = backtrace_get(frames.data(), frames.size());
297*8d67ca89SAndroid Build Coastguard Worker if (num_frames == 0) {
298*8d67ca89SAndroid Build Coastguard Worker error_log(" Backtrace failed to get any frames.");
299*8d67ca89SAndroid Build Coastguard Worker } else {
300*8d67ca89SAndroid Build Coastguard Worker backtrace_log(frames.data(), num_frames);
301*8d67ca89SAndroid Build Coastguard Worker }
302*8d67ca89SAndroid Build Coastguard Worker }
303*8d67ca89SAndroid Build Coastguard Worker }
304*8d67ca89SAndroid Build Coastguard Worker
LogError(const void * pointer,const char * error_str)305*8d67ca89SAndroid Build Coastguard Worker static void LogError(const void* pointer, const char* error_str) {
306*8d67ca89SAndroid Build Coastguard Worker error_log(LOG_DIVIDER);
307*8d67ca89SAndroid Build Coastguard Worker error_log("+++ ALLOCATION %p %s", pointer, error_str);
308*8d67ca89SAndroid Build Coastguard Worker
309*8d67ca89SAndroid Build Coastguard Worker // If we are tracking already freed pointers, check to see if this is
310*8d67ca89SAndroid Build Coastguard Worker // one so we can print extra information.
311*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FREE_TRACK) {
312*8d67ca89SAndroid Build Coastguard Worker PointerData::LogFreeBacktrace(pointer);
313*8d67ca89SAndroid Build Coastguard Worker }
314*8d67ca89SAndroid Build Coastguard Worker
315*8d67ca89SAndroid Build Coastguard Worker error_log("Backtrace at time of failure:");
316*8d67ca89SAndroid Build Coastguard Worker BacktraceAndLog();
317*8d67ca89SAndroid Build Coastguard Worker error_log(LOG_DIVIDER);
318*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & ABORT_ON_ERROR) {
319*8d67ca89SAndroid Build Coastguard Worker abort();
320*8d67ca89SAndroid Build Coastguard Worker }
321*8d67ca89SAndroid Build Coastguard Worker }
322*8d67ca89SAndroid Build Coastguard Worker
VerifyPointer(const void * pointer,const char * function_name)323*8d67ca89SAndroid Build Coastguard Worker static bool VerifyPointer(const void* pointer, const char* function_name) {
324*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
325*8d67ca89SAndroid Build Coastguard Worker Header* header = g_debug->GetHeader(pointer);
326*8d67ca89SAndroid Build Coastguard Worker if (header->tag != DEBUG_TAG) {
327*8d67ca89SAndroid Build Coastguard Worker std::string error_str;
328*8d67ca89SAndroid Build Coastguard Worker if (header->tag == DEBUG_FREE_TAG) {
329*8d67ca89SAndroid Build Coastguard Worker error_str = std::string("USED AFTER FREE (") + function_name + ")";
330*8d67ca89SAndroid Build Coastguard Worker } else {
331*8d67ca89SAndroid Build Coastguard Worker error_str = android::base::StringPrintf("HAS INVALID TAG %" PRIx32 " (%s)", header->tag,
332*8d67ca89SAndroid Build Coastguard Worker function_name);
333*8d67ca89SAndroid Build Coastguard Worker }
334*8d67ca89SAndroid Build Coastguard Worker LogError(pointer, error_str.c_str());
335*8d67ca89SAndroid Build Coastguard Worker return false;
336*8d67ca89SAndroid Build Coastguard Worker }
337*8d67ca89SAndroid Build Coastguard Worker }
338*8d67ca89SAndroid Build Coastguard Worker
339*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
340*8d67ca89SAndroid Build Coastguard Worker if (!PointerData::Exists(pointer)) {
341*8d67ca89SAndroid Build Coastguard Worker std::string error_str(std::string("UNKNOWN POINTER (") + function_name + ")");
342*8d67ca89SAndroid Build Coastguard Worker LogError(pointer, error_str.c_str());
343*8d67ca89SAndroid Build Coastguard Worker return false;
344*8d67ca89SAndroid Build Coastguard Worker }
345*8d67ca89SAndroid Build Coastguard Worker }
346*8d67ca89SAndroid Build Coastguard Worker return true;
347*8d67ca89SAndroid Build Coastguard Worker }
348*8d67ca89SAndroid Build Coastguard Worker
InternalMallocUsableSize(void * pointer)349*8d67ca89SAndroid Build Coastguard Worker static size_t InternalMallocUsableSize(void* pointer) {
350*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
351*8d67ca89SAndroid Build Coastguard Worker return g_debug->GetHeader(pointer)->usable_size;
352*8d67ca89SAndroid Build Coastguard Worker } else {
353*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->malloc_usable_size(pointer);
354*8d67ca89SAndroid Build Coastguard Worker }
355*8d67ca89SAndroid Build Coastguard Worker }
356*8d67ca89SAndroid Build Coastguard Worker
InitHeader(Header * header,void * orig_pointer,size_t size)357*8d67ca89SAndroid Build Coastguard Worker static void* InitHeader(Header* header, void* orig_pointer, size_t size) {
358*8d67ca89SAndroid Build Coastguard Worker header->tag = DEBUG_TAG;
359*8d67ca89SAndroid Build Coastguard Worker header->orig_pointer = orig_pointer;
360*8d67ca89SAndroid Build Coastguard Worker header->size = size;
361*8d67ca89SAndroid Build Coastguard Worker header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
362*8d67ca89SAndroid Build Coastguard Worker if (header->usable_size == 0) {
363*8d67ca89SAndroid Build Coastguard Worker g_dispatch->free(orig_pointer);
364*8d67ca89SAndroid Build Coastguard Worker return nullptr;
365*8d67ca89SAndroid Build Coastguard Worker }
366*8d67ca89SAndroid Build Coastguard Worker header->usable_size -= g_debug->pointer_offset() + reinterpret_cast<uintptr_t>(header) -
367*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(orig_pointer);
368*8d67ca89SAndroid Build Coastguard Worker
369*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FRONT_GUARD) {
370*8d67ca89SAndroid Build Coastguard Worker uint8_t* guard = g_debug->GetFrontGuard(header);
371*8d67ca89SAndroid Build Coastguard Worker memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
372*8d67ca89SAndroid Build Coastguard Worker }
373*8d67ca89SAndroid Build Coastguard Worker
374*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & REAR_GUARD) {
375*8d67ca89SAndroid Build Coastguard Worker uint8_t* guard = g_debug->GetRearGuard(header);
376*8d67ca89SAndroid Build Coastguard Worker memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
377*8d67ca89SAndroid Build Coastguard Worker // If the rear guard is enabled, set the usable size to the exact size
378*8d67ca89SAndroid Build Coastguard Worker // of the allocation.
379*8d67ca89SAndroid Build Coastguard Worker header->usable_size = header->size;
380*8d67ca89SAndroid Build Coastguard Worker }
381*8d67ca89SAndroid Build Coastguard Worker
382*8d67ca89SAndroid Build Coastguard Worker return g_debug->GetPointer(header);
383*8d67ca89SAndroid Build Coastguard Worker }
384*8d67ca89SAndroid Build Coastguard Worker
385*8d67ca89SAndroid Build Coastguard Worker extern "C" void __asan_init() __attribute__((weak));
386*8d67ca89SAndroid Build Coastguard Worker
debug_initialize(const MallocDispatch * malloc_dispatch,bool * zygote_child,const char * options)387*8d67ca89SAndroid Build Coastguard Worker bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* zygote_child,
388*8d67ca89SAndroid Build Coastguard Worker const char* options) {
389*8d67ca89SAndroid Build Coastguard Worker if (zygote_child == nullptr || options == nullptr) {
390*8d67ca89SAndroid Build Coastguard Worker return false;
391*8d67ca89SAndroid Build Coastguard Worker }
392*8d67ca89SAndroid Build Coastguard Worker
393*8d67ca89SAndroid Build Coastguard Worker if (__asan_init != 0) {
394*8d67ca89SAndroid Build Coastguard Worker error_log("malloc debug cannot be enabled alongside ASAN");
395*8d67ca89SAndroid Build Coastguard Worker return false;
396*8d67ca89SAndroid Build Coastguard Worker }
397*8d67ca89SAndroid Build Coastguard Worker
398*8d67ca89SAndroid Build Coastguard Worker InitAtfork();
399*8d67ca89SAndroid Build Coastguard Worker
400*8d67ca89SAndroid Build Coastguard Worker g_zygote_child = zygote_child;
401*8d67ca89SAndroid Build Coastguard Worker
402*8d67ca89SAndroid Build Coastguard Worker g_dispatch = malloc_dispatch;
403*8d67ca89SAndroid Build Coastguard Worker
404*8d67ca89SAndroid Build Coastguard Worker if (!DebugDisableInitialize()) {
405*8d67ca89SAndroid Build Coastguard Worker return false;
406*8d67ca89SAndroid Build Coastguard Worker }
407*8d67ca89SAndroid Build Coastguard Worker
408*8d67ca89SAndroid Build Coastguard Worker DebugData* debug = new DebugData();
409*8d67ca89SAndroid Build Coastguard Worker if (!debug->Initialize(options) || !Unreachable::Initialize(debug->config())) {
410*8d67ca89SAndroid Build Coastguard Worker delete debug;
411*8d67ca89SAndroid Build Coastguard Worker DebugDisableFinalize();
412*8d67ca89SAndroid Build Coastguard Worker return false;
413*8d67ca89SAndroid Build Coastguard Worker }
414*8d67ca89SAndroid Build Coastguard Worker g_debug = debug;
415*8d67ca89SAndroid Build Coastguard Worker
416*8d67ca89SAndroid Build Coastguard Worker // Always enable the backtrace code since we will use it in a number
417*8d67ca89SAndroid Build Coastguard Worker // of different error cases.
418*8d67ca89SAndroid Build Coastguard Worker backtrace_startup();
419*8d67ca89SAndroid Build Coastguard Worker
420*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & VERBOSE) {
421*8d67ca89SAndroid Build Coastguard Worker info_log("%s: malloc debug enabled", getprogname());
422*8d67ca89SAndroid Build Coastguard Worker }
423*8d67ca89SAndroid Build Coastguard Worker
424*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock::Init();
425*8d67ca89SAndroid Build Coastguard Worker
426*8d67ca89SAndroid Build Coastguard Worker return true;
427*8d67ca89SAndroid Build Coastguard Worker }
428*8d67ca89SAndroid Build Coastguard Worker
debug_finalize()429*8d67ca89SAndroid Build Coastguard Worker void debug_finalize() {
430*8d67ca89SAndroid Build Coastguard Worker if (g_debug == nullptr) {
431*8d67ca89SAndroid Build Coastguard Worker return;
432*8d67ca89SAndroid Build Coastguard Worker }
433*8d67ca89SAndroid Build Coastguard Worker
434*8d67ca89SAndroid Build Coastguard Worker // Make sure that there are no other threads doing debug allocations
435*8d67ca89SAndroid Build Coastguard Worker // before we kill everything.
436*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock::BlockAllOperations();
437*8d67ca89SAndroid Build Coastguard Worker
438*8d67ca89SAndroid Build Coastguard Worker // Turn off capturing allocations calls.
439*8d67ca89SAndroid Build Coastguard Worker DebugDisableSet(true);
440*8d67ca89SAndroid Build Coastguard Worker
441*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FREE_TRACK) {
442*8d67ca89SAndroid Build Coastguard Worker PointerData::VerifyAllFreed();
443*8d67ca89SAndroid Build Coastguard Worker }
444*8d67ca89SAndroid Build Coastguard Worker
445*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & LEAK_TRACK) {
446*8d67ca89SAndroid Build Coastguard Worker PointerData::LogLeaks();
447*8d67ca89SAndroid Build Coastguard Worker }
448*8d67ca89SAndroid Build Coastguard Worker
449*8d67ca89SAndroid Build Coastguard Worker if ((g_debug->config().options() & RECORD_ALLOCS) && g_debug->config().record_allocs_on_exit()) {
450*8d67ca89SAndroid Build Coastguard Worker RecordData::WriteEntriesOnExit();
451*8d67ca89SAndroid Build Coastguard Worker }
452*8d67ca89SAndroid Build Coastguard Worker
453*8d67ca89SAndroid Build Coastguard Worker if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
454*8d67ca89SAndroid Build Coastguard Worker debug_dump_heap(android::base::StringPrintf("%s.%d.exit.txt",
455*8d67ca89SAndroid Build Coastguard Worker g_debug->config().backtrace_dump_prefix().c_str(),
456*8d67ca89SAndroid Build Coastguard Worker getpid()).c_str());
457*8d67ca89SAndroid Build Coastguard Worker }
458*8d67ca89SAndroid Build Coastguard Worker
459*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & LOG_ALLOCATOR_STATS_ON_EXIT) {
460*8d67ca89SAndroid Build Coastguard Worker LogAllocatorStats::Log();
461*8d67ca89SAndroid Build Coastguard Worker }
462*8d67ca89SAndroid Build Coastguard Worker
463*8d67ca89SAndroid Build Coastguard Worker backtrace_shutdown();
464*8d67ca89SAndroid Build Coastguard Worker
465*8d67ca89SAndroid Build Coastguard Worker // In order to prevent any issues of threads freeing previous pointers
466*8d67ca89SAndroid Build Coastguard Worker // after the main thread calls this code, simply leak the g_debug pointer
467*8d67ca89SAndroid Build Coastguard Worker // and do not destroy the debug disable pthread key.
468*8d67ca89SAndroid Build Coastguard Worker }
469*8d67ca89SAndroid Build Coastguard Worker
debug_get_malloc_leak_info(uint8_t ** info,size_t * overall_size,size_t * info_size,size_t * total_memory,size_t * backtrace_size)470*8d67ca89SAndroid Build Coastguard Worker void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
471*8d67ca89SAndroid Build Coastguard Worker size_t* total_memory, size_t* backtrace_size) {
472*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
473*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
474*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
475*8d67ca89SAndroid Build Coastguard Worker
476*8d67ca89SAndroid Build Coastguard Worker // Verify the arguments.
477*8d67ca89SAndroid Build Coastguard Worker if (info == nullptr || overall_size == nullptr || info_size == nullptr || total_memory == nullptr ||
478*8d67ca89SAndroid Build Coastguard Worker backtrace_size == nullptr) {
479*8d67ca89SAndroid Build Coastguard Worker error_log("get_malloc_leak_info: At least one invalid parameter.");
480*8d67ca89SAndroid Build Coastguard Worker return;
481*8d67ca89SAndroid Build Coastguard Worker }
482*8d67ca89SAndroid Build Coastguard Worker
483*8d67ca89SAndroid Build Coastguard Worker *info = nullptr;
484*8d67ca89SAndroid Build Coastguard Worker *overall_size = 0;
485*8d67ca89SAndroid Build Coastguard Worker *info_size = 0;
486*8d67ca89SAndroid Build Coastguard Worker *total_memory = 0;
487*8d67ca89SAndroid Build Coastguard Worker *backtrace_size = 0;
488*8d67ca89SAndroid Build Coastguard Worker
489*8d67ca89SAndroid Build Coastguard Worker if (!(g_debug->config().options() & BACKTRACE)) {
490*8d67ca89SAndroid Build Coastguard Worker error_log(
491*8d67ca89SAndroid Build Coastguard Worker "get_malloc_leak_info: Allocations not being tracked, to enable "
492*8d67ca89SAndroid Build Coastguard Worker "set the option 'backtrace'.");
493*8d67ca89SAndroid Build Coastguard Worker return;
494*8d67ca89SAndroid Build Coastguard Worker }
495*8d67ca89SAndroid Build Coastguard Worker
496*8d67ca89SAndroid Build Coastguard Worker PointerData::GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
497*8d67ca89SAndroid Build Coastguard Worker }
498*8d67ca89SAndroid Build Coastguard Worker
debug_free_malloc_leak_info(uint8_t * info)499*8d67ca89SAndroid Build Coastguard Worker void debug_free_malloc_leak_info(uint8_t* info) {
500*8d67ca89SAndroid Build Coastguard Worker g_dispatch->free(info);
501*8d67ca89SAndroid Build Coastguard Worker // Purge the memory that was freed since a significant amount of
502*8d67ca89SAndroid Build Coastguard Worker // memory could have been allocated and freed.
503*8d67ca89SAndroid Build Coastguard Worker g_dispatch->mallopt(M_PURGE_ALL, 0);
504*8d67ca89SAndroid Build Coastguard Worker }
505*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_usable_size(void * pointer)506*8d67ca89SAndroid Build Coastguard Worker size_t debug_malloc_usable_size(void* pointer) {
507*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
508*8d67ca89SAndroid Build Coastguard Worker
509*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled() || pointer == nullptr) {
510*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->malloc_usable_size(pointer);
511*8d67ca89SAndroid Build Coastguard Worker }
512*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
513*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
514*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
515*8d67ca89SAndroid Build Coastguard Worker
516*8d67ca89SAndroid Build Coastguard Worker if (!VerifyPointer(pointer, "malloc_usable_size")) {
517*8d67ca89SAndroid Build Coastguard Worker return 0;
518*8d67ca89SAndroid Build Coastguard Worker }
519*8d67ca89SAndroid Build Coastguard Worker
520*8d67ca89SAndroid Build Coastguard Worker return InternalMallocUsableSize(pointer);
521*8d67ca89SAndroid Build Coastguard Worker }
522*8d67ca89SAndroid Build Coastguard Worker
InternalMalloc(size_t size)523*8d67ca89SAndroid Build Coastguard Worker static TimedResult InternalMalloc(size_t size) {
524*8d67ca89SAndroid Build Coastguard Worker uint64_t options = g_debug->config().options();
525*8d67ca89SAndroid Build Coastguard Worker if ((options & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
526*8d67ca89SAndroid Build Coastguard Worker debug_dump_heap(android::base::StringPrintf(
527*8d67ca89SAndroid Build Coastguard Worker "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
528*8d67ca89SAndroid Build Coastguard Worker .c_str());
529*8d67ca89SAndroid Build Coastguard Worker }
530*8d67ca89SAndroid Build Coastguard Worker if (options & LOG_ALLOCATOR_STATS_ON_SIGNAL) {
531*8d67ca89SAndroid Build Coastguard Worker LogAllocatorStats::CheckIfShouldLog();
532*8d67ca89SAndroid Build Coastguard Worker }
533*8d67ca89SAndroid Build Coastguard Worker
534*8d67ca89SAndroid Build Coastguard Worker if (size == 0) {
535*8d67ca89SAndroid Build Coastguard Worker size = 1;
536*8d67ca89SAndroid Build Coastguard Worker }
537*8d67ca89SAndroid Build Coastguard Worker
538*8d67ca89SAndroid Build Coastguard Worker TimedResult result;
539*8d67ca89SAndroid Build Coastguard Worker
540*8d67ca89SAndroid Build Coastguard Worker size_t real_size = size + g_debug->extra_bytes();
541*8d67ca89SAndroid Build Coastguard Worker if (real_size < size) {
542*8d67ca89SAndroid Build Coastguard Worker // Overflow.
543*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
544*8d67ca89SAndroid Build Coastguard Worker result.setValue<void*>(nullptr);
545*8d67ca89SAndroid Build Coastguard Worker return result;
546*8d67ca89SAndroid Build Coastguard Worker }
547*8d67ca89SAndroid Build Coastguard Worker
548*8d67ca89SAndroid Build Coastguard Worker if (size > PointerInfoType::MaxSize()) {
549*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
550*8d67ca89SAndroid Build Coastguard Worker result.setValue<void*>(nullptr);
551*8d67ca89SAndroid Build Coastguard Worker return result;
552*8d67ca89SAndroid Build Coastguard Worker }
553*8d67ca89SAndroid Build Coastguard Worker
554*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
555*8d67ca89SAndroid Build Coastguard Worker result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
556*8d67ca89SAndroid Build Coastguard Worker Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
557*8d67ca89SAndroid Build Coastguard Worker if (header == nullptr) {
558*8d67ca89SAndroid Build Coastguard Worker return result;
559*8d67ca89SAndroid Build Coastguard Worker }
560*8d67ca89SAndroid Build Coastguard Worker result.setValue<void*>(InitHeader(header, header, size));
561*8d67ca89SAndroid Build Coastguard Worker } else {
562*8d67ca89SAndroid Build Coastguard Worker result = TCALL(malloc, real_size);
563*8d67ca89SAndroid Build Coastguard Worker }
564*8d67ca89SAndroid Build Coastguard Worker
565*8d67ca89SAndroid Build Coastguard Worker void* pointer = result.getValue<void*>();
566*8d67ca89SAndroid Build Coastguard Worker
567*8d67ca89SAndroid Build Coastguard Worker if (pointer != nullptr) {
568*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
569*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(pointer, size);
570*8d67ca89SAndroid Build Coastguard Worker }
571*8d67ca89SAndroid Build Coastguard Worker
572*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FILL_ON_ALLOC) {
573*8d67ca89SAndroid Build Coastguard Worker size_t bytes = InternalMallocUsableSize(pointer);
574*8d67ca89SAndroid Build Coastguard Worker size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
575*8d67ca89SAndroid Build Coastguard Worker bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
576*8d67ca89SAndroid Build Coastguard Worker memset(pointer, g_debug->config().fill_alloc_value(), bytes);
577*8d67ca89SAndroid Build Coastguard Worker }
578*8d67ca89SAndroid Build Coastguard Worker }
579*8d67ca89SAndroid Build Coastguard Worker
580*8d67ca89SAndroid Build Coastguard Worker return result;
581*8d67ca89SAndroid Build Coastguard Worker }
582*8d67ca89SAndroid Build Coastguard Worker
debug_malloc(size_t size)583*8d67ca89SAndroid Build Coastguard Worker void* debug_malloc(size_t size) {
584*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
585*8d67ca89SAndroid Build Coastguard Worker
586*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
587*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->malloc(size);
588*8d67ca89SAndroid Build Coastguard Worker }
589*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
590*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
591*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
592*8d67ca89SAndroid Build Coastguard Worker
593*8d67ca89SAndroid Build Coastguard Worker TimedResult result = InternalMalloc(size);
594*8d67ca89SAndroid Build Coastguard Worker
595*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
596*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(
597*8d67ca89SAndroid Build Coastguard Worker memory_trace::Entry{.tid = gettid(),
598*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::MALLOC,
599*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(result.getValue<void*>()),
600*8d67ca89SAndroid Build Coastguard Worker .size = size,
601*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
602*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
603*8d67ca89SAndroid Build Coastguard Worker }
604*8d67ca89SAndroid Build Coastguard Worker
605*8d67ca89SAndroid Build Coastguard Worker return result.getValue<void*>();
606*8d67ca89SAndroid Build Coastguard Worker }
607*8d67ca89SAndroid Build Coastguard Worker
InternalFree(void * pointer)608*8d67ca89SAndroid Build Coastguard Worker static TimedResult InternalFree(void* pointer) {
609*8d67ca89SAndroid Build Coastguard Worker uint64_t options = g_debug->config().options();
610*8d67ca89SAndroid Build Coastguard Worker if ((options & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
611*8d67ca89SAndroid Build Coastguard Worker debug_dump_heap(android::base::StringPrintf(
612*8d67ca89SAndroid Build Coastguard Worker "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
613*8d67ca89SAndroid Build Coastguard Worker .c_str());
614*8d67ca89SAndroid Build Coastguard Worker }
615*8d67ca89SAndroid Build Coastguard Worker if (options & LOG_ALLOCATOR_STATS_ON_SIGNAL) {
616*8d67ca89SAndroid Build Coastguard Worker LogAllocatorStats::CheckIfShouldLog();
617*8d67ca89SAndroid Build Coastguard Worker }
618*8d67ca89SAndroid Build Coastguard Worker
619*8d67ca89SAndroid Build Coastguard Worker void* free_pointer = pointer;
620*8d67ca89SAndroid Build Coastguard Worker size_t bytes;
621*8d67ca89SAndroid Build Coastguard Worker Header* header;
622*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
623*8d67ca89SAndroid Build Coastguard Worker header = g_debug->GetHeader(pointer);
624*8d67ca89SAndroid Build Coastguard Worker free_pointer = header->orig_pointer;
625*8d67ca89SAndroid Build Coastguard Worker
626*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FRONT_GUARD) {
627*8d67ca89SAndroid Build Coastguard Worker if (!g_debug->front_guard->Valid(header)) {
628*8d67ca89SAndroid Build Coastguard Worker g_debug->front_guard->LogFailure(header);
629*8d67ca89SAndroid Build Coastguard Worker }
630*8d67ca89SAndroid Build Coastguard Worker }
631*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & REAR_GUARD) {
632*8d67ca89SAndroid Build Coastguard Worker if (!g_debug->rear_guard->Valid(header)) {
633*8d67ca89SAndroid Build Coastguard Worker g_debug->rear_guard->LogFailure(header);
634*8d67ca89SAndroid Build Coastguard Worker }
635*8d67ca89SAndroid Build Coastguard Worker }
636*8d67ca89SAndroid Build Coastguard Worker
637*8d67ca89SAndroid Build Coastguard Worker header->tag = DEBUG_FREE_TAG;
638*8d67ca89SAndroid Build Coastguard Worker
639*8d67ca89SAndroid Build Coastguard Worker bytes = header->usable_size;
640*8d67ca89SAndroid Build Coastguard Worker } else {
641*8d67ca89SAndroid Build Coastguard Worker bytes = g_dispatch->malloc_usable_size(pointer);
642*8d67ca89SAndroid Build Coastguard Worker }
643*8d67ca89SAndroid Build Coastguard Worker
644*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FILL_ON_FREE) {
645*8d67ca89SAndroid Build Coastguard Worker size_t fill_bytes = g_debug->config().fill_on_free_bytes();
646*8d67ca89SAndroid Build Coastguard Worker fill_bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
647*8d67ca89SAndroid Build Coastguard Worker memset(pointer, g_debug->config().fill_free_value(), fill_bytes);
648*8d67ca89SAndroid Build Coastguard Worker }
649*8d67ca89SAndroid Build Coastguard Worker
650*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
651*8d67ca89SAndroid Build Coastguard Worker PointerData::Remove(pointer);
652*8d67ca89SAndroid Build Coastguard Worker }
653*8d67ca89SAndroid Build Coastguard Worker
654*8d67ca89SAndroid Build Coastguard Worker TimedResult result;
655*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FREE_TRACK) {
656*8d67ca89SAndroid Build Coastguard Worker // Do not add the allocation until we are done modifying the pointer
657*8d67ca89SAndroid Build Coastguard Worker // itself. This avoids a race if a lot of threads are all doing
658*8d67ca89SAndroid Build Coastguard Worker // frees at the same time and we wind up trying to really free this
659*8d67ca89SAndroid Build Coastguard Worker // pointer from another thread, while still trying to free it in
660*8d67ca89SAndroid Build Coastguard Worker // this function.
661*8d67ca89SAndroid Build Coastguard Worker pointer = PointerData::AddFreed(pointer, bytes);
662*8d67ca89SAndroid Build Coastguard Worker if (pointer != nullptr && g_debug->HeaderEnabled()) {
663*8d67ca89SAndroid Build Coastguard Worker pointer = g_debug->GetHeader(pointer)->orig_pointer;
664*8d67ca89SAndroid Build Coastguard Worker }
665*8d67ca89SAndroid Build Coastguard Worker result = TCALLVOID(free, pointer);
666*8d67ca89SAndroid Build Coastguard Worker } else {
667*8d67ca89SAndroid Build Coastguard Worker result = TCALLVOID(free, free_pointer);
668*8d67ca89SAndroid Build Coastguard Worker }
669*8d67ca89SAndroid Build Coastguard Worker
670*8d67ca89SAndroid Build Coastguard Worker return result;
671*8d67ca89SAndroid Build Coastguard Worker }
672*8d67ca89SAndroid Build Coastguard Worker
debug_free(void * pointer)673*8d67ca89SAndroid Build Coastguard Worker void debug_free(void* pointer) {
674*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
675*8d67ca89SAndroid Build Coastguard Worker
676*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled() || pointer == nullptr) {
677*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->free(pointer);
678*8d67ca89SAndroid Build Coastguard Worker }
679*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
680*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
681*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
682*8d67ca89SAndroid Build Coastguard Worker
683*8d67ca89SAndroid Build Coastguard Worker if (!VerifyPointer(pointer, "free")) {
684*8d67ca89SAndroid Build Coastguard Worker return;
685*8d67ca89SAndroid Build Coastguard Worker }
686*8d67ca89SAndroid Build Coastguard Worker
687*8d67ca89SAndroid Build Coastguard Worker TimedResult result = InternalFree(pointer);
688*8d67ca89SAndroid Build Coastguard Worker
689*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
690*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
691*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::FREE,
692*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(pointer),
693*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
694*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
695*8d67ca89SAndroid Build Coastguard Worker }
696*8d67ca89SAndroid Build Coastguard Worker }
697*8d67ca89SAndroid Build Coastguard Worker
debug_memalign(size_t alignment,size_t bytes)698*8d67ca89SAndroid Build Coastguard Worker void* debug_memalign(size_t alignment, size_t bytes) {
699*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
700*8d67ca89SAndroid Build Coastguard Worker
701*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
702*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->memalign(alignment, bytes);
703*8d67ca89SAndroid Build Coastguard Worker }
704*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
705*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
706*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
707*8d67ca89SAndroid Build Coastguard Worker
708*8d67ca89SAndroid Build Coastguard Worker if (bytes == 0) {
709*8d67ca89SAndroid Build Coastguard Worker bytes = 1;
710*8d67ca89SAndroid Build Coastguard Worker }
711*8d67ca89SAndroid Build Coastguard Worker
712*8d67ca89SAndroid Build Coastguard Worker if (bytes > PointerInfoType::MaxSize()) {
713*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
714*8d67ca89SAndroid Build Coastguard Worker return nullptr;
715*8d67ca89SAndroid Build Coastguard Worker }
716*8d67ca89SAndroid Build Coastguard Worker
717*8d67ca89SAndroid Build Coastguard Worker TimedResult result;
718*8d67ca89SAndroid Build Coastguard Worker void* pointer;
719*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
720*8d67ca89SAndroid Build Coastguard Worker // Make the alignment a power of two.
721*8d67ca89SAndroid Build Coastguard Worker if (!powerof2(alignment)) {
722*8d67ca89SAndroid Build Coastguard Worker alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
723*8d67ca89SAndroid Build Coastguard Worker }
724*8d67ca89SAndroid Build Coastguard Worker // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee
725*8d67ca89SAndroid Build Coastguard Worker // that the header is aligned properly.
726*8d67ca89SAndroid Build Coastguard Worker if (alignment < MINIMUM_ALIGNMENT_BYTES) {
727*8d67ca89SAndroid Build Coastguard Worker alignment = MINIMUM_ALIGNMENT_BYTES;
728*8d67ca89SAndroid Build Coastguard Worker }
729*8d67ca89SAndroid Build Coastguard Worker
730*8d67ca89SAndroid Build Coastguard Worker // We don't have any idea what the natural alignment of
731*8d67ca89SAndroid Build Coastguard Worker // the underlying native allocator is, so we always need to
732*8d67ca89SAndroid Build Coastguard Worker // over allocate.
733*8d67ca89SAndroid Build Coastguard Worker size_t real_size = alignment + bytes + g_debug->extra_bytes();
734*8d67ca89SAndroid Build Coastguard Worker if (real_size < bytes) {
735*8d67ca89SAndroid Build Coastguard Worker // Overflow.
736*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
737*8d67ca89SAndroid Build Coastguard Worker return nullptr;
738*8d67ca89SAndroid Build Coastguard Worker }
739*8d67ca89SAndroid Build Coastguard Worker
740*8d67ca89SAndroid Build Coastguard Worker result = TCALL(malloc, real_size);
741*8d67ca89SAndroid Build Coastguard Worker pointer = result.getValue<void*>();
742*8d67ca89SAndroid Build Coastguard Worker if (pointer == nullptr) {
743*8d67ca89SAndroid Build Coastguard Worker return nullptr;
744*8d67ca89SAndroid Build Coastguard Worker }
745*8d67ca89SAndroid Build Coastguard Worker
746*8d67ca89SAndroid Build Coastguard Worker uintptr_t value = reinterpret_cast<uintptr_t>(pointer) + g_debug->pointer_offset();
747*8d67ca89SAndroid Build Coastguard Worker // Now align the pointer.
748*8d67ca89SAndroid Build Coastguard Worker value += (-value % alignment);
749*8d67ca89SAndroid Build Coastguard Worker
750*8d67ca89SAndroid Build Coastguard Worker Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
751*8d67ca89SAndroid Build Coastguard Worker // Don't need to update `result` here because we only need the timestamps.
752*8d67ca89SAndroid Build Coastguard Worker pointer = InitHeader(header, pointer, bytes);
753*8d67ca89SAndroid Build Coastguard Worker } else {
754*8d67ca89SAndroid Build Coastguard Worker size_t real_size = bytes + g_debug->extra_bytes();
755*8d67ca89SAndroid Build Coastguard Worker if (real_size < bytes) {
756*8d67ca89SAndroid Build Coastguard Worker // Overflow.
757*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
758*8d67ca89SAndroid Build Coastguard Worker return nullptr;
759*8d67ca89SAndroid Build Coastguard Worker }
760*8d67ca89SAndroid Build Coastguard Worker result = TCALL(memalign, alignment, real_size);
761*8d67ca89SAndroid Build Coastguard Worker pointer = result.getValue<void*>();
762*8d67ca89SAndroid Build Coastguard Worker }
763*8d67ca89SAndroid Build Coastguard Worker
764*8d67ca89SAndroid Build Coastguard Worker if (pointer != nullptr) {
765*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
766*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(pointer, bytes);
767*8d67ca89SAndroid Build Coastguard Worker }
768*8d67ca89SAndroid Build Coastguard Worker
769*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FILL_ON_ALLOC) {
770*8d67ca89SAndroid Build Coastguard Worker size_t bytes = InternalMallocUsableSize(pointer);
771*8d67ca89SAndroid Build Coastguard Worker size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
772*8d67ca89SAndroid Build Coastguard Worker bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
773*8d67ca89SAndroid Build Coastguard Worker memset(pointer, g_debug->config().fill_alloc_value(), bytes);
774*8d67ca89SAndroid Build Coastguard Worker }
775*8d67ca89SAndroid Build Coastguard Worker
776*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
777*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
778*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::MEMALIGN,
779*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(pointer),
780*8d67ca89SAndroid Build Coastguard Worker .size = bytes,
781*8d67ca89SAndroid Build Coastguard Worker .u.align = alignment,
782*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
783*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
784*8d67ca89SAndroid Build Coastguard Worker }
785*8d67ca89SAndroid Build Coastguard Worker }
786*8d67ca89SAndroid Build Coastguard Worker
787*8d67ca89SAndroid Build Coastguard Worker return pointer;
788*8d67ca89SAndroid Build Coastguard Worker }
789*8d67ca89SAndroid Build Coastguard Worker
debug_realloc(void * pointer,size_t bytes)790*8d67ca89SAndroid Build Coastguard Worker void* debug_realloc(void* pointer, size_t bytes) {
791*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
792*8d67ca89SAndroid Build Coastguard Worker
793*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
794*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->realloc(pointer, bytes);
795*8d67ca89SAndroid Build Coastguard Worker }
796*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
797*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
798*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
799*8d67ca89SAndroid Build Coastguard Worker
800*8d67ca89SAndroid Build Coastguard Worker if (pointer == nullptr) {
801*8d67ca89SAndroid Build Coastguard Worker TimedResult result = InternalMalloc(bytes);
802*8d67ca89SAndroid Build Coastguard Worker pointer = result.getValue<void*>();
803*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
804*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
805*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::REALLOC,
806*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(pointer),
807*8d67ca89SAndroid Build Coastguard Worker .size = bytes,
808*8d67ca89SAndroid Build Coastguard Worker .u.old_ptr = 0,
809*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
810*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
811*8d67ca89SAndroid Build Coastguard Worker }
812*8d67ca89SAndroid Build Coastguard Worker return pointer;
813*8d67ca89SAndroid Build Coastguard Worker }
814*8d67ca89SAndroid Build Coastguard Worker
815*8d67ca89SAndroid Build Coastguard Worker if (!VerifyPointer(pointer, "realloc")) {
816*8d67ca89SAndroid Build Coastguard Worker return nullptr;
817*8d67ca89SAndroid Build Coastguard Worker }
818*8d67ca89SAndroid Build Coastguard Worker
819*8d67ca89SAndroid Build Coastguard Worker if (bytes == 0) {
820*8d67ca89SAndroid Build Coastguard Worker TimedResult result = InternalFree(pointer);
821*8d67ca89SAndroid Build Coastguard Worker
822*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
823*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(
824*8d67ca89SAndroid Build Coastguard Worker memory_trace::Entry{.tid = gettid(),
825*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::REALLOC,
826*8d67ca89SAndroid Build Coastguard Worker .ptr = 0,
827*8d67ca89SAndroid Build Coastguard Worker .size = 0,
828*8d67ca89SAndroid Build Coastguard Worker .u.old_ptr = reinterpret_cast<uint64_t>(pointer),
829*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
830*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
831*8d67ca89SAndroid Build Coastguard Worker }
832*8d67ca89SAndroid Build Coastguard Worker
833*8d67ca89SAndroid Build Coastguard Worker return nullptr;
834*8d67ca89SAndroid Build Coastguard Worker }
835*8d67ca89SAndroid Build Coastguard Worker
836*8d67ca89SAndroid Build Coastguard Worker size_t real_size = bytes;
837*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & EXPAND_ALLOC) {
838*8d67ca89SAndroid Build Coastguard Worker real_size += g_debug->config().expand_alloc_bytes();
839*8d67ca89SAndroid Build Coastguard Worker if (real_size < bytes) {
840*8d67ca89SAndroid Build Coastguard Worker // Overflow.
841*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
842*8d67ca89SAndroid Build Coastguard Worker return nullptr;
843*8d67ca89SAndroid Build Coastguard Worker }
844*8d67ca89SAndroid Build Coastguard Worker }
845*8d67ca89SAndroid Build Coastguard Worker
846*8d67ca89SAndroid Build Coastguard Worker if (bytes > PointerInfoType::MaxSize()) {
847*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
848*8d67ca89SAndroid Build Coastguard Worker return nullptr;
849*8d67ca89SAndroid Build Coastguard Worker }
850*8d67ca89SAndroid Build Coastguard Worker
851*8d67ca89SAndroid Build Coastguard Worker TimedResult result;
852*8d67ca89SAndroid Build Coastguard Worker void* new_pointer;
853*8d67ca89SAndroid Build Coastguard Worker size_t prev_size;
854*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
855*8d67ca89SAndroid Build Coastguard Worker // Same size, do nothing.
856*8d67ca89SAndroid Build Coastguard Worker Header* header = g_debug->GetHeader(pointer);
857*8d67ca89SAndroid Build Coastguard Worker if (real_size == header->size) {
858*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
859*8d67ca89SAndroid Build Coastguard Worker // Remove and re-add so that the backtrace is updated.
860*8d67ca89SAndroid Build Coastguard Worker PointerData::Remove(pointer);
861*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(pointer, real_size);
862*8d67ca89SAndroid Build Coastguard Worker }
863*8d67ca89SAndroid Build Coastguard Worker return pointer;
864*8d67ca89SAndroid Build Coastguard Worker }
865*8d67ca89SAndroid Build Coastguard Worker
866*8d67ca89SAndroid Build Coastguard Worker // Allocation is shrinking.
867*8d67ca89SAndroid Build Coastguard Worker if (real_size < header->usable_size) {
868*8d67ca89SAndroid Build Coastguard Worker header->size = real_size;
869*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & REAR_GUARD) {
870*8d67ca89SAndroid Build Coastguard Worker // Don't bother allocating a smaller pointer in this case, simply
871*8d67ca89SAndroid Build Coastguard Worker // change the header usable_size and reset the rear guard.
872*8d67ca89SAndroid Build Coastguard Worker header->usable_size = header->size;
873*8d67ca89SAndroid Build Coastguard Worker memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
874*8d67ca89SAndroid Build Coastguard Worker g_debug->config().rear_guard_bytes());
875*8d67ca89SAndroid Build Coastguard Worker }
876*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
877*8d67ca89SAndroid Build Coastguard Worker // Remove and re-add so that the backtrace is updated.
878*8d67ca89SAndroid Build Coastguard Worker PointerData::Remove(pointer);
879*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(pointer, real_size);
880*8d67ca89SAndroid Build Coastguard Worker }
881*8d67ca89SAndroid Build Coastguard Worker return pointer;
882*8d67ca89SAndroid Build Coastguard Worker }
883*8d67ca89SAndroid Build Coastguard Worker
884*8d67ca89SAndroid Build Coastguard Worker // Allocate the new size.
885*8d67ca89SAndroid Build Coastguard Worker result = InternalMalloc(bytes);
886*8d67ca89SAndroid Build Coastguard Worker new_pointer = result.getValue<void*>();
887*8d67ca89SAndroid Build Coastguard Worker if (new_pointer == nullptr) {
888*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
889*8d67ca89SAndroid Build Coastguard Worker return nullptr;
890*8d67ca89SAndroid Build Coastguard Worker }
891*8d67ca89SAndroid Build Coastguard Worker
892*8d67ca89SAndroid Build Coastguard Worker prev_size = header->usable_size;
893*8d67ca89SAndroid Build Coastguard Worker memcpy(new_pointer, pointer, prev_size);
894*8d67ca89SAndroid Build Coastguard Worker TimedResult free_time = InternalFree(pointer);
895*8d67ca89SAndroid Build Coastguard Worker // `realloc` is split into two steps, update the end time to the finish time
896*8d67ca89SAndroid Build Coastguard Worker // of the second operation.
897*8d67ca89SAndroid Build Coastguard Worker result.SetEndTimeNS(free_time.GetEndTimeNS());
898*8d67ca89SAndroid Build Coastguard Worker } else {
899*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
900*8d67ca89SAndroid Build Coastguard Worker PointerData::Remove(pointer);
901*8d67ca89SAndroid Build Coastguard Worker }
902*8d67ca89SAndroid Build Coastguard Worker
903*8d67ca89SAndroid Build Coastguard Worker prev_size = g_dispatch->malloc_usable_size(pointer);
904*8d67ca89SAndroid Build Coastguard Worker result = TCALL(realloc, pointer, real_size);
905*8d67ca89SAndroid Build Coastguard Worker new_pointer = result.getValue<void*>();
906*8d67ca89SAndroid Build Coastguard Worker if (new_pointer == nullptr) {
907*8d67ca89SAndroid Build Coastguard Worker return nullptr;
908*8d67ca89SAndroid Build Coastguard Worker }
909*8d67ca89SAndroid Build Coastguard Worker
910*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
911*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(new_pointer, real_size);
912*8d67ca89SAndroid Build Coastguard Worker }
913*8d67ca89SAndroid Build Coastguard Worker }
914*8d67ca89SAndroid Build Coastguard Worker
915*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & FILL_ON_ALLOC) {
916*8d67ca89SAndroid Build Coastguard Worker size_t bytes = InternalMallocUsableSize(new_pointer);
917*8d67ca89SAndroid Build Coastguard Worker if (bytes > g_debug->config().fill_on_alloc_bytes()) {
918*8d67ca89SAndroid Build Coastguard Worker bytes = g_debug->config().fill_on_alloc_bytes();
919*8d67ca89SAndroid Build Coastguard Worker }
920*8d67ca89SAndroid Build Coastguard Worker if (bytes > prev_size) {
921*8d67ca89SAndroid Build Coastguard Worker memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
922*8d67ca89SAndroid Build Coastguard Worker g_debug->config().fill_alloc_value(), bytes - prev_size);
923*8d67ca89SAndroid Build Coastguard Worker }
924*8d67ca89SAndroid Build Coastguard Worker }
925*8d67ca89SAndroid Build Coastguard Worker
926*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
927*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
928*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::REALLOC,
929*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(new_pointer),
930*8d67ca89SAndroid Build Coastguard Worker .size = bytes,
931*8d67ca89SAndroid Build Coastguard Worker .u.old_ptr = reinterpret_cast<uint64_t>(pointer),
932*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
933*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
934*8d67ca89SAndroid Build Coastguard Worker }
935*8d67ca89SAndroid Build Coastguard Worker
936*8d67ca89SAndroid Build Coastguard Worker return new_pointer;
937*8d67ca89SAndroid Build Coastguard Worker }
938*8d67ca89SAndroid Build Coastguard Worker
debug_calloc(size_t nmemb,size_t bytes)939*8d67ca89SAndroid Build Coastguard Worker void* debug_calloc(size_t nmemb, size_t bytes) {
940*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
941*8d67ca89SAndroid Build Coastguard Worker
942*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
943*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->calloc(nmemb, bytes);
944*8d67ca89SAndroid Build Coastguard Worker }
945*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
946*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
947*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
948*8d67ca89SAndroid Build Coastguard Worker
949*8d67ca89SAndroid Build Coastguard Worker size_t size;
950*8d67ca89SAndroid Build Coastguard Worker if (__builtin_mul_overflow(nmemb, bytes, &size)) {
951*8d67ca89SAndroid Build Coastguard Worker // Overflow
952*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
953*8d67ca89SAndroid Build Coastguard Worker return nullptr;
954*8d67ca89SAndroid Build Coastguard Worker }
955*8d67ca89SAndroid Build Coastguard Worker
956*8d67ca89SAndroid Build Coastguard Worker if (size == 0) {
957*8d67ca89SAndroid Build Coastguard Worker size = 1;
958*8d67ca89SAndroid Build Coastguard Worker }
959*8d67ca89SAndroid Build Coastguard Worker
960*8d67ca89SAndroid Build Coastguard Worker size_t real_size;
961*8d67ca89SAndroid Build Coastguard Worker if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
962*8d67ca89SAndroid Build Coastguard Worker // Overflow.
963*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
964*8d67ca89SAndroid Build Coastguard Worker return nullptr;
965*8d67ca89SAndroid Build Coastguard Worker }
966*8d67ca89SAndroid Build Coastguard Worker
967*8d67ca89SAndroid Build Coastguard Worker if (real_size > PointerInfoType::MaxSize()) {
968*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
969*8d67ca89SAndroid Build Coastguard Worker return nullptr;
970*8d67ca89SAndroid Build Coastguard Worker }
971*8d67ca89SAndroid Build Coastguard Worker
972*8d67ca89SAndroid Build Coastguard Worker void* pointer;
973*8d67ca89SAndroid Build Coastguard Worker TimedResult result;
974*8d67ca89SAndroid Build Coastguard Worker if (g_debug->HeaderEnabled()) {
975*8d67ca89SAndroid Build Coastguard Worker // Need to guarantee the alignment of the header.
976*8d67ca89SAndroid Build Coastguard Worker result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
977*8d67ca89SAndroid Build Coastguard Worker Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
978*8d67ca89SAndroid Build Coastguard Worker if (header == nullptr) {
979*8d67ca89SAndroid Build Coastguard Worker return nullptr;
980*8d67ca89SAndroid Build Coastguard Worker }
981*8d67ca89SAndroid Build Coastguard Worker memset(header, 0, g_dispatch->malloc_usable_size(header));
982*8d67ca89SAndroid Build Coastguard Worker pointer = InitHeader(header, header, size);
983*8d67ca89SAndroid Build Coastguard Worker } else {
984*8d67ca89SAndroid Build Coastguard Worker result = TCALL(calloc, 1, real_size);
985*8d67ca89SAndroid Build Coastguard Worker pointer = result.getValue<void*>();
986*8d67ca89SAndroid Build Coastguard Worker }
987*8d67ca89SAndroid Build Coastguard Worker
988*8d67ca89SAndroid Build Coastguard Worker if (g_debug->config().options() & RECORD_ALLOCS) {
989*8d67ca89SAndroid Build Coastguard Worker g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
990*8d67ca89SAndroid Build Coastguard Worker .type = memory_trace::CALLOC,
991*8d67ca89SAndroid Build Coastguard Worker .ptr = reinterpret_cast<uint64_t>(pointer),
992*8d67ca89SAndroid Build Coastguard Worker .size = bytes,
993*8d67ca89SAndroid Build Coastguard Worker .u.n_elements = nmemb,
994*8d67ca89SAndroid Build Coastguard Worker .start_ns = result.GetStartTimeNS(),
995*8d67ca89SAndroid Build Coastguard Worker .end_ns = result.GetEndTimeNS()});
996*8d67ca89SAndroid Build Coastguard Worker }
997*8d67ca89SAndroid Build Coastguard Worker
998*8d67ca89SAndroid Build Coastguard Worker if (pointer != nullptr && g_debug->TrackPointers()) {
999*8d67ca89SAndroid Build Coastguard Worker PointerData::Add(pointer, size);
1000*8d67ca89SAndroid Build Coastguard Worker }
1001*8d67ca89SAndroid Build Coastguard Worker return pointer;
1002*8d67ca89SAndroid Build Coastguard Worker }
1003*8d67ca89SAndroid Build Coastguard Worker
debug_mallinfo()1004*8d67ca89SAndroid Build Coastguard Worker struct mallinfo debug_mallinfo() {
1005*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->mallinfo();
1006*8d67ca89SAndroid Build Coastguard Worker }
1007*8d67ca89SAndroid Build Coastguard Worker
debug_mallopt(int param,int value)1008*8d67ca89SAndroid Build Coastguard Worker int debug_mallopt(int param, int value) {
1009*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->mallopt(param, value);
1010*8d67ca89SAndroid Build Coastguard Worker }
1011*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_info(int options,FILE * fp)1012*8d67ca89SAndroid Build Coastguard Worker int debug_malloc_info(int options, FILE* fp) {
1013*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled() || !g_debug->TrackPointers()) {
1014*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->malloc_info(options, fp);
1015*8d67ca89SAndroid Build Coastguard Worker }
1016*8d67ca89SAndroid Build Coastguard Worker
1017*8d67ca89SAndroid Build Coastguard Worker // Make sure any pending output is written to the file.
1018*8d67ca89SAndroid Build Coastguard Worker fflush(fp);
1019*8d67ca89SAndroid Build Coastguard Worker
1020*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1021*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
1022*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
1023*8d67ca89SAndroid Build Coastguard Worker
1024*8d67ca89SAndroid Build Coastguard Worker // Avoid any issues where allocations are made that will be freed
1025*8d67ca89SAndroid Build Coastguard Worker // in the fclose.
1026*8d67ca89SAndroid Build Coastguard Worker int fd = fileno(fp);
1027*8d67ca89SAndroid Build Coastguard Worker MallocXmlElem root(fd, "malloc", "version=\"debug-malloc-1\"");
1028*8d67ca89SAndroid Build Coastguard Worker std::vector<ListInfoType> list;
1029*8d67ca89SAndroid Build Coastguard Worker PointerData::GetAllocList(&list);
1030*8d67ca89SAndroid Build Coastguard Worker
1031*8d67ca89SAndroid Build Coastguard Worker size_t alloc_num = 0;
1032*8d67ca89SAndroid Build Coastguard Worker for (size_t i = 0; i < list.size(); i++) {
1033*8d67ca89SAndroid Build Coastguard Worker MallocXmlElem alloc(fd, "allocation", "nr=\"%zu\"", alloc_num);
1034*8d67ca89SAndroid Build Coastguard Worker
1035*8d67ca89SAndroid Build Coastguard Worker size_t total = 1;
1036*8d67ca89SAndroid Build Coastguard Worker size_t size = list[i].size;
1037*8d67ca89SAndroid Build Coastguard Worker while (i < list.size() - 1 && list[i + 1].size == size) {
1038*8d67ca89SAndroid Build Coastguard Worker i++;
1039*8d67ca89SAndroid Build Coastguard Worker total++;
1040*8d67ca89SAndroid Build Coastguard Worker }
1041*8d67ca89SAndroid Build Coastguard Worker MallocXmlElem(fd, "size").Contents("%zu", list[i].size);
1042*8d67ca89SAndroid Build Coastguard Worker MallocXmlElem(fd, "total").Contents("%zu", total);
1043*8d67ca89SAndroid Build Coastguard Worker alloc_num++;
1044*8d67ca89SAndroid Build Coastguard Worker }
1045*8d67ca89SAndroid Build Coastguard Worker return 0;
1046*8d67ca89SAndroid Build Coastguard Worker }
1047*8d67ca89SAndroid Build Coastguard Worker
debug_aligned_alloc(size_t alignment,size_t size)1048*8d67ca89SAndroid Build Coastguard Worker void* debug_aligned_alloc(size_t alignment, size_t size) {
1049*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
1050*8d67ca89SAndroid Build Coastguard Worker
1051*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
1052*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->aligned_alloc(alignment, size);
1053*8d67ca89SAndroid Build Coastguard Worker }
1054*8d67ca89SAndroid Build Coastguard Worker if (!powerof2(alignment) || (size % alignment) != 0) {
1055*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
1056*8d67ca89SAndroid Build Coastguard Worker return nullptr;
1057*8d67ca89SAndroid Build Coastguard Worker }
1058*8d67ca89SAndroid Build Coastguard Worker return debug_memalign(alignment, size);
1059*8d67ca89SAndroid Build Coastguard Worker }
1060*8d67ca89SAndroid Build Coastguard Worker
debug_posix_memalign(void ** memptr,size_t alignment,size_t size)1061*8d67ca89SAndroid Build Coastguard Worker int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
1062*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
1063*8d67ca89SAndroid Build Coastguard Worker
1064*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
1065*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->posix_memalign(memptr, alignment, size);
1066*8d67ca89SAndroid Build Coastguard Worker }
1067*8d67ca89SAndroid Build Coastguard Worker
1068*8d67ca89SAndroid Build Coastguard Worker if (alignment < sizeof(void*) || !powerof2(alignment)) {
1069*8d67ca89SAndroid Build Coastguard Worker return EINVAL;
1070*8d67ca89SAndroid Build Coastguard Worker }
1071*8d67ca89SAndroid Build Coastguard Worker int saved_errno = errno;
1072*8d67ca89SAndroid Build Coastguard Worker *memptr = debug_memalign(alignment, size);
1073*8d67ca89SAndroid Build Coastguard Worker errno = saved_errno;
1074*8d67ca89SAndroid Build Coastguard Worker return (*memptr != nullptr) ? 0 : ENOMEM;
1075*8d67ca89SAndroid Build Coastguard Worker }
1076*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_iterate(uintptr_t base,size_t size,void (* callback)(uintptr_t,size_t,void *),void * arg)1077*8d67ca89SAndroid Build Coastguard Worker int debug_malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*),
1078*8d67ca89SAndroid Build Coastguard Worker void* arg) {
1079*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1080*8d67ca89SAndroid Build Coastguard Worker if (g_debug->TrackPointers()) {
1081*8d67ca89SAndroid Build Coastguard Worker PointerData::IteratePointers([&callback, &arg](uintptr_t pointer) {
1082*8d67ca89SAndroid Build Coastguard Worker callback(pointer, InternalMallocUsableSize(reinterpret_cast<void*>(pointer)), arg);
1083*8d67ca89SAndroid Build Coastguard Worker });
1084*8d67ca89SAndroid Build Coastguard Worker return 0;
1085*8d67ca89SAndroid Build Coastguard Worker }
1086*8d67ca89SAndroid Build Coastguard Worker
1087*8d67ca89SAndroid Build Coastguard Worker // An option that adds a header will add pointer tracking, so no need to
1088*8d67ca89SAndroid Build Coastguard Worker // check if headers are enabled.
1089*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->malloc_iterate(base, size, callback, arg);
1090*8d67ca89SAndroid Build Coastguard Worker }
1091*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_disable()1092*8d67ca89SAndroid Build Coastguard Worker void debug_malloc_disable() {
1093*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1094*8d67ca89SAndroid Build Coastguard Worker g_dispatch->malloc_disable();
1095*8d67ca89SAndroid Build Coastguard Worker if (g_debug->pointer) {
1096*8d67ca89SAndroid Build Coastguard Worker g_debug->pointer->PrepareFork();
1097*8d67ca89SAndroid Build Coastguard Worker }
1098*8d67ca89SAndroid Build Coastguard Worker }
1099*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_enable()1100*8d67ca89SAndroid Build Coastguard Worker void debug_malloc_enable() {
1101*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1102*8d67ca89SAndroid Build Coastguard Worker if (g_debug->pointer) {
1103*8d67ca89SAndroid Build Coastguard Worker g_debug->pointer->PostForkParent();
1104*8d67ca89SAndroid Build Coastguard Worker }
1105*8d67ca89SAndroid Build Coastguard Worker g_dispatch->malloc_enable();
1106*8d67ca89SAndroid Build Coastguard Worker }
1107*8d67ca89SAndroid Build Coastguard Worker
debug_malloc_backtrace(void * pointer,uintptr_t * frames,size_t max_frames)1108*8d67ca89SAndroid Build Coastguard Worker ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t max_frames) {
1109*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled() || pointer == nullptr) {
1110*8d67ca89SAndroid Build Coastguard Worker return 0;
1111*8d67ca89SAndroid Build Coastguard Worker }
1112*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1113*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
1114*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
1115*8d67ca89SAndroid Build Coastguard Worker
1116*8d67ca89SAndroid Build Coastguard Worker if (!(g_debug->config().options() & BACKTRACE)) {
1117*8d67ca89SAndroid Build Coastguard Worker return 0;
1118*8d67ca89SAndroid Build Coastguard Worker }
1119*8d67ca89SAndroid Build Coastguard Worker pointer = UntagPointer(pointer);
1120*8d67ca89SAndroid Build Coastguard Worker return PointerData::GetFrames(pointer, frames, max_frames);
1121*8d67ca89SAndroid Build Coastguard Worker }
1122*8d67ca89SAndroid Build Coastguard Worker
1123*8d67ca89SAndroid Build Coastguard Worker #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
debug_pvalloc(size_t bytes)1124*8d67ca89SAndroid Build Coastguard Worker void* debug_pvalloc(size_t bytes) {
1125*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
1126*8d67ca89SAndroid Build Coastguard Worker
1127*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
1128*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->pvalloc(bytes);
1129*8d67ca89SAndroid Build Coastguard Worker }
1130*8d67ca89SAndroid Build Coastguard Worker
1131*8d67ca89SAndroid Build Coastguard Worker size_t pagesize = getpagesize();
1132*8d67ca89SAndroid Build Coastguard Worker size_t size = __BIONIC_ALIGN(bytes, pagesize);
1133*8d67ca89SAndroid Build Coastguard Worker if (size < bytes) {
1134*8d67ca89SAndroid Build Coastguard Worker // Overflow
1135*8d67ca89SAndroid Build Coastguard Worker errno = ENOMEM;
1136*8d67ca89SAndroid Build Coastguard Worker return nullptr;
1137*8d67ca89SAndroid Build Coastguard Worker }
1138*8d67ca89SAndroid Build Coastguard Worker return debug_memalign(pagesize, size);
1139*8d67ca89SAndroid Build Coastguard Worker }
1140*8d67ca89SAndroid Build Coastguard Worker
debug_valloc(size_t size)1141*8d67ca89SAndroid Build Coastguard Worker void* debug_valloc(size_t size) {
1142*8d67ca89SAndroid Build Coastguard Worker Unreachable::CheckIfRequested(g_debug->config());
1143*8d67ca89SAndroid Build Coastguard Worker
1144*8d67ca89SAndroid Build Coastguard Worker if (DebugCallsDisabled()) {
1145*8d67ca89SAndroid Build Coastguard Worker return g_dispatch->valloc(size);
1146*8d67ca89SAndroid Build Coastguard Worker }
1147*8d67ca89SAndroid Build Coastguard Worker return debug_memalign(getpagesize(), size);
1148*8d67ca89SAndroid Build Coastguard Worker }
1149*8d67ca89SAndroid Build Coastguard Worker #endif
1150*8d67ca89SAndroid Build Coastguard Worker
1151*8d67ca89SAndroid Build Coastguard Worker static std::mutex g_dump_lock;
1152*8d67ca89SAndroid Build Coastguard Worker
write_dump(int fd)1153*8d67ca89SAndroid Build Coastguard Worker static void write_dump(int fd) {
1154*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "Android Native Heap Dump v1.2\n\n");
1155*8d67ca89SAndroid Build Coastguard Worker
1156*8d67ca89SAndroid Build Coastguard Worker std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown");
1157*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "Build fingerprint: '%s'\n\n", fingerprint.c_str());
1158*8d67ca89SAndroid Build Coastguard Worker
1159*8d67ca89SAndroid Build Coastguard Worker PointerData::DumpLiveToFile(fd);
1160*8d67ca89SAndroid Build Coastguard Worker
1161*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "MAPS\n");
1162*8d67ca89SAndroid Build Coastguard Worker std::string content;
1163*8d67ca89SAndroid Build Coastguard Worker if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
1164*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "Could not open /proc/self/maps\n");
1165*8d67ca89SAndroid Build Coastguard Worker } else {
1166*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "%s", content.c_str());
1167*8d67ca89SAndroid Build Coastguard Worker }
1168*8d67ca89SAndroid Build Coastguard Worker dprintf(fd, "END\n");
1169*8d67ca89SAndroid Build Coastguard Worker
1170*8d67ca89SAndroid Build Coastguard Worker // Purge the memory that was allocated and freed during this operation
1171*8d67ca89SAndroid Build Coastguard Worker // since it can be large enough to expand the RSS significantly.
1172*8d67ca89SAndroid Build Coastguard Worker g_dispatch->mallopt(M_PURGE_ALL, 0);
1173*8d67ca89SAndroid Build Coastguard Worker }
1174*8d67ca89SAndroid Build Coastguard Worker
debug_write_malloc_leak_info(FILE * fp)1175*8d67ca89SAndroid Build Coastguard Worker bool debug_write_malloc_leak_info(FILE* fp) {
1176*8d67ca89SAndroid Build Coastguard Worker // Make sure any pending output is written to the file.
1177*8d67ca89SAndroid Build Coastguard Worker fflush(fp);
1178*8d67ca89SAndroid Build Coastguard Worker
1179*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1180*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
1181*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
1182*8d67ca89SAndroid Build Coastguard Worker
1183*8d67ca89SAndroid Build Coastguard Worker std::lock_guard<std::mutex> guard(g_dump_lock);
1184*8d67ca89SAndroid Build Coastguard Worker
1185*8d67ca89SAndroid Build Coastguard Worker if (!(g_debug->config().options() & BACKTRACE)) {
1186*8d67ca89SAndroid Build Coastguard Worker return false;
1187*8d67ca89SAndroid Build Coastguard Worker }
1188*8d67ca89SAndroid Build Coastguard Worker
1189*8d67ca89SAndroid Build Coastguard Worker write_dump(fileno(fp));
1190*8d67ca89SAndroid Build Coastguard Worker
1191*8d67ca89SAndroid Build Coastguard Worker return true;
1192*8d67ca89SAndroid Build Coastguard Worker }
1193*8d67ca89SAndroid Build Coastguard Worker
debug_dump_heap(const char * file_name)1194*8d67ca89SAndroid Build Coastguard Worker void debug_dump_heap(const char* file_name) {
1195*8d67ca89SAndroid Build Coastguard Worker ScopedConcurrentLock lock;
1196*8d67ca89SAndroid Build Coastguard Worker ScopedDisableDebugCalls disable;
1197*8d67ca89SAndroid Build Coastguard Worker ScopedBacktraceSignalBlocker blocked;
1198*8d67ca89SAndroid Build Coastguard Worker
1199*8d67ca89SAndroid Build Coastguard Worker std::lock_guard<std::mutex> guard(g_dump_lock);
1200*8d67ca89SAndroid Build Coastguard Worker
1201*8d67ca89SAndroid Build Coastguard Worker int fd = open(file_name, O_RDWR | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0644);
1202*8d67ca89SAndroid Build Coastguard Worker if (fd == -1) {
1203*8d67ca89SAndroid Build Coastguard Worker error_log("Unable to create file: %s", file_name);
1204*8d67ca89SAndroid Build Coastguard Worker return;
1205*8d67ca89SAndroid Build Coastguard Worker }
1206*8d67ca89SAndroid Build Coastguard Worker
1207*8d67ca89SAndroid Build Coastguard Worker error_log("Dumping to file: %s\n", file_name);
1208*8d67ca89SAndroid Build Coastguard Worker write_dump(fd);
1209*8d67ca89SAndroid Build Coastguard Worker close(fd);
1210*8d67ca89SAndroid Build Coastguard Worker }
1211