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 |