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