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