Home | History | Annotate | Download | only in malloc_debug
      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 <mutex>
     37 #include <string>
     38 #include <unordered_map>
     39 #include <vector>
     40 
     41 #include <private/bionic_macros.h>
     42 
     43 #include "OptionData.h"
     44 
     45 extern int* g_malloc_zygote_child;
     46 
     47 // Forward declarations.
     48 class Config;
     49 
     50 struct FrameKeyType {
     51   size_t num_frames;
     52   uintptr_t* frames;
     53 
     54   bool operator==(const FrameKeyType& comp) const {
     55     if (num_frames != comp.num_frames) return false;
     56     for (size_t i = 0; i < num_frames; i++) {
     57       if (frames[i] != comp.frames[i]) {
     58         return false;
     59       }
     60     }
     61     return true;
     62   }
     63 };
     64 
     65 namespace std {
     66 template <>
     67 struct hash<FrameKeyType> {
     68   std::size_t operator()(const FrameKeyType& key) const {
     69     std::size_t cur_hash = key.frames[0];
     70     // Limit the number of frames to speed up hashing.
     71     size_t max_frames = (key.num_frames > 5) ? 5 : key.num_frames;
     72     for (size_t i = 1; i < max_frames; i++) {
     73       cur_hash ^= key.frames[i];
     74     }
     75     return cur_hash;
     76   }
     77 };
     78 };  // namespace std
     79 
     80 struct FrameInfoType {
     81   size_t references = 0;
     82   std::vector<uintptr_t> frames;
     83 };
     84 
     85 struct PointerInfoType {
     86   size_t size;
     87   size_t hash_index;
     88   size_t RealSize() const { return size & ~(1U << 31); }
     89   bool ZygoteChildAlloc() const { return size & (1U << 31); }
     90   static size_t GetEncodedSize(size_t size) { return GetEncodedSize(*g_malloc_zygote_child, size); }
     91   static size_t GetEncodedSize(bool child_alloc, size_t size) {
     92     return size | ((child_alloc) ? (1U << 31) : 0);
     93   }
     94   static size_t MaxSize() { return (1U << 31) - 1; }
     95 };
     96 
     97 struct FreePointerInfoType {
     98   uintptr_t pointer;
     99   size_t hash_index;
    100 };
    101 
    102 struct ListInfoType {
    103   uintptr_t pointer;
    104   size_t num_allocations;
    105   size_t size;
    106   bool zygote_child_alloc;
    107   FrameInfoType* frame_info;
    108 };
    109 
    110 class PointerData : public OptionData {
    111  public:
    112   PointerData(DebugData* debug_data);
    113   virtual ~PointerData() = default;
    114 
    115   bool Initialize(const Config& config);
    116 
    117   inline size_t alloc_offset() { return alloc_offset_; }
    118 
    119   bool ShouldBacktrace() { return backtrace_enabled_ == 1; }
    120   void ToggleBacktraceEnabled() { backtrace_enabled_.fetch_xor(1); }
    121 
    122   void EnableDumping() { backtrace_dump_ = true; }
    123   bool ShouldDumpAndReset() {
    124     bool expected = true;
    125     return backtrace_dump_.compare_exchange_strong(expected, false);
    126   }
    127 
    128   void PrepareFork();
    129   void PostForkParent();
    130   void PostForkChild();
    131 
    132   static void GetList(std::vector<ListInfoType>* list, bool only_with_backtrace);
    133   static void GetUniqueList(std::vector<ListInfoType>* list, bool only_with_backtrace);
    134 
    135   static size_t AddBacktrace(size_t num_frames);
    136   static void RemoveBacktrace(size_t hash_index);
    137 
    138   static void Add(const void* pointer, size_t size);
    139   static void Remove(const void* pointer);
    140 
    141   typedef std::unordered_map<uintptr_t, PointerInfoType>::iterator iterator;
    142   static iterator begin() { return pointers_.begin(); }
    143   static iterator end() { return pointers_.end(); }
    144 
    145   static void* AddFreed(const void* pointer);
    146   static void LogFreeError(const FreePointerInfoType& info, size_t usable_size);
    147   static void LogFreeBacktrace(const void* ptr);
    148   static void VerifyFreedPointer(const FreePointerInfoType& info);
    149   static void VerifyAllFreed();
    150 
    151   static void LogLeaks();
    152   static void DumpLiveToFile(FILE* fp);
    153 
    154   static void GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
    155                       size_t* backtrace_size);
    156 
    157   static size_t GetFrames(const void* pointer, uintptr_t* frames, size_t max_frames);
    158 
    159   static bool Exists(const void* pointer);
    160 
    161  private:
    162   static std::string GetHashString(uintptr_t* frames, size_t num_frames);
    163 
    164   size_t alloc_offset_ = 0;
    165   std::vector<uint8_t> cmp_mem_;
    166 
    167   static std::atomic_uint8_t backtrace_enabled_;
    168 
    169   static std::atomic_bool backtrace_dump_;
    170 
    171   static std::mutex pointer_mutex_;
    172   static std::unordered_map<uintptr_t, PointerInfoType> pointers_;
    173 
    174   static std::mutex frame_mutex_;
    175   static std::unordered_map<FrameKeyType, size_t> key_to_index_;
    176   static std::unordered_map<size_t, FrameInfoType> frames_;
    177   static size_t cur_hash_index_;
    178 
    179   static std::mutex free_pointer_mutex_;
    180   static std::deque<FreePointerInfoType> free_pointers_;
    181 
    182   DISALLOW_COPY_AND_ASSIGN(PointerData);
    183 };
    184