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 INCLUDE_V8_INITIALIZATION_H_ 6 #define INCLUDE_V8_INITIALIZATION_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include "v8-callbacks.h" // NOLINT(build/include_directory) 12 #include "v8-internal.h" // NOLINT(build/include_directory) 13 #include "v8-isolate.h" // NOLINT(build/include_directory) 14 #include "v8-platform.h" // NOLINT(build/include_directory) 15 #include "v8config.h" // NOLINT(build/include_directory) 16 17 // We reserve the V8_* prefix for macros defined in V8 public API and 18 // assume there are no name conflicts with the embedder's code. 19 20 /** 21 * The v8 JavaScript engine. 22 */ 23 namespace v8 { 24 25 class PageAllocator; 26 class Platform; 27 template <class K, class V, class T> 28 class PersistentValueMapBase; 29 30 /** 31 * EntropySource is used as a callback function when v8 needs a source 32 * of entropy. 33 */ 34 using EntropySource = bool (*)(unsigned char* buffer, size_t length); 35 36 /** 37 * ReturnAddressLocationResolver is used as a callback function when v8 is 38 * resolving the location of a return address on the stack. Profilers that 39 * change the return address on the stack can use this to resolve the stack 40 * location to wherever the profiler stashed the original return address. 41 * 42 * \param return_addr_location A location on stack where a machine 43 * return address resides. 44 * \returns Either return_addr_location, or else a pointer to the profiler's 45 * copy of the original return address. 46 * 47 * \note The resolver function must not cause garbage collection. 48 */ 49 using ReturnAddressLocationResolver = 50 uintptr_t (*)(uintptr_t return_addr_location); 51 52 using DcheckErrorCallback = void (*)(const char* file, int line, 53 const char* message); 54 55 /** 56 * Container class for static utility functions. 57 */ 58 class V8_EXPORT V8 { 59 public: 60 /** 61 * Hand startup data to V8, in case the embedder has chosen to build 62 * V8 with external startup data. 63 * 64 * Note: 65 * - By default the startup data is linked into the V8 library, in which 66 * case this function is not meaningful. 67 * - If this needs to be called, it needs to be called before V8 68 * tries to make use of its built-ins. 69 * - To avoid unnecessary copies of data, V8 will point directly into the 70 * given data blob, so pretty please keep it around until V8 exit. 71 * - Compression of the startup blob might be useful, but needs to 72 * handled entirely on the embedders' side. 73 * - The call will abort if the data is invalid. 74 */ 75 static void SetSnapshotDataBlob(StartupData* startup_blob); 76 77 /** Set the callback to invoke in case of Dcheck failures. */ 78 static void SetDcheckErrorHandler(DcheckErrorCallback that); 79 80 /** 81 * Sets V8 flags from a string. 82 */ 83 static void SetFlagsFromString(const char* str); 84 static void SetFlagsFromString(const char* str, size_t length); 85 86 /** 87 * Sets V8 flags from the command line. 88 */ 89 static void SetFlagsFromCommandLine(int* argc, char** argv, 90 bool remove_flags); 91 92 /** Get the version string. */ 93 static const char* GetVersion(); 94 95 /** 96 * Initializes V8. This function needs to be called before the first Isolate 97 * is created. It always returns true. 98 */ Initialize()99 V8_INLINE static bool Initialize() { 100 const int kBuildConfiguration = 101 (internal::PointerCompressionIsEnabled() ? kPointerCompression : 0) | 102 (internal::SmiValuesAre31Bits() ? k31BitSmis : 0) | 103 (internal::SandboxedExternalPointersAreEnabled() 104 ? kSandboxedExternalPointers 105 : 0) | 106 (internal::SandboxIsEnabled() ? kSandbox : 0); 107 return Initialize(kBuildConfiguration); 108 } 109 110 /** 111 * Allows the host application to provide a callback which can be used 112 * as a source of entropy for random number generators. 113 */ 114 static void SetEntropySource(EntropySource source); 115 116 /** 117 * Allows the host application to provide a callback that allows v8 to 118 * cooperate with a profiler that rewrites return addresses on stack. 119 */ 120 static void SetReturnAddressLocationResolver( 121 ReturnAddressLocationResolver return_address_resolver); 122 123 /** 124 * Releases any resources used by v8 and stops any utility threads 125 * that may be running. Note that disposing v8 is permanent, it 126 * cannot be reinitialized. 127 * 128 * It should generally not be necessary to dispose v8 before exiting 129 * a process, this should happen automatically. It is only necessary 130 * to use if the process needs the resources taken up by v8. 131 */ 132 static bool Dispose(); 133 134 /** 135 * Initialize the ICU library bundled with V8. The embedder should only 136 * invoke this method when using the bundled ICU. Returns true on success. 137 * 138 * If V8 was compiled with the ICU data in an external file, the location 139 * of the data file has to be provided. 140 */ 141 static bool InitializeICU(const char* icu_data_file = nullptr); 142 143 /** 144 * Initialize the ICU library bundled with V8. The embedder should only 145 * invoke this method when using the bundled ICU. If V8 was compiled with 146 * the ICU data in an external file and when the default location of that 147 * file should be used, a path to the executable must be provided. 148 * Returns true on success. 149 * 150 * The default is a file called icudtl.dat side-by-side with the executable. 151 * 152 * Optionally, the location of the data file can be provided to override the 153 * default. 154 */ 155 static bool InitializeICUDefaultLocation(const char* exec_path, 156 const char* icu_data_file = nullptr); 157 158 /** 159 * Initialize the external startup data. The embedder only needs to 160 * invoke this method when external startup data was enabled in a build. 161 * 162 * If V8 was compiled with the startup data in an external file, then 163 * V8 needs to be given those external files during startup. There are 164 * three ways to do this: 165 * - InitializeExternalStartupData(const char*) 166 * This will look in the given directory for the file "snapshot_blob.bin". 167 * - InitializeExternalStartupDataFromFile(const char*) 168 * As above, but will directly use the given file name. 169 * - Call SetSnapshotDataBlob. 170 * This will read the blobs from the given data structure and will 171 * not perform any file IO. 172 */ 173 static void InitializeExternalStartupData(const char* directory_path); 174 static void InitializeExternalStartupDataFromFile(const char* snapshot_blob); 175 176 /** 177 * Sets the v8::Platform to use. This should be invoked before V8 is 178 * initialized. 179 */ 180 static void InitializePlatform(Platform* platform); 181 182 /** 183 * Clears all references to the v8::Platform. This should be invoked after 184 * V8 was disposed. 185 */ 186 static void DisposePlatform(); 187 V8_DEPRECATED("Use DisposePlatform()") ShutdownPlatform()188 static void ShutdownPlatform() { DisposePlatform(); } 189 190 #ifdef V8_SANDBOX 191 // 192 // Sandbox related API. 193 // 194 // This API is not yet stable and subject to changes in the future. 195 // 196 197 /** 198 * Initializes the V8 sandbox. 199 * 200 * This must be invoked after the platform was initialized but before V8 is 201 * initialized. The sandbox is torn down during platform shutdown. 202 * Returns true on success, false otherwise. 203 * 204 * TODO(saelo) Once it is no longer optional to initialize the sandbox when 205 * compiling with V8_SANDBOX, the sandbox initialization will likely happen 206 * as part of V8::Initialize, at which point this function should be removed. 207 */ 208 static bool InitializeSandbox(); 209 V8_DEPRECATE_SOON("Use InitializeSandbox()") InitializeVirtualMemoryCage()210 static bool InitializeVirtualMemoryCage() { return InitializeSandbox(); } 211 212 /** 213 * Provides access to the virtual address subspace backing the sandbox. 214 * 215 * This can be used to allocate pages inside the sandbox, for example to 216 * obtain virtual memory for ArrayBuffer backing stores, which must be 217 * located inside the sandbox. 218 * 219 * It should be assumed that an attacker can corrupt data inside the sandbox, 220 * and so in particular the contents of pages allocagted in this virtual 221 * address space, arbitrarily and concurrently. Due to this, it is 222 * recommended to to only place pure data buffers in them. 223 * 224 * This function must only be called after initializing the sandbox. 225 */ 226 static VirtualAddressSpace* GetSandboxAddressSpace(); 227 V8_DEPRECATE_SOON("Use GetSandboxAddressSpace()") 228 static PageAllocator* GetVirtualMemoryCagePageAllocator(); 229 230 /** 231 * Returns the size of the sandbox in bytes. 232 * 233 * If the sandbox has not been initialized, or if the initialization failed, 234 * this returns zero. 235 */ 236 static size_t GetSandboxSizeInBytes(); 237 V8_DEPRECATE_SOON("Use GetSandboxSizeInBytes()") GetVirtualMemoryCageSizeInBytes()238 static size_t GetVirtualMemoryCageSizeInBytes() { 239 return GetSandboxSizeInBytes(); 240 } 241 242 /** 243 * Returns whether the sandbox is configured securely. 244 * 245 * If V8 cannot create a proper sandbox, it will fall back to creating a 246 * sandbox that doesn't have the desired security properties but at least 247 * still allows V8 to function. This API can be used to determine if such an 248 * insecure sandbox is being used, in which case it will return false. 249 */ 250 static bool IsSandboxConfiguredSecurely(); 251 V8_DEPRECATE_SOON("Use IsSandboxConfiguredSecurely()") IsUsingSecureVirtualMemoryCage()252 static bool IsUsingSecureVirtualMemoryCage() { 253 return IsSandboxConfiguredSecurely(); 254 } 255 #endif 256 257 /** 258 * Activate trap-based bounds checking for WebAssembly. 259 * 260 * \param use_v8_signal_handler Whether V8 should install its own signal 261 * handler or rely on the embedder's. 262 */ 263 static bool EnableWebAssemblyTrapHandler(bool use_v8_signal_handler); 264 265 #if defined(V8_OS_WIN) 266 /** 267 * On Win64, by default V8 does not emit unwinding data for jitted code, 268 * which means the OS cannot walk the stack frames and the system Structured 269 * Exception Handling (SEH) cannot unwind through V8-generated code: 270 * https://code.google.com/p/v8/issues/detail?id=3598. 271 * 272 * This function allows embedders to register a custom exception handler for 273 * exceptions in V8-generated code. 274 */ 275 static void SetUnhandledExceptionCallback( 276 UnhandledExceptionCallback unhandled_exception_callback); 277 #endif 278 279 /** 280 * Allows the host application to provide a callback that will be called when 281 * v8 has encountered a fatal failure to allocate memory and is about to 282 * terminate. 283 */ 284 285 static void SetFatalMemoryErrorCallback(OOMErrorCallback oom_error_callback); 286 287 /** 288 * Get statistics about the shared memory usage. 289 */ 290 static void GetSharedMemoryStatistics(SharedMemoryStatistics* statistics); 291 292 private: 293 V8(); 294 295 enum BuildConfigurationFeatures { 296 kPointerCompression = 1 << 0, 297 k31BitSmis = 1 << 1, 298 kSandboxedExternalPointers = 1 << 2, 299 kSandbox = 1 << 3, 300 }; 301 302 /** 303 * Checks that the embedder build configuration is compatible with 304 * the V8 binary and if so initializes V8. 305 */ 306 static bool Initialize(int build_config); 307 308 friend class Context; 309 template <class K, class V, class T> 310 friend class PersistentValueMapBase; 311 }; 312 313 } // namespace v8 314 315 #endif // INCLUDE_V8_INITIALIZATION_H_ 316