| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2013 Google Inc. All rights reserved. | 2  * Copyright (C) 2013 Google Inc. All rights reserved. | 
| 3  * | 3  * | 
| 4  * Redistribution and use in source and binary forms, with or without | 4  * Redistribution and use in source and binary forms, with or without | 
| 5  * modification, are permitted provided that the following conditions are | 5  * modification, are permitted provided that the following conditions are | 
| 6  * met: | 6  * met: | 
| 7  * | 7  * | 
| 8  *     * Redistributions of source code must retain the above copyright | 8  *     * Redistributions of source code must retain the above copyright | 
| 9  * notice, this list of conditions and the following disclaimer. | 9  * notice, this list of conditions and the following disclaimer. | 
| 10  *     * Redistributions in binary form must reproduce the above | 10  *     * Redistributions in binary form must reproduce the above | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 29  */ | 29  */ | 
| 30 | 30 | 
| 31 #ifndef HeapPage_h | 31 #ifndef HeapPage_h | 
| 32 #define HeapPage_h | 32 #define HeapPage_h | 
| 33 | 33 | 
|  | 34 #include <stdint.h> | 
| 34 #include "base/trace_event/memory_allocator_dump.h" | 35 #include "base/trace_event/memory_allocator_dump.h" | 
| 35 #include "platform/PlatformExport.h" | 36 #include "platform/PlatformExport.h" | 
| 36 #include "platform/heap/BlinkGC.h" | 37 #include "platform/heap/BlinkGC.h" | 
| 37 #include "platform/heap/GCInfo.h" | 38 #include "platform/heap/GCInfo.h" | 
| 38 #include "platform/heap/ThreadState.h" | 39 #include "platform/heap/ThreadState.h" | 
| 39 #include "platform/heap/Visitor.h" | 40 #include "platform/heap/Visitor.h" | 
| 40 #include "wtf/AddressSanitizer.h" | 41 #include "wtf/AddressSanitizer.h" | 
| 41 #include "wtf/Allocator.h" | 42 #include "wtf/Allocator.h" | 
| 42 #include "wtf/Assertions.h" | 43 #include "wtf/Assertions.h" | 
| 43 #include "wtf/ContainerAnnotations.h" | 44 #include "wtf/ContainerAnnotations.h" | 
| 44 #include "wtf/Forward.h" | 45 #include "wtf/Forward.h" | 
| 45 #include "wtf/allocator/Partitions.h" | 46 #include "wtf/allocator/Partitions.h" | 
| 46 #include <stdint.h> |  | 
| 47 | 47 | 
| 48 namespace blink { | 48 namespace blink { | 
| 49 | 49 | 
| 50 const size_t blinkPageSizeLog2 = 17; | 50 const size_t blinkPageSizeLog2 = 17; | 
| 51 const size_t blinkPageSize = 1 << blinkPageSizeLog2; | 51 const size_t blinkPageSize = 1 << blinkPageSizeLog2; | 
| 52 const size_t blinkPageOffsetMask = blinkPageSize - 1; | 52 const size_t blinkPageOffsetMask = blinkPageSize - 1; | 
| 53 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; | 53 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; | 
| 54 | 54 | 
| 55 // We allocate pages at random addresses but in groups of | 55 // We allocate pages at random addresses but in groups of | 
| 56 // blinkPagesPerRegion at a given random address. We group pages to | 56 // blinkPagesPerRegion at a given random address. We group pages to | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 117 #else | 117 #else | 
| 118 #define SET_MEMORY_INACCESSIBLE(address, size) memset((address), 0, (size)) | 118 #define SET_MEMORY_INACCESSIBLE(address, size) memset((address), 0, (size)) | 
| 119 #define SET_MEMORY_ACCESSIBLE(address, size) \ | 119 #define SET_MEMORY_ACCESSIBLE(address, size) \ | 
| 120   do {                                       \ | 120   do {                                       \ | 
| 121   } while (false) | 121   } while (false) | 
| 122 #define CHECK_MEMORY_INACCESSIBLE(address, size) \ | 122 #define CHECK_MEMORY_INACCESSIBLE(address, size) \ | 
| 123   do {                                           \ | 123   do {                                           \ | 
| 124   } while (false) | 124   } while (false) | 
| 125 #endif | 125 #endif | 
| 126 | 126 | 
| 127 #if !DCHECK_IS_ON() && CPU(64BIT) |  | 
| 128 #define USE_4BYTE_HEADER_PADDING 1 |  | 
| 129 #else |  | 
| 130 #define USE_4BYTE_HEADER_PADDING 0 |  | 
| 131 #endif |  | 
| 132 |  | 
| 133 class NormalPageArena; | 127 class NormalPageArena; | 
| 134 class PageMemory; | 128 class PageMemory; | 
| 135 | 129 | 
| 136 // HeapObjectHeader is 4 byte (32 bit) that has the following layout: | 130 // HeapObjectHeader is 4 byte (32 bit) that has the following layout: | 
| 137 // | 131 // | 
| 138 // | gcInfoIndex (14 bit) | | 132 // | gcInfoIndex (14 bit) | | 
| 139 // | DOM mark bit (1 bit) | | 133 // | DOM mark bit (1 bit) | | 
| 140 // | size (14 bit)        | | 134 // | size (14 bit)        | | 
| 141 // | dead bit (1 bit)     | | 135 // | dead bit (1 bit)     | | 
| 142 // | freed bit (1 bit)    | | 136 // | freed bit (1 bit)    | | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 172     nonLargeObjectPageSizeMax >= blinkPageSize, | 166     nonLargeObjectPageSizeMax >= blinkPageSize, | 
| 173     "max size supported by HeapObjectHeader must at least be blinkPageSize"); | 167     "max size supported by HeapObjectHeader must at least be blinkPageSize"); | 
| 174 | 168 | 
| 175 class PLATFORM_EXPORT HeapObjectHeader { | 169 class PLATFORM_EXPORT HeapObjectHeader { | 
| 176   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 170   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 
| 177 | 171 | 
| 178  public: | 172  public: | 
| 179   // If gcInfoIndex is 0, this header is interpreted as a free list header. | 173   // If gcInfoIndex is 0, this header is interpreted as a free list header. | 
| 180   NO_SANITIZE_ADDRESS | 174   NO_SANITIZE_ADDRESS | 
| 181   HeapObjectHeader(size_t size, size_t gcInfoIndex) { | 175   HeapObjectHeader(size_t size, size_t gcInfoIndex) { | 
| 182 #if DCHECK_IS_ON() | 176     m_magic = getMagic(); | 
| 183     m_magic = magic; |  | 
| 184 #endif |  | 
| 185     // sizeof(HeapObjectHeader) must be equal to or smaller than | 177     // sizeof(HeapObjectHeader) must be equal to or smaller than | 
| 186     // allocationGranurarity, because HeapObjectHeader is used as a header | 178     // allocationGranurarity, because HeapObjectHeader is used as a header | 
| 187     // for an freed entry.  Given that the smallest entry size is | 179     // for an freed entry.  Given that the smallest entry size is | 
| 188     // allocationGranurarity, HeapObjectHeader must fit into the size. | 180     // allocationGranurarity, HeapObjectHeader must fit into the size. | 
| 189     static_assert( | 181     static_assert( | 
| 190         sizeof(HeapObjectHeader) <= allocationGranularity, | 182         sizeof(HeapObjectHeader) <= allocationGranularity, | 
| 191         "size of HeapObjectHeader must be smaller than allocationGranularity"); | 183         "size of HeapObjectHeader must be smaller than allocationGranularity"); | 
| 192 #if CPU(64BIT) |  | 
| 193     static_assert(sizeof(HeapObjectHeader) == 8, | 184     static_assert(sizeof(HeapObjectHeader) == 8, | 
| 194                   "size of HeapObjectHeader must be 8 byte aligned"); | 185                   "sizeof(HeapObjectHeader) must be 8 bytes"); | 
| 195 #endif |  | 
| 196 | 186 | 
| 197     ASSERT(gcInfoIndex < GCInfoTable::maxIndex); | 187     ASSERT(gcInfoIndex < GCInfoTable::maxIndex); | 
| 198     ASSERT(size < nonLargeObjectPageSizeMax); | 188     ASSERT(size < nonLargeObjectPageSizeMax); | 
| 199     ASSERT(!(size & allocationMask)); | 189     ASSERT(!(size & allocationMask)); | 
| 200     m_encoded = static_cast<uint32_t>( | 190     m_encoded = static_cast<uint32_t>( | 
| 201         (gcInfoIndex << headerGCInfoIndexShift) | size | | 191         (gcInfoIndex << headerGCInfoIndexShift) | size | | 
| 202         (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); | 192         (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); | 
| 203   } | 193   } | 
| 204 | 194 | 
| 205   NO_SANITIZE_ADDRESS | 195   NO_SANITIZE_ADDRESS | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 226   void markWrapperHeader(); | 216   void markWrapperHeader(); | 
| 227   void unmarkWrapperHeader(); | 217   void unmarkWrapperHeader(); | 
| 228   bool isMarked() const; | 218   bool isMarked() const; | 
| 229   void mark(); | 219   void mark(); | 
| 230   void unmark(); | 220   void unmark(); | 
| 231 | 221 | 
| 232   Address payload(); | 222   Address payload(); | 
| 233   size_t payloadSize(); | 223   size_t payloadSize(); | 
| 234   Address payloadEnd(); | 224   Address payloadEnd(); | 
| 235 | 225 | 
| 236 #if DCHECK_IS_ON() | 226   // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should | 
|  | 227   // manage its integrity on its own, without requiring outside callers to | 
|  | 228   // explicitly check. | 
| 237   bool checkHeader() const; | 229   bool checkHeader() const; | 
| 238   // Zap magic number with a new magic number that means there was once an | 230   // Zap magic number with a new magic number that means there was once an | 
| 239   // object allocated here, but it was freed because nobody marked it during | 231   // object allocated here, but it was freed because nobody marked it during | 
| 240   // GC. | 232   // GC. | 
| 241   void zapMagic(); | 233   void zapMagic(); | 
| 242 #endif |  | 
| 243 | 234 | 
| 244   void finalize(Address, size_t); | 235   void finalize(Address, size_t); | 
| 245   static HeapObjectHeader* fromPayload(const void*); | 236   static HeapObjectHeader* fromPayload(const void*); | 
| 246 | 237 | 
| 247   static const uint16_t magic = 0xfff1; | 238   static const uint32_t zappedMagic = 0xDEAD4321; | 
| 248   static const uint16_t zappedMagic = 0x4321; |  | 
| 249 | 239 | 
| 250  private: | 240  private: | 
|  | 241   // Returns a random value. | 
|  | 242   // | 
|  | 243   // The implementation gets its randomness from the locations of 2 independent | 
|  | 244   // sources of address space layout randomization: a function in a Chrome | 
|  | 245   // executable image, and a function in an external DLL/so. This implementation | 
|  | 246   // should be fast and small, and should have the benefit of requiring | 
|  | 247   // attackers to discover and use 2 independent weak infoleak bugs, or 1 | 
|  | 248   // arbitrary infoleak bug (used twice). | 
|  | 249   uint32_t getMagic() const; | 
|  | 250 | 
|  | 251   uint32_t m_magic; | 
| 251   uint32_t m_encoded; | 252   uint32_t m_encoded; | 
| 252 #if DCHECK_IS_ON() |  | 
| 253   uint16_t m_magic; |  | 
| 254 #endif |  | 
| 255 |  | 
| 256 // In 64 bit architectures, we intentionally add 4 byte padding immediately |  | 
| 257 // after the HeapObjectHeader. This is because: |  | 
| 258 // |  | 
| 259 // | HeapObjectHeader (4 byte)   |  <- 8 byte aligned |  | 
| 260 // | padding (4 byte)            | |  | 
| 261 // | object payload (8 * n byte) |  <- 8 byte aligned |  | 
| 262 // |  | 
| 263 // is better than: |  | 
| 264 // |  | 
| 265 // | HeapObjectHeader (4 byte)   |  <- 4 byte aligned |  | 
| 266 // | object payload (8 * n byte) |  <- 8 byte aligned |  | 
| 267 // | padding (4 byte)            |  <- 4 byte aligned |  | 
| 268 // |  | 
| 269 // since the former layout aligns both header and payload to 8 byte. |  | 
| 270 #if USE_4BYTE_HEADER_PADDING |  | 
| 271  public: |  | 
| 272   uint32_t m_padding; |  | 
| 273 #endif |  | 
| 274 }; | 253 }; | 
| 275 | 254 | 
| 276 class FreeListEntry final : public HeapObjectHeader { | 255 class FreeListEntry final : public HeapObjectHeader { | 
| 277  public: | 256  public: | 
| 278   NO_SANITIZE_ADDRESS | 257   NO_SANITIZE_ADDRESS | 
| 279   explicit FreeListEntry(size_t size) | 258   explicit FreeListEntry(size_t size) | 
| 280       : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { | 259       : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { | 
| 281 #if DCHECK_IS_ON() | 260 #if DCHECK_IS_ON() | 
| 282     ASSERT(size >= sizeof(HeapObjectHeader)); | 261     ASSERT(size >= sizeof(HeapObjectHeader)); | 
| 283     zapMagic(); | 262     zapMagic(); | 
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 849 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { | 828 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { | 
| 850   size_t result = m_encoded & headerSizeMask; | 829   size_t result = m_encoded & headerSizeMask; | 
| 851   // Large objects should not refer to header->size(). | 830   // Large objects should not refer to header->size(). | 
| 852   // The actual size of a large object is stored in | 831   // The actual size of a large object is stored in | 
| 853   // LargeObjectPage::m_payloadSize. | 832   // LargeObjectPage::m_payloadSize. | 
| 854   ASSERT(result != largeObjectSizeInHeader); | 833   ASSERT(result != largeObjectSizeInHeader); | 
| 855   ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 834   ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 
| 856   return result; | 835   return result; | 
| 857 } | 836 } | 
| 858 | 837 | 
| 859 #if DCHECK_IS_ON() |  | 
| 860 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { | 838 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { | 
| 861   return m_magic == magic; | 839   return m_magic == getMagic(); | 
| 862 } | 840 } | 
| 863 #endif |  | 
| 864 | 841 | 
| 865 inline Address HeapObjectHeader::payload() { | 842 inline Address HeapObjectHeader::payload() { | 
| 866   return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); | 843   return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); | 
| 867 } | 844 } | 
| 868 | 845 | 
| 869 inline Address HeapObjectHeader::payloadEnd() { | 846 inline Address HeapObjectHeader::payloadEnd() { | 
| 870   return reinterpret_cast<Address>(this) + size(); | 847   return reinterpret_cast<Address>(this) + size(); | 
| 871 } | 848 } | 
| 872 | 849 | 
| 873 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { | 850 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { | 
| 874   size_t size = m_encoded & headerSizeMask; | 851   size_t size = m_encoded & headerSizeMask; | 
| 875   if (UNLIKELY(size == largeObjectSizeInHeader)) { | 852   if (UNLIKELY(size == largeObjectSizeInHeader)) { | 
| 876     ASSERT(pageFromObject(this)->isLargeObjectPage()); | 853     ASSERT(pageFromObject(this)->isLargeObjectPage()); | 
| 877     return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); | 854     return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); | 
| 878   } | 855   } | 
| 879   ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 856   ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 
| 880   return size - sizeof(HeapObjectHeader); | 857   return size - sizeof(HeapObjectHeader); | 
| 881 } | 858 } | 
| 882 | 859 | 
| 883 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { | 860 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { | 
| 884   Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | 861   Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | 
| 885   HeapObjectHeader* header = | 862   HeapObjectHeader* header = | 
| 886       reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); | 863       reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); | 
| 887   ASSERT(header->checkHeader()); | 864   ASSERT(header->checkHeader()); | 
| 888   return header; | 865   return header; | 
| 889 } | 866 } | 
| 890 | 867 | 
|  | 868 inline uint32_t HeapObjectHeader::getMagic() const { | 
|  | 869   const uintptr_t random1 = | 
|  | 870       ~(reinterpret_cast<uintptr_t>( | 
|  | 871             base::trace_event::MemoryAllocatorDump::kNameSize) >> | 
|  | 872         16); | 
|  | 873 | 
|  | 874 #if OS(WIN) | 
|  | 875   const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16); | 
|  | 876 #elif OS(POSIX) | 
|  | 877   const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16); | 
|  | 878 #else | 
|  | 879 #error OS not supported | 
|  | 880 #endif | 
|  | 881 | 
|  | 882 #if CPU(64BIT) | 
|  | 883   static_assert(sizeof(uintptr_t) == sizeof(uint64_t), | 
|  | 884                 "uintptr_t is not uint64_t"); | 
|  | 885   const uint32_t random = static_cast<uint32_t>( | 
|  | 886       (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL)); | 
|  | 887 #elif CPU(32BIT) | 
|  | 888   static_assert(sizeof(uintptr_t) == sizeof(uint32_t), | 
|  | 889                 "uintptr_t is not uint32_t"); | 
|  | 890   const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL); | 
|  | 891 #else | 
|  | 892 #error architecture not supported | 
|  | 893 #endif | 
|  | 894 | 
|  | 895   return random; | 
|  | 896 } | 
|  | 897 | 
| 891 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() | 898 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() | 
| 892     const { | 899     const { | 
| 893   ASSERT(checkHeader()); | 900   ASSERT(checkHeader()); | 
| 894   return m_encoded & headerWrapperMarkBitMask; | 901   return m_encoded & headerWrapperMarkBitMask; | 
| 895 } | 902 } | 
| 896 | 903 | 
| 897 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() { | 904 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() { | 
| 898   ASSERT(checkHeader()); | 905   ASSERT(checkHeader()); | 
| 899   ASSERT(!isWrapperHeaderMarked()); | 906   ASSERT(!isWrapperHeaderMarked()); | 
| 900   m_encoded |= headerWrapperMarkBitMask; | 907   m_encoded |= headerWrapperMarkBitMask; | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 941   return outOfLineAllocate(allocationSize, gcInfoIndex); | 948   return outOfLineAllocate(allocationSize, gcInfoIndex); | 
| 942 } | 949 } | 
| 943 | 950 | 
| 944 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 951 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 
| 945   return static_cast<NormalPageArena*>(arena()); | 952   return static_cast<NormalPageArena*>(arena()); | 
| 946 } | 953 } | 
| 947 | 954 | 
| 948 }  // namespace blink | 955 }  // namespace blink | 
| 949 | 956 | 
| 950 #endif  // HeapPage_h | 957 #endif  // HeapPage_h | 
| OLD | NEW | 
|---|