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 */
23namespace v8 {
24
25class PageAllocator;
26class Platform;
27template <class K, class V, class T>
28class PersistentValueMapBase;
29
30/**
31 * EntropySource is used as a callback function when v8 needs a source
32 * of entropy.
33 */
34using 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 */
49using ReturnAddressLocationResolver =
50    uintptr_t (*)(uintptr_t return_addr_location);
51
52using DcheckErrorCallback = void (*)(const char* file, int line,
53                                     const char* message);
54
55/**
56 * Container class for static utility functions.
57 */
58class 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   */
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()")
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()")
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()")
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()")
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