1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <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 55 std::atomic_uint8_t PointerData::backtrace_enabled_; 56 std::atomic_bool PointerData::backtrace_dump_; 57 58 std::mutex PointerData::pointer_mutex_; 59 std::unordered_map<uintptr_t, PointerInfoType> PointerData::pointers_ GUARDED_BY( 60 PointerData::pointer_mutex_); 61 62 std::mutex PointerData::frame_mutex_; 63 std::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY( 64 PointerData::frame_mutex_); 65 std::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_); 66 constexpr size_t kBacktraceEmptyIndex = 1; 67 size_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_); 68 69 std::mutex PointerData::free_pointer_mutex_; 70 std::deque<FreePointerInfoType> PointerData::free_pointers_ GUARDED_BY( 71 PointerData::free_pointer_mutex_); 72 73 // Buffer to use for comparison. 74 static constexpr size_t kCompareBufferSize = 512 * 1024; 75 static std::vector<uint8_t> g_cmp_mem(0); 76 77 static void ToggleBacktraceEnable(int, siginfo_t*, void*) { 78 g_debug->pointer->ToggleBacktraceEnabled(); 79 } 80 81 static void EnableDump(int, siginfo_t*, void*) { 82 g_debug->pointer->EnableDumping(); 83 } 84 85 PointerData::PointerData(DebugData* debug_data) : OptionData(debug_data) {} 86 87 bool 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 129 size_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 155 void 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 174 void 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 185 void 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 203 size_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 233 void 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 257 void 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 291 void* 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 314 void 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 342 void 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 349 void 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 } else if (a_frame != nullptr && b_frame == nullptr) { 396 return true; 397 } else if (a_frame == nullptr && b_frame == nullptr) { 398 return a.pointer < b.pointer; 399 } 400 401 // Put the pointers with longest backtrace first. 402 if (a_frame->frames.size() != b_frame->frames.size()) { 403 return a_frame->frames.size() > b_frame->frames.size(); 404 } 405 406 // Last sort by pointer. 407 return a.pointer < b.pointer; 408 }); 409 } 410 411 void PointerData::GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace) 412 REQUIRES(pointer_mutex_, frame_mutex_) { 413 GetList(list, only_with_backtrace); 414 415 // Remove duplicates of size/backtraces. 416 for (auto iter = list->begin(); iter != list->end();) { 417 auto dup_iter = iter + 1; 418 bool zygote_child_alloc = iter->zygote_child_alloc; 419 size_t size = iter->size; 420 FrameInfoType* frame_info = iter->frame_info; 421 for (; dup_iter != list->end(); ++dup_iter) { 422 if (zygote_child_alloc != dup_iter->zygote_child_alloc || size != dup_iter->size || 423 frame_info != dup_iter->frame_info) { 424 break; 425 } 426 iter->num_allocations++; 427 } 428 iter = list->erase(iter + 1, dup_iter); 429 } 430 } 431 432 void PointerData::LogLeaks() { 433 std::vector<ListInfoType> list; 434 435 std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 436 std::lock_guard<std::mutex> frame_guard(frame_mutex_); 437 GetList(&list, false); 438 439 size_t track_count = 0; 440 for (const auto& list_info : list) { 441 error_log("+++ %s leaked block of size %zu at 0x%" PRIxPTR " (leak %zu of %zu)", getprogname(), 442 list_info.size, list_info.pointer, ++track_count, list.size()); 443 if (list_info.frame_info != nullptr) { 444 error_log("Backtrace at time of allocation:"); 445 backtrace_log(list_info.frame_info->frames.data(), list_info.frame_info->frames.size()); 446 } 447 // Do not bother to free the pointers, we are about to exit any way. 448 } 449 } 450 451 void PointerData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, 452 size_t* total_memory, size_t* backtrace_size) { 453 std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 454 std::lock_guard<std::mutex> frame_guard(frame_mutex_); 455 456 if (pointers_.empty()) { 457 return; 458 } 459 460 std::vector<ListInfoType> list; 461 GetUniqueList(&list, true); 462 if (list.empty()) { 463 return; 464 } 465 466 *backtrace_size = g_debug->config().backtrace_frames(); 467 *info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size; 468 *overall_size = *info_size * list.size(); 469 *info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, list.size())); 470 if (*info == nullptr) { 471 return; 472 } 473 474 uint8_t* data = *info; 475 *total_memory = 0; 476 for (const auto& list_info : list) { 477 FrameInfoType* frame_info = list_info.frame_info; 478 *total_memory += list_info.size * list_info.num_allocations; 479 size_t allocation_size = 480 PointerInfoType::GetEncodedSize(list_info.zygote_child_alloc, list_info.size); 481 memcpy(data, &allocation_size, sizeof(size_t)); 482 memcpy(&data[sizeof(size_t)], &list_info.num_allocations, sizeof(size_t)); 483 if (frame_info != nullptr) { 484 memcpy(&data[2 * sizeof(size_t)], frame_info->frames.data(), 485 frame_info->frames.size() * sizeof(uintptr_t)); 486 } 487 data += *info_size; 488 } 489 } 490 491 bool PointerData::Exists(const void* ptr) { 492 uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr); 493 std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 494 return pointers_.count(pointer) != 0; 495 } 496 497 void PointerData::DumpLiveToFile(FILE* fp) { 498 std::vector<ListInfoType> list; 499 500 std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); 501 std::lock_guard<std::mutex> frame_guard(frame_mutex_); 502 GetUniqueList(&list, false); 503 504 size_t total_memory = 0; 505 for (const auto& info : list) { 506 total_memory += info.size * info.num_allocations; 507 } 508 509 fprintf(fp, "Total memory: %zu\n", total_memory); 510 fprintf(fp, "Allocation records: %zd\n", list.size()); 511 fprintf(fp, "Backtrace size: %zu\n", g_debug->config().backtrace_frames()); 512 fprintf(fp, "\n"); 513 514 for (const auto& info : list) { 515 fprintf(fp, "z %d sz %8zu num %zu bt", (info.zygote_child_alloc) ? 1 : 0, info.size, 516 info.num_allocations); 517 FrameInfoType* frame_info = info.frame_info; 518 if (frame_info != nullptr) { 519 for (size_t i = 0; i < frame_info->frames.size(); i++) { 520 if (frame_info->frames[i] == 0) { 521 break; 522 } 523 #if defined(__LP64__) 524 fprintf(fp, " %016" PRIxPTR, frame_info->frames[i]); 525 #else 526 fprintf(fp, " %08" PRIxPTR, frame_info->frames[i]); 527 #endif 528 } 529 } 530 fprintf(fp, "\n"); 531 } 532 } 533 534 void PointerData::PrepareFork() NO_THREAD_SAFETY_ANALYSIS { 535 pointer_mutex_.lock(); 536 frame_mutex_.lock(); 537 free_pointer_mutex_.lock(); 538 } 539 540 void PointerData::PostForkParent() NO_THREAD_SAFETY_ANALYSIS { 541 frame_mutex_.unlock(); 542 pointer_mutex_.unlock(); 543 free_pointer_mutex_.unlock(); 544 } 545 546 void PointerData::PostForkChild() __attribute__((no_thread_safety_analysis)) { 547 // Make sure that any potential mutexes have been released and are back 548 // to an initial state. 549 frame_mutex_.try_lock(); 550 frame_mutex_.unlock(); 551 pointer_mutex_.try_lock(); 552 pointer_mutex_.unlock(); 553 free_pointer_mutex_.try_lock(); 554 free_pointer_mutex_.unlock(); 555 } 556