Flutter Engine
The 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
16namespace flutter {
17
18const char* DartSnapshot::kVMDataSymbol = "kDartVmSnapshotData";
19const char* DartSnapshot::kVMInstructionsSymbol = "kDartVmSnapshotInstructions";
20const 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 ((FML_OS_WIN || FML_OS_ANDROID) && FLUTTER_JIT_RUNTIME)
29
30#if !DART_SNAPSHOT_STATIC_LINK
31
32static 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.
53static std::shared_ptr<const fml::Mapping> SearchMapping(
54 const 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 // Note that mapping will be nullptr if the mapping callback returns an
63 // invalid mapping. If all the other methods for resolving the data also
64 // fail, the engine will stop with accompanying error logs.
65 if (auto mapping = embedder_mapping_callback()) {
66 return mapping;
67 }
68 }
69
70 // Attempt to open file at path specified.
71 if (!file_path.empty()) {
72 if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
73 return file_mapping;
74 }
75 }
76
77 // Look in application specified native library if specified.
78 for (const std::string& path : native_library_path) {
79 auto native_library = fml::NativeLibrary::Create(path.c_str());
80 auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
81 native_library, native_library_symbol_name);
82 if (symbol_mapping->GetMapping() != nullptr) {
83 return symbol_mapping;
84 }
85 }
86
87 // Look inside the currently loaded process.
88 {
89 auto loaded_process = fml::NativeLibrary::CreateForCurrentProcess();
90 auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
91 loaded_process, native_library_symbol_name);
92 if (symbol_mapping->GetMapping() != nullptr) {
93 return symbol_mapping;
94 }
95 }
96
97 return nullptr;
98}
99
100#endif // !DART_SNAPSHOT_STATIC_LINK
101
102static std::shared_ptr<const fml::Mapping> ResolveVMData(
103 const Settings& settings) {
104#if DART_SNAPSHOT_STATIC_LINK
105 return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData,
106 0, // size
107 nullptr, // release_func
108 true // dontneed_safe
109 );
110#else // DART_SNAPSHOT_STATIC_LINK
111 return SearchMapping(
112 settings.vm_snapshot_data, // embedder_mapping_callback
113 settings.vm_snapshot_data_path, // file_path
114 settings.application_library_path, // native_library_path
115 DartSnapshot::kVMDataSymbol, // native_library_symbol_name
116 false // is_executable
117 );
118#endif // DART_SNAPSHOT_STATIC_LINK
119}
120
121static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
122 const Settings& settings) {
123#if DART_SNAPSHOT_STATIC_LINK
124 return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions,
125 0, // size
126 nullptr, // release_func
127 true // dontneed_safe
128 );
129#else // DART_SNAPSHOT_STATIC_LINK
130 return SearchMapping(
131 settings.vm_snapshot_instr, // embedder_mapping_callback
132 settings.vm_snapshot_instr_path, // file_path
133 settings.application_library_path, // native_library_path
134 DartSnapshot::kVMInstructionsSymbol, // native_library_symbol_name
135 true // is_executable
136 );
137#endif // DART_SNAPSHOT_STATIC_LINK
138}
139
140static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
141 const Settings& settings) {
142#if DART_SNAPSHOT_STATIC_LINK
143 return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData,
144 0, // size
145 nullptr, // release_func
146 true // dontneed_safe
147 );
148#else // DART_SNAPSHOT_STATIC_LINK
149 return SearchMapping(
150 settings.isolate_snapshot_data, // embedder_mapping_callback
151 settings.isolate_snapshot_data_path, // file_path
152 settings.application_library_path, // native_library_path
153 DartSnapshot::kIsolateDataSymbol, // native_library_symbol_name
154 false // is_executable
155 );
156#endif // DART_SNAPSHOT_STATIC_LINK
157}
158
159static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
160 const Settings& settings) {
161#if DART_SNAPSHOT_STATIC_LINK
162 return std::make_unique<fml::NonOwnedMapping>(
164 0, // size
165 nullptr, // release_func
166 true // dontneed_safe
167 );
168#else // DART_SNAPSHOT_STATIC_LINK
169 return SearchMapping(
170 settings.isolate_snapshot_instr, // embedder_mapping_callback
171 settings.isolate_snapshot_instr_path, // file_path
172 settings.application_library_path, // native_library_path
173 DartSnapshot::kIsolateInstructionsSymbol, // native_library_symbol_name
174 true // is_executable
175 );
176#endif // DART_SNAPSHOT_STATIC_LINK
177}
178
180 const Settings& settings) {
181 TRACE_EVENT0("flutter", "DartSnapshot::VMSnapshotFromSettings");
182 auto snapshot =
183 fml::MakeRefCounted<DartSnapshot>(ResolveVMData(settings), //
185 );
186 if (snapshot->IsValid()) {
187 return snapshot;
188 }
189 return nullptr;
190}
191
193 const Settings& settings) {
194 TRACE_EVENT0("flutter", "DartSnapshot::IsolateSnapshotFromSettings");
195 auto snapshot =
196 fml::MakeRefCounted<DartSnapshot>(ResolveIsolateData(settings), //
198 );
199 if (snapshot->IsValid()) {
200 return snapshot;
201 }
202 return nullptr;
203}
204
206 const std::shared_ptr<const fml::Mapping>& snapshot_data,
207 const std::shared_ptr<const fml::Mapping>& snapshot_instructions) {
208 auto snapshot =
209 fml::MakeRefCounted<DartSnapshot>(snapshot_data, snapshot_instructions);
210 if (snapshot->IsValid()) {
211 return snapshot;
212 }
213 return nullptr;
214}
215
217 const Settings& settings) {
218#if DART_SNAPSHOT_STATIC_LINK
219 return nullptr;
220#else // DART_SNAPSHOT_STATIC_LINK
221 if (settings.vmservice_snapshot_library_path.empty()) {
222 return nullptr;
223 }
224
225 std::shared_ptr<const fml::Mapping> snapshot_data =
226 SearchMapping(nullptr, "", settings.vmservice_snapshot_library_path,
228 std::shared_ptr<const fml::Mapping> snapshot_instructions =
229 SearchMapping(nullptr, "", settings.vmservice_snapshot_library_path,
231 return IsolateSnapshotFromMappings(snapshot_data, snapshot_instructions);
232#endif // DART_SNAPSHOT_STATIC_LINK
233}
234
235DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
236 std::shared_ptr<const fml::Mapping> instructions)
237 : data_(std::move(data)), instructions_(std::move(instructions)) {}
238
239DartSnapshot::~DartSnapshot() = default;
240
242 return static_cast<bool>(data_);
243}
244
246 return data_ && instructions_;
247}
248
249const uint8_t* DartSnapshot::GetDataMapping() const {
250 return data_ ? data_->GetMapping() : nullptr;
251}
252
254 return instructions_ ? instructions_->GetMapping() : nullptr;
255}
256
258 if (data_ && !data_->IsDontNeedSafe()) {
259 return false;
260 }
261 if (instructions_ && !instructions_->IsDontNeedSafe()) {
262 return false;
263 }
264 return true;
265}
266
269 nullptr, // script_uri (unsupported by Flutter)
270 nullptr, // package_config (package resolution of parent used)
271 nullptr, // original_working_directory (no package config)
272 GetDataMapping(), // snapshot_data
273 GetInstructionsMapping(), // snapshot_instructions
274 kernel ? kernel->GetMapping() : nullptr, // kernel_buffer
275 kernel ? kernel->GetSize() : 0u // kernel_buffer_size
276 );
277}
278
279} // namespace flutter
bool IsNullSafetyEnabled(const fml::Mapping *application_kernel_mapping) const
bool IsValidForAOT() const
Determines if this snapshot contains both the heap and instructions components. This is only useful w...
static fml::RefPtr< DartSnapshot > VMServiceIsolateSnapshotFromSettings(const Settings &settings)
Create an isolate snapshot specialized for launching the service isolate. Returns nullptr if no such ...
static fml::RefPtr< const DartSnapshot > VMSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the core snapshot.
static fml::RefPtr< DartSnapshot > IsolateSnapshotFromMappings(const std::shared_ptr< const fml::Mapping > &snapshot_data, const std::shared_ptr< const fml::Mapping > &snapshot_instructions)
Create an isolate snapshot from existing fml::Mappings.
bool IsValid() const
Determines if this snapshot contains a heap component. Since the instructions component is optional,...
const uint8_t * GetInstructionsMapping() const
Get a pointer to the read-execute mapping to the instructions snapshot.
static const char * kIsolateDataSymbol
Definition: dart_snapshot.h:58
static const char * kVMDataSymbol
Definition: dart_snapshot.h:48
const uint8_t * GetDataMapping() const
Get a pointer to the read-only mapping to the heap snapshot.
static const char * kIsolateInstructionsSymbol
Definition: dart_snapshot.h:63
bool IsDontNeedSafe() const
Returns whether both the data and instructions mappings are safe to use with madvise(DONTNEED).
static fml::RefPtr< const DartSnapshot > IsolateSnapshotFromSettings(const Settings &settings)
From the fields present in the given settings object, infer the isolate snapshot.
static const char * kVMInstructionsSymbol
Definition: dart_snapshot.h:53
static std::unique_ptr< FileMapping > CreateReadExecute(const std::string &path)
Definition: mapping.cc:44
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition: mapping.cc:20
virtual const uint8_t * GetMapping() const =0
virtual size_t GetSize() const =0
static fml::RefPtr< NativeLibrary > CreateForCurrentProcess()
static fml::RefPtr< NativeLibrary > Create(const char *path)
DART_EXPORT bool Dart_DetectNullSafety(const char *script_uri, const char *package_config, const char *original_working_directory, const uint8_t *snapshot_data, const uint8_t *snapshot_instructions, const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
const uint8_t kDartVmSnapshotData[]
const uint8_t kDartVmSnapshotInstructions[]
const uint8_t kDartIsolateSnapshotData[]
const uint8_t kDartIsolateSnapshotInstructions[]
static std::shared_ptr< const fml::Mapping > ResolveIsolateData(const Settings &settings)
static std::shared_ptr< const fml::Mapping > ResolveVMInstructions(const Settings &settings)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
static std::shared_ptr< const fml::Mapping > ResolveVMData(const Settings &settings)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition: switches.h:41
std::function< std::unique_ptr< fml::Mapping >(void)> MappingCallback
Definition: settings.h:93
static std::unique_ptr< const fml::Mapping > GetFileMapping(const std::string &path, bool executable)
static std::shared_ptr< const fml::Mapping > ResolveIsolateInstructions(const Settings &settings)
static std::shared_ptr< const fml::Mapping > SearchMapping(const 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)
Definition: ref_ptr.h:256
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131