• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 namespace flutter {
16 
17 const char* DartSnapshot::kVMDataSymbol = "kDartVmSnapshotData";
18 const char* DartSnapshot::kVMInstructionsSymbol = "kDartVmSnapshotInstructions";
19 const char* DartSnapshot::kIsolateDataSymbol = "kDartIsolateSnapshotData";
20 const char* DartSnapshot::kIsolateInstructionsSymbol =
21     "kDartIsolateSnapshotInstructions";
22 
23 // On Windows and Android (in debug mode) the engine finds the Dart snapshot
24 // data through symbols that are statically linked into the executable.
25 // On other platforms this data is obtained by a dynamic symbol lookup.
26 #define DART_SNAPSHOT_STATIC_LINK \
27   (OS_WIN || (OS_ANDROID && FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG))
28 
29 #if !DART_SNAPSHOT_STATIC_LINK
30 
GetFileMapping(const std::string & path,bool executable)31 static std::unique_ptr<const fml::Mapping> GetFileMapping(
32     const std::string& path,
33     bool executable) {
34   if (executable) {
35     return fml::FileMapping::CreateReadExecute(path);
36   } else {
37     return fml::FileMapping::CreateReadOnly(path);
38   }
39 }
40 
41 // The first party embedders don't yet use the stable embedder API and depend on
42 // the engine figuring out the locations of the various heap and instructions
43 // buffers. Consequently, the engine had baked in opinions about where these
44 // buffers would reside and how they would be packaged (examples, in an external
45 // dylib, in the same dylib, at a path, at a path relative to and FD, etc..). As
46 // the needs of the platforms changed, the lack of an API meant that the engine
47 // had to be patched to look for new fields in the settings object. This grew
48 // untenable and with the addition of the new Fuchsia embedder and the generic C
49 // embedder API, embedders could specify the mapping directly. Once everyone
50 // moves to the embedder API, this method can effectively be reduced to just
51 // invoking the embedder_mapping_callback directly.
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)52 static std::shared_ptr<const fml::Mapping> SearchMapping(
53     MappingCallback embedder_mapping_callback,
54     const std::string& file_path,
55     const std::vector<std::string>& native_library_path,
56     const char* native_library_symbol_name,
57     bool is_executable) {
58   // Ask the embedder. There is no fallback as we expect the embedders (via
59   // their embedding APIs) to just specify the mappings directly.
60   if (embedder_mapping_callback) {
61     return embedder_mapping_callback();
62   }
63 
64   // Attempt to open file at path specified.
65   if (file_path.size() > 0) {
66     if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
67       return file_mapping;
68     }
69   }
70 
71   // Look in application specified native library if specified.
72   for (const std::string& path : native_library_path) {
73     auto native_library = fml::NativeLibrary::Create(path.c_str());
74     auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
75         native_library, native_library_symbol_name);
76     if (symbol_mapping->GetMapping() != nullptr) {
77       return symbol_mapping;
78     }
79   }
80 
81   // Look inside the currently loaded process.
82   {
83     auto loaded_process = fml::NativeLibrary::CreateForCurrentProcess();
84     auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
85         loaded_process, native_library_symbol_name);
86     if (symbol_mapping->GetMapping() != nullptr) {
87       return symbol_mapping;
88     }
89   }
90 
91   return nullptr;
92 }
93 
94 #endif  // !DART_SNAPSHOT_STATIC_LINK
95 
ResolveVMData(const Settings & settings)96 static std::shared_ptr<const fml::Mapping> ResolveVMData(
97     const Settings& settings) {
98 #if DART_SNAPSHOT_STATIC_LINK
99   return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData, 0);
100 #else   // DART_SNAPSHOT_STATIC_LINK
101   return SearchMapping(
102       settings.vm_snapshot_data,          // embedder_mapping_callback
103       settings.vm_snapshot_data_path,     // file_path
104       settings.application_library_path,  // native_library_path
105       DartSnapshot::kVMDataSymbol,        // native_library_symbol_name
106       false                               // is_executable
107   );
108 #endif  // DART_SNAPSHOT_STATIC_LINK
109 }
110 
ResolveVMInstructions(const Settings & settings)111 static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
112     const Settings& settings) {
113 #if DART_SNAPSHOT_STATIC_LINK
114   return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions, 0);
115 #else   // DART_SNAPSHOT_STATIC_LINK
116   return SearchMapping(
117       settings.vm_snapshot_instr,           // embedder_mapping_callback
118       settings.vm_snapshot_instr_path,      // file_path
119       settings.application_library_path,    // native_library_path
120       DartSnapshot::kVMInstructionsSymbol,  // native_library_symbol_name
121       true                                  // is_executable
122   );
123 #endif  // DART_SNAPSHOT_STATIC_LINK
124 }
125 
ResolveIsolateData(const Settings & settings)126 static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
127     const Settings& settings) {
128 #if DART_SNAPSHOT_STATIC_LINK
129   return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData, 0);
130 #else   // DART_SNAPSHOT_STATIC_LINK
131   return SearchMapping(
132       settings.isolate_snapshot_data,       // embedder_mapping_callback
133       settings.isolate_snapshot_data_path,  // file_path
134       settings.application_library_path,    // native_library_path
135       DartSnapshot::kIsolateDataSymbol,     // native_library_symbol_name
136       false                                 // is_executable
137   );
138 #endif  // DART_SNAPSHOT_STATIC_LINK
139 }
140 
ResolveIsolateInstructions(const Settings & settings)141 static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
142     const Settings& settings) {
143 #if DART_SNAPSHOT_STATIC_LINK
144   return std::make_unique<fml::NonOwnedMapping>(
145       kDartIsolateSnapshotInstructions, 0);
146 #else   // DART_SNAPSHOT_STATIC_LINK
147   return SearchMapping(
148       settings.isolate_snapshot_instr,           // embedder_mapping_callback
149       settings.isolate_snapshot_instr_path,      // file_path
150       settings.application_library_path,         // native_library_path
151       DartSnapshot::kIsolateInstructionsSymbol,  // native_library_symbol_name
152       true                                       // is_executable
153   );
154 #endif  // DART_SNAPSHOT_STATIC_LINK
155 }
156 
VMSnapshotFromSettings(const Settings & settings)157 fml::RefPtr<DartSnapshot> DartSnapshot::VMSnapshotFromSettings(
158     const Settings& settings) {
159   TRACE_EVENT0("flutter", "DartSnapshot::VMSnapshotFromSettings");
160   auto snapshot =
161       fml::MakeRefCounted<DartSnapshot>(ResolveVMData(settings),         //
162                                         ResolveVMInstructions(settings)  //
163       );
164   if (snapshot->IsValid()) {
165     return snapshot;
166   }
167   return nullptr;
168 }
169 
IsolateSnapshotFromSettings(const Settings & settings)170 fml::RefPtr<DartSnapshot> DartSnapshot::IsolateSnapshotFromSettings(
171     const Settings& settings) {
172   TRACE_EVENT0("flutter", "DartSnapshot::IsolateSnapshotFromSettings");
173   auto snapshot =
174       fml::MakeRefCounted<DartSnapshot>(ResolveIsolateData(settings),         //
175                                         ResolveIsolateInstructions(settings)  //
176       );
177   if (snapshot->IsValid()) {
178     return snapshot;
179   }
180   return nullptr;
181 }
182 
Empty()183 fml::RefPtr<DartSnapshot> DartSnapshot::Empty() {
184   return fml::MakeRefCounted<DartSnapshot>(nullptr, nullptr);
185 }
186 
DartSnapshot(std::shared_ptr<const fml::Mapping> data,std::shared_ptr<const fml::Mapping> instructions)187 DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
188                            std::shared_ptr<const fml::Mapping> instructions)
189     : data_(std::move(data)), instructions_(std::move(instructions)) {}
190 
191 DartSnapshot::~DartSnapshot() = default;
192 
IsValid() const193 bool DartSnapshot::IsValid() const {
194   return static_cast<bool>(data_);
195 }
196 
IsValidForAOT() const197 bool DartSnapshot::IsValidForAOT() const {
198   return data_ && instructions_;
199 }
200 
GetDataMapping() const201 const uint8_t* DartSnapshot::GetDataMapping() const {
202   return data_ ? data_->GetMapping() : nullptr;
203 }
204 
GetInstructionsMapping() const205 const uint8_t* DartSnapshot::GetInstructionsMapping() const {
206   return instructions_ ? instructions_->GetMapping() : nullptr;
207 }
208 
209 }  // namespace flutter
210