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::SandboxIsEnabled() ? kSandbox : 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 DisposePlatform();
184 
185 #if defined(V8_ENABLE_SANDBOX)
186   /**
187    * Returns true if the sandbox is configured securely.
188    *
189    * If V8 cannot create a regular sandbox during initialization, for example
190    * because not enough virtual address space can be reserved, it will instead
191    * create a fallback sandbox that still allows it to function normally but
192    * does not have the same security properties as a regular sandbox. This API
193    * can be used to determine if such a fallback sandbox is being used, in
194    * which case it will return false.
195    */
196   static bool IsSandboxConfiguredSecurely();
197 
198   /**
199    * Provides access to the virtual address subspace backing the sandbox.
200    *
201    * This can be used to allocate pages inside the sandbox, for example to
202    * obtain virtual memory for ArrayBuffer backing stores, which must be
203    * located inside the sandbox.
204    *
205    * It should be assumed that an attacker can corrupt data inside the sandbox,
206    * and so in particular the contents of pages allocagted in this virtual
207    * address space, arbitrarily and concurrently. Due to this, it is
208    * recommended to to only place pure data buffers in them.
209    */
210   static VirtualAddressSpace* GetSandboxAddressSpace();
211 
212   /**
213    * Returns the size of the sandbox in bytes.
214    *
215    * This represents the size of the address space that V8 can directly address
216    * and in which it allocates its objects.
217    */
218   static size_t GetSandboxSizeInBytes();
219 
220   /**
221    * Returns the size of the address space reservation backing the sandbox.
222    *
223    * This may be larger than the sandbox (i.e. |GetSandboxSizeInBytes()|) due
224    * to surrounding guard regions, or may be smaller than the sandbox in case a
225    * fallback sandbox is being used, which will use a smaller virtual address
226    * space reservation. In the latter case this will also be different from
227    * |GetSandboxAddressSpace()->size()| as that will cover a larger part of the
228    * address space than what has actually been reserved.
229    */
230   static size_t GetSandboxReservationSizeInBytes();
231 #endif  // V8_ENABLE_SANDBOX
232 
233   /**
234    * Activate trap-based bounds checking for WebAssembly.
235    *
236    * \param use_v8_signal_handler Whether V8 should install its own signal
237    * handler or rely on the embedder's.
238    */
239   static bool EnableWebAssemblyTrapHandler(bool use_v8_signal_handler);
240 
241 #if defined(V8_OS_WIN)
242   /**
243    * On Win64, by default V8 does not emit unwinding data for jitted code,
244    * which means the OS cannot walk the stack frames and the system Structured
245    * Exception Handling (SEH) cannot unwind through V8-generated code:
246    * https://code.google.com/p/v8/issues/detail?id=3598.
247    *
248    * This function allows embedders to register a custom exception handler for
249    * exceptions in V8-generated code.
250    */
251   static void SetUnhandledExceptionCallback(
252       UnhandledExceptionCallback callback);
253 #endif
254 
255   /**
256    * Allows the host application to provide a callback that will be called when
257    * v8 has encountered a fatal failure to allocate memory and is about to
258    * terminate.
259    */
260   static void SetFatalMemoryErrorCallback(OOMErrorCallback callback);
261 
262   /**
263    * Get statistics about the shared memory usage.
264    */
265   static void GetSharedMemoryStatistics(SharedMemoryStatistics* statistics);
266 
267  private:
268   V8();
269 
270   enum BuildConfigurationFeatures {
271     kPointerCompression = 1 << 0,
272     k31BitSmis = 1 << 1,
273     kSandbox = 1 << 2,
274   };
275 
276   /**
277    * Checks that the embedder build configuration is compatible with
278    * the V8 binary and if so initializes V8.
279    */
280   static bool Initialize(int build_config);
281 
282   friend class Context;
283   template <class K, class V, class T>
284   friend class PersistentValueMapBase;
285 };
286 
287 }  // namespace v8
288 
289 #endif  // INCLUDE_V8_INITIALIZATION_H_
290