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 #pragma once 30 31 #include <stdint.h> 32 #include <stdio.h> 33 34 #include <atomic> 35 #include <deque> 36 #include <functional> 37 #include <mutex> 38 #include <string> 39 #include <unordered_map> 40 #include <vector> 41 42 #include <platform/bionic/macros.h> 43 #include <unwindstack/Unwinder.h> 44 45 #include "OptionData.h" 46 #include "UnwindBacktrace.h" 47 48 extern bool* g_zygote_child; 49 50 // Forward declarations. 51 class Config; 52 53 struct FrameKeyType { 54 size_t num_frames; 55 uintptr_t* frames; 56 57 bool operator==(const FrameKeyType& comp) const { 58 if (num_frames != comp.num_frames) return false; 59 for (size_t i = 0; i < num_frames; i++) { 60 if (frames[i] != comp.frames[i]) { 61 return false; 62 } 63 } 64 return true; 65 } 66 }; 67 68 namespace std { 69 template <> 70 struct hash<FrameKeyType> { 71 std::size_t operator()(const FrameKeyType& key) const { 72 std::size_t cur_hash = key.frames[0]; 73 // Limit the number of frames to speed up hashing. 74 size_t max_frames = (key.num_frames > 5) ? 5 : key.num_frames; 75 for (size_t i = 1; i < max_frames; i++) { 76 cur_hash ^= key.frames[i]; 77 } 78 return cur_hash; 79 } 80 }; 81 }; // namespace std 82 83 struct FrameInfoType { 84 size_t references = 0; 85 std::vector<uintptr_t> frames; 86 }; 87 88 struct PointerInfoType { 89 size_t size; 90 size_t hash_index; 91 size_t RealSize() const { return size & ~(1U << 31); } 92 bool ZygoteChildAlloc() const { return size & (1U << 31); } 93 static size_t GetEncodedSize(size_t size) { 94 return GetEncodedSize(*g_zygote_child, size); 95 } 96 static size_t GetEncodedSize(bool child_alloc, size_t size) { 97 return size | ((child_alloc) ? (1U << 31) : 0); 98 } 99 static size_t MaxSize() { return (1U << 31) - 1; } 100 }; 101 102 struct FreePointerInfoType { 103 uintptr_t mangled_ptr; 104 size_t hash_index; 105 }; 106 107 struct ListInfoType { 108 uintptr_t pointer; 109 size_t num_allocations; 110 size_t size; 111 bool zygote_child_alloc; 112 FrameInfoType* frame_info; 113 std::vector<unwindstack::FrameData>* backtrace_info; 114 }; 115 116 class PointerData : public OptionData { 117 public: 118 explicit PointerData(DebugData* debug_data); 119 virtual ~PointerData() = default; 120 121 bool Initialize(const Config& config); 122 123 inline size_t alloc_offset() { return alloc_offset_; } 124 125 bool ShouldBacktrace() { return backtrace_enabled_ == 1; } 126 void ToggleBacktraceEnabled() { backtrace_enabled_.fetch_xor(1); } 127 128 void EnableDumping() { backtrace_dump_ = true; } 129 bool ShouldDumpAndReset() { 130 bool expected = true; 131 return backtrace_dump_.compare_exchange_strong(expected, false); 132 } 133 134 void PrepareFork(); 135 void PostForkParent(); 136 void PostForkChild(); 137 138 static void IteratePointers(std::function<void(uintptr_t pointer)> fn); 139 140 static size_t AddBacktrace(size_t num_frames, size_t size_bytes); 141 static void RemoveBacktrace(size_t hash_index); 142 143 static void Add(const void* pointer, size_t size); 144 static void Remove(const void* pointer); 145 146 static void* AddFreed(const void* pointer, size_t size_bytes); 147 static void LogFreeError(const FreePointerInfoType& info, size_t usable_size); 148 static void LogFreeBacktrace(const void* ptr); 149 static void VerifyFreedPointer(const FreePointerInfoType& info); 150 static void VerifyAllFreed(); 151 152 static void GetAllocList(std::vector<ListInfoType>* list); 153 static void LogLeaks(); 154 static void DumpLiveToFile(int fd); 155 156 static void GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory, 157 size_t* backtrace_size); 158 159 static size_t GetFrames(const void* pointer, uintptr_t* frames, size_t max_frames); 160 161 static bool Exists(const void* pointer); 162 163 private: 164 // Only keep mangled pointers in internal data structures. This avoids 165 // problems where libmemunreachable finds these pointers and thinks they 166 // are not unreachable. 167 static inline uintptr_t ManglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; } 168 static inline uintptr_t DemanglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; } 169 170 static std::string GetHashString(uintptr_t* frames, size_t num_frames); 171 static void LogBacktrace(size_t hash_index); 172 173 static void GetList(std::vector<ListInfoType>* list, bool only_with_backtrace); 174 static void GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace); 175 176 size_t alloc_offset_ = 0; 177 std::vector<uint8_t> cmp_mem_; 178 179 static std::atomic_uint8_t backtrace_enabled_; 180 181 static std::atomic_bool backtrace_dump_; 182 183 static std::mutex pointer_mutex_; 184 static std::unordered_map<uintptr_t, PointerInfoType> pointers_; 185 186 static std::mutex frame_mutex_; 187 static std::unordered_map<FrameKeyType, size_t> key_to_index_; 188 static std::unordered_map<size_t, FrameInfoType> frames_; 189 static std::unordered_map<size_t, std::vector<unwindstack::FrameData>> backtraces_info_; 190 static size_t cur_hash_index_; 191 192 static std::mutex free_pointer_mutex_; 193 static std::deque<FreePointerInfoType> free_pointers_; 194 195 BIONIC_DISALLOW_COPY_AND_ASSIGN(PointerData); 196 }; 197