PHC.h (5702B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef PHC_h 8 #define PHC_h 9 10 #include "mozilla/Maybe.h" 11 #include <stdint.h> 12 #include <stdlib.h> 13 14 #include "mozmemory_wrap.h" 15 16 namespace mozilla { 17 namespace phc { 18 19 // Note: a stack trace may have no frames due to a collection problem. 20 // 21 // Also note: a more compact stack trace representation could be achieved with 22 // some effort. 23 struct StackTrace { 24 public: 25 static const size_t kMaxFrames = 16; 26 27 // The number of PCs in the stack trace. 28 size_t mLength; 29 30 // The PCs in the stack trace. Only the first mLength are initialized. 31 const void* mPcs[kMaxFrames]; 32 33 public: 34 StackTrace() : mLength(0) {} 35 }; 36 37 // Info from PHC about an address in memory. 38 class AddrInfo { 39 public: 40 enum class Kind { 41 // The address is not in PHC-managed memory. 42 Unknown = 0, 43 44 // The address is within a PHC page that has never been allocated. A crash 45 // involving such an address is unlikely in practice, because it would 46 // require the crash to happen quite early. 47 NeverAllocatedPage = 1, 48 49 // The address is within a PHC page that is in use. 50 InUsePage = 2, 51 52 // The address is within a PHC page that has been allocated and then freed. 53 // A crash involving such an address most likely indicates a 54 // use-after-free. (A sufficiently wild write -- e.g. a large buffer 55 // overflow -- could also trigger it, but this is less likely.) 56 FreedPage = 3, 57 58 // The address is within a PHC guard page. A crash involving such an 59 // address most likely indicates a buffer overflow. (Again, a sufficiently 60 // wild write could unluckily trigger it, but this is less likely.) 61 GuardPage = 4, 62 }; 63 64 // The page kind. 65 Kind mKind; 66 67 // The starting address of the allocation. 68 // - Unknown | NeverAllocatedPage: nullptr. 69 // - InUsePage | FreedPage: the address of the allocation within the page. 70 // - GuardPage: the mBaseAddr value from the preceding allocation page. 71 const void* mBaseAddr; 72 73 // The usable size, which could be bigger than the requested size. 74 // - Unknown | NeverAllocatePage: 0. 75 // - InUsePage | FreedPage: the usable size of the allocation within the page. 76 // - GuardPage: the mUsableSize value from the preceding allocation page. 77 size_t mUsableSize; 78 79 // The allocation stack. 80 // - Unknown | NeverAllocatedPage: Nothing. 81 // - InUsePage | FreedPage: Some. 82 // - GuardPage: the mAllocStack value from the preceding allocation page. 83 mozilla::Maybe<StackTrace> mAllocStack; 84 85 // The free stack. 86 // - Unknown | NeverAllocatedPage | InUsePage: Nothing. 87 // - FreedPage: Some. 88 // - GuardPage: the mFreeStack value from the preceding allocation page. 89 mozilla::Maybe<StackTrace> mFreeStack; 90 91 // True if PHC was locked and therefore we couldn't retrive some infomation. 92 bool mPhcWasLocked = false; 93 94 // Default to no PHC info. 95 AddrInfo() : mKind(Kind::Unknown), mBaseAddr(nullptr), mUsableSize(0) {} 96 }; 97 98 // Global instance that is retrieved by the process generating the crash report 99 extern AddrInfo gAddrInfo; 100 101 // If this is a PHC-handled address, return true, and if an AddrInfo is 102 // provided, fill in all of its fields. Otherwise, return false and leave 103 // AddrInfo unchanged. 104 MOZ_JEMALLOC_API bool IsPHCAllocation(const void*, AddrInfo*); 105 106 // Disable PHC allocations on the current thread. Only useful for tests. Note 107 // that PHC deallocations will still occur as needed. 108 MOZ_JEMALLOC_API void DisablePHCOnCurrentThread(); 109 110 // Re-enable PHC allocations on the current thread. Only useful for tests. 111 MOZ_JEMALLOC_API void ReenablePHCOnCurrentThread(); 112 113 // Test whether PHC allocations are enabled on the current thread. Only 114 // useful for tests. 115 MOZ_JEMALLOC_API bool IsPHCEnabledOnCurrentThread(); 116 117 // PHC has three different states: 118 // * Not compiled in 119 // * OnlyFree - The memory allocator is hooked but new allocations 120 // requests will be forwarded to mozjemalloc, free() will 121 // correctly free any PHC allocations and realloc() will 122 // "move" PHC allocations to mozjemalloc allocations. 123 // * Enabled - Full use. 124 enum PHCState { 125 OnlyFree, 126 Enabled, 127 }; 128 129 MOZ_JEMALLOC_API void SetPHCState(PHCState aState); 130 131 // Set the maximum allowed memory usage of PHC, including fragmentation and 132 // metadata. 133 MOZ_JEMALLOC_API void SetPHCSize(size_t aNumPHCBytes); 134 135 MOZ_JEMALLOC_API void SetPHCProbabilities(int64_t aAvgDelayFirst, 136 int64_t aAvgDelayNormal, 137 int64_t aAvgDelayPageReuse); 138 139 struct MemoryUsage { 140 // The amount of memory used for PHC metadata, eg information about each 141 // allocation including stacks. 142 size_t mMetadataBytes = 0; 143 144 // The amount of memory lost due to rounding allocation sizes up to the 145 // nearest page. AKA internal fragmentation. 146 size_t mFragmentationBytes = 0; 147 148 // The amount of memory allocated from PHC. 149 size_t mAllocatedBytes = 0; 150 }; 151 152 MOZ_JEMALLOC_API void PHCMemoryUsage(MemoryUsage& aMemoryUsage); 153 154 struct PHCStats { 155 size_t mSlotsAllocated = 0; 156 size_t mSlotsFreed = 0; 157 size_t mSlotsUnused = 0; 158 }; 159 160 // Return PHC memory usage information by filling in the supplied structure. 161 MOZ_JEMALLOC_API void GetPHCStats(PHCStats& aStats); 162 163 } // namespace phc 164 } // namespace mozilla 165 166 // Initialise PHC (called from mozjemalloc's initialisation. 167 void phc_init(); 168 169 #endif /* PHC_h */