Flutter Engine
dart_snapshot.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 #include "flutter/runtime/dart_snapshot.h"
6 
7 #include <sstream>
8 
9 #include "flutter/fml/native_library.h"
10 #include "flutter/fml/paths.h"
11 #include "flutter/fml/trace_event.h"
12 #include "flutter/lib/snapshot/snapshot.h"
13 #include "flutter/runtime/dart_vm.h"
14 #include "third_party/dart/runtime/include/dart_api.h"
15 
16 namespace flutter {
17 
18 const char* DartSnapshot::kVMDataSymbol = "kDartVmSnapshotData";
19 const char* DartSnapshot::kVMInstructionsSymbol = "kDartVmSnapshotInstructions";
20 const char* DartSnapshot::kIsolateDataSymbol = "kDartIsolateSnapshotData";
22  "kDartIsolateSnapshotInstructions";
23 
24 // On Windows and Android (in debug mode) the engine finds the Dart snapshot
25 // data through symbols that are statically linked into the executable.
26 // On other platforms this data is obtained by a dynamic symbol lookup.
27 #define DART_SNAPSHOT_STATIC_LINK \
28  ((OS_WIN || OS_ANDROID) && FLUTTER_JIT_RUNTIME)
29 
30 #if !DART_SNAPSHOT_STATIC_LINK
31 
32 static std::unique_ptr<const fml::Mapping> GetFileMapping(
33  const std::string& path,
34  bool executable) {
35  if (executable) {
37  } else {
39  }
40 }
41 
42 // The first party embedders don't yet use the stable embedder API and depend on
43 // the engine figuring out the locations of the various heap and instructions
44 // buffers. Consequently, the engine had baked in opinions about where these
45 // buffers would reside and how they would be packaged (examples, in an external
46 // dylib, in the same dylib, at a path, at a path relative to and FD, etc..). As
47 // the needs of the platforms changed, the lack of an API meant that the engine
48 // had to be patched to look for new fields in the settings object. This grew
49 // untenable and with the addition of the new Fuchsia embedder and the generic C
50 // embedder API, embedders could specify the mapping directly. Once everyone
51 // moves to the embedder API, this method can effectively be reduced to just
52 // invoking the embedder_mapping_callback directly.
53 static std::shared_ptr<const fml::Mapping> SearchMapping(
54  MappingCallback embedder_mapping_callback,
55  const std::string& file_path,
56  const std::vector<std::string>& native_library_path,
57  const char* native_library_symbol_name,
58  bool is_executable) {
59  // Ask the embedder. There is no fallback as we expect the embedders (via
60  // their embedding APIs) to just specify the mappings directly.
61  if (embedder_mapping_callback) {
62  return embedder_mapping_callback();
63  }
64 
65  // Attempt to open file at path specified.
66  if (file_path.size() > 0) {
67  if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
68  return file_mapping;
69  }
70  }
71 
72  // Look in application specified native library if specified.
73  for (const std::string& path : native_library_path) {
74  auto native_library = fml::NativeLibrary::Create(path.c_str());
75  auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
76  native_library, native_library_symbol_name);
77  if (symbol_mapping->GetMapping() != nullptr) {
78  return symbol_mapping;
79  }
80  }
81 
82  // Look inside the currently loaded process.
83  {
84  auto loaded_process = fml::NativeLibrary::CreateForCurrentProcess();
85  auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
86  loaded_process, native_library_symbol_name);
87  if (symbol_mapping->GetMapping() != nullptr) {
88  return symbol_mapping;
89  }
90  }
91 
92  return nullptr;
93 }
94 
95 #endif // !DART_SNAPSHOT_STATIC_LINK
96 
97 static std::shared_ptr<const fml::Mapping> ResolveVMData(
98  const Settings& settings) {
99 #if DART_SNAPSHOT_STATIC_LINK
100  return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData, 0);
101 #else // DART_SNAPSHOT_STATIC_LINK
102  return SearchMapping(
103  settings.vm_snapshot_data, // embedder_mapping_callback
104  settings.vm_snapshot_data_path, // file_path
105  settings.application_library_path, // native_library_path
106  DartSnapshot::kVMDataSymbol, // native_library_symbol_name
107  false // is_executable
108  );
109 #endif // DART_SNAPSHOT_STATIC_LINK
110 }
111 
112 static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
113  const Settings& settings) {
114 #if DART_SNAPSHOT_STATIC_LINK
115  return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions, 0);
116 #else // DART_SNAPSHOT_STATIC_LINK
117  return SearchMapping(
118  settings.vm_snapshot_instr, // embedder_mapping_callback
119  settings.vm_snapshot_instr_path, // file_path
120  settings.application_library_path, // native_library_path
121  DartSnapshot::kVMInstructionsSymbol, // native_library_symbol_name
122  true // is_executable
123  );
124 #endif // DART_SNAPSHOT_STATIC_LINK
125 }
126 
127 static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
128  const Settings& settings) {
129 #if DART_SNAPSHOT_STATIC_LINK
130  return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData, 0);
131 #else // DART_SNAPSHOT_STATIC_LINK
132  return SearchMapping(
133  settings.isolate_snapshot_data, // embedder_mapping_callback
134  settings.isolate_snapshot_data_path, // file_path
135  settings.application_library_path, // native_library_path
136  DartSnapshot::kIsolateDataSymbol, // native_library_symbol_name
137  false // is_executable
138  );
139 #endif // DART_SNAPSHOT_STATIC_LINK
140 }
141 
142 static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
143  const Settings& settings) {
144 #if DART_SNAPSHOT_STATIC_LINK
145  return std::make_unique<fml::NonOwnedMapping>(
147 #else // DART_SNAPSHOT_STATIC_LINK
148  return SearchMapping(
149  settings.isolate_snapshot_instr, // embedder_mapping_callback
150  settings.isolate_snapshot_instr_path, // file_path
151  settings.application_library_path, // native_library_path
152  DartSnapshot::kIsolateInstructionsSymbol, // native_library_symbol_name
153  true // is_executable
154  );
155 #endif // DART_SNAPSHOT_STATIC_LINK
156 }
157 
159  const Settings& settings) {
160  TRACE_EVENT0("flutter", "DartSnapshot::VMSnapshotFromSettings");
161  auto snapshot =
162  fml::MakeRefCounted<DartSnapshot>(ResolveVMData(settings), //
163  ResolveVMInstructions(settings) //
164  );
165  if (snapshot->IsValid()) {
166  return snapshot;
167  }
168  return nullptr;
169 }
170 
172  const Settings& settings) {
173  TRACE_EVENT0("flutter", "DartSnapshot::IsolateSnapshotFromSettings");
174  auto snapshot =
175  fml::MakeRefCounted<DartSnapshot>(ResolveIsolateData(settings), //
176  ResolveIsolateInstructions(settings) //
177  );
178  if (snapshot->IsValid()) {
179  return snapshot;
180  }
181  return nullptr;
182 }
183 
184 DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
185  std::shared_ptr<const fml::Mapping> instructions)
186  : data_(std::move(data)), instructions_(std::move(instructions)) {}
187 
188 DartSnapshot::~DartSnapshot() = default;
189 
190 bool DartSnapshot::IsValid() const {
191  return static_cast<bool>(data_);
192 }
193 
195  return data_ && instructions_;
196 }
197 
198 const uint8_t* DartSnapshot::GetDataMapping() const {
199  return data_ ? data_->GetMapping() : nullptr;
200 }
201 
202 const uint8_t* DartSnapshot::GetInstructionsMapping() const {
203  return instructions_ ? instructions_->GetMapping() : nullptr;
204 }
205 
207  return ::Dart_DetectNullSafety(
208  nullptr, // script_uri (unsupported by Flutter)
209  nullptr, // package_config (package resolution of parent used)
210  nullptr, // original_working_directory (no package config)
211  GetDataMapping(), // snapshot_data
212  GetInstructionsMapping(), // snapshot_instructions
213  kernel ? kernel->GetMapping() : nullptr, // kernel_buffer
214  kernel ? kernel->GetSize() : 0u // kernel_buffer_size
215  );
216 }
217 
218 } // namespace flutter
const uint8_t kDartVmSnapshotData[]
static std::shared_ptr< const fml::Mapping > ResolveVMInstructions(const Settings &settings)
MappingCallback isolate_snapshot_instr
Definition: settings.h:80
std::function< std::unique_ptr< fml::Mapping >(void)> MappingCallback
Definition: settings.h:56
static std::shared_ptr< const fml::Mapping > SearchMapping(MappingCallback embedder_mapping_callback, const std::string &file_path, const std::vector< std::string > &native_library_path, const char *native_library_symbol_name, bool is_executable)
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
static std::unique_ptr< FileMapping > CreateReadExecute(const std::string &path)
Definition: mapping.cc:42
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
static fml::RefPtr< NativeLibrary > CreateForCurrentProcess()
static std::unique_ptr< const fml::Mapping > GetFileMapping(const std::string &path, bool executable)
virtual size_t GetSize() const =0
const uint8_t * GetInstructionsMapping() const
Get a pointer to the read-execute mapping to the instructions snapshot.
std::string isolate_snapshot_instr_path
Definition: settings.h:79
static fml::RefPtr< DartSnapshot > IsolateSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the isolate snapshot. ...
MappingCallback vm_snapshot_data
Definition: settings.h:73
const uint8_t kDartIsolateSnapshotInstructions[]
virtual const uint8_t * GetMapping() const =0
static std::shared_ptr< const fml::Mapping > ResolveIsolateInstructions(const Settings &settings)
static const char * kIsolateDataSymbol
Definition: dart_snapshot.h:58
std::string isolate_snapshot_data_path
Definition: settings.h:77
bool IsNullSafetyEnabled(const fml::Mapping *application_kernel_mapping) const
static const char * kIsolateInstructionsSymbol
Definition: dart_snapshot.h:63
static fml::RefPtr< NativeLibrary > Create(const char *path)
static std::shared_ptr< const fml::Mapping > ResolveIsolateData(const Settings &settings)
const uint8_t kDartIsolateSnapshotData[]
static std::shared_ptr< const fml::Mapping > ResolveVMData(const Settings &settings)
MappingCallback isolate_snapshot_data
Definition: settings.h:78
std::vector< std::string > application_library_path
Definition: settings.h:89
static fml::RefPtr< DartSnapshot > VMSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the core snapshot.
std::string vm_snapshot_data_path
Definition: settings.h:72
bool IsValidForAOT() const
Determines if this snapshot contains both the heap and instructions components. This is only useful w...
MappingCallback vm_snapshot_instr
Definition: settings.h:75
const uint8_t kDartVmSnapshotInstructions[]
std::string vm_snapshot_instr_path
Definition: settings.h:74
const uint8_t * GetDataMapping() const
Get a pointer to the read-only mapping to the heap snapshot.
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition: mapping.cc:18
static const char * kVMDataSymbol
Definition: dart_snapshot.h:48
bool IsValid() const
Determines if this snapshot contains a heap component. Since the instructions component is optional...
static const char * kVMInstructionsSymbol
Definition: dart_snapshot.h:53