1// Copyright 2021 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef V8_HEAP_CPPGC_MEMORY_H_ 6#define V8_HEAP_CPPGC_MEMORY_H_ 7 8#include <cstddef> 9#include <cstdint> 10#include <cstring> 11 12#include "src/base/macros.h" 13#include "src/base/sanitizer/asan.h" 14#include "src/base/sanitizer/msan.h" 15#include "src/heap/cppgc/globals.h" 16 17namespace cppgc { 18namespace internal { 19 20V8_NOINLINE DISABLE_ASAN void NoSanitizeMemset(void* address, char c, 21 size_t bytes); 22 23static constexpr uint8_t kZappedValue = 0xdc; 24 25V8_INLINE void ZapMemory(void* address, size_t size) { 26 // The lowest bit of the zapped value should be 0 so that zapped object are 27 // never viewed as fully constructed objects. 28 memset(address, kZappedValue, size); 29} 30 31V8_INLINE void CheckMemoryIsZapped(const void* address, size_t size) { 32 for (size_t i = 0; i < size; i++) { 33 CHECK_EQ(kZappedValue, reinterpret_cast<ConstAddress>(address)[i]); 34 } 35} 36 37V8_INLINE void CheckMemoryIsZero(const void* address, size_t size) { 38 for (size_t i = 0; i < size; i++) { 39 CHECK_EQ(0, reinterpret_cast<ConstAddress>(address)[i]); 40 } 41} 42 43// Together `SetMemoryAccessible()` and `SetMemoryInaccessible()` form the 44// memory access model for allocation and free. 45V8_INLINE void SetMemoryAccessible(void* address, size_t size) { 46#if defined(V8_USE_MEMORY_SANITIZER) 47 48 MSAN_MEMORY_IS_INITIALIZED(address, size); 49 50#elif defined(V8_USE_ADDRESS_SANITIZER) 51 52 ASAN_UNPOISON_MEMORY_REGION(address, size); 53 54#elif DEBUG 55 56 memset(address, 0, size); 57 58#else // Release builds. 59 60 // Nothing to be done for release builds. 61 62#endif // Release builds. 63} 64 65V8_INLINE void SetMemoryInaccessible(void* address, size_t size) { 66#if defined(V8_USE_MEMORY_SANITIZER) 67 68 memset(address, 0, size); 69 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(address, size); 70 71#elif defined(V8_USE_ADDRESS_SANITIZER) 72 73 NoSanitizeMemset(address, 0, size); 74 ASAN_POISON_MEMORY_REGION(address, size); 75 76#elif DEBUG 77 78 ::cppgc::internal::ZapMemory(address, size); 79 80#else // Release builds. 81 82 memset(address, 0, size); 83 84#endif // Release builds. 85} 86 87constexpr bool CheckMemoryIsInaccessibleIsNoop() { 88#if defined(V8_USE_MEMORY_SANITIZER) 89 90 return true; 91 92#elif defined(V8_USE_ADDRESS_SANITIZER) 93 94 return false; 95 96#elif DEBUG 97 98 return false; 99 100#else // Release builds. 101 102 return true; 103 104#endif // Release builds. 105} 106 107V8_INLINE void CheckMemoryIsInaccessible(const void* address, size_t size) { 108#if defined(V8_USE_MEMORY_SANITIZER) 109 110 static_assert(CheckMemoryIsInaccessibleIsNoop(), 111 "CheckMemoryIsInaccessibleIsNoop() needs to reflect " 112 "CheckMemoryIsInaccessible()."); 113 // Unable to check that memory is marked as uninitialized by MSAN. 114 115#elif defined(V8_USE_ADDRESS_SANITIZER) 116 117 static_assert(!CheckMemoryIsInaccessibleIsNoop(), 118 "CheckMemoryIsInaccessibleIsNoop() needs to reflect " 119 "CheckMemoryIsInaccessible()."); 120 // Only check if memory is poisoned on 64 bit, since there we make sure that 121 // object sizes and alignments are multiple of shadow memory granularity. 122#if defined(V8_TARGET_ARCH_64_BIT) 123 ASAN_CHECK_WHOLE_MEMORY_REGION_IS_POISONED(address, size); 124#endif 125 ASAN_UNPOISON_MEMORY_REGION(address, size); 126 CheckMemoryIsZero(address, size); 127 ASAN_POISON_MEMORY_REGION(address, size); 128 129#elif DEBUG 130 131 static_assert(!CheckMemoryIsInaccessibleIsNoop(), 132 "CheckMemoryIsInaccessibleIsNoop() needs to reflect " 133 "CheckMemoryIsInaccessible()."); 134 CheckMemoryIsZapped(address, size); 135 136#else // Release builds. 137 138 static_assert(CheckMemoryIsInaccessibleIsNoop(), 139 "CheckMemoryIsInaccessibleIsNoop() needs to reflect " 140 "CheckMemoryIsInaccessible()."); 141 // No check in release builds. 142 143#endif // Release builds. 144} 145 146} // namespace internal 147} // namespace cppgc 148 149#endif // V8_HEAP_CPPGC_MEMORY_H_ 150