Flutter Engine
The Flutter Engine
analyze_snapshot.cc
Go to the documentation of this file.
1// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "bin/elf_loader.h"
6#include "bin/error_exit.h"
7#include "bin/file.h"
8
9#include "bin/options.h"
10#include "bin/platform.h"
11
12#if defined(TARGET_ARCH_IS_64_BIT) && defined(DART_PRECOMPILED_RUNTIME) && \
13 (defined(DART_TARGET_OS_ANDROID) || defined(DART_TARGET_OS_LINUX))
14#define SUPPORT_ANALYZE_SNAPSHOT
15#endif
16
17#ifdef SUPPORT_ANALYZE_SNAPSHOT
19#endif
20
21namespace dart {
22namespace bin {
23#ifdef SUPPORT_ANALYZE_SNAPSHOT
24#define STRING_OPTIONS_LIST(V) V(out, out_path)
25
26#define BOOL_OPTIONS_LIST(V) \
27 V(help, help) \
28 V(sdk_version, sdk_version)
29
30#define STRING_OPTION_DEFINITION(flag, variable) \
31 static const char* variable = nullptr; \
32 DEFINE_STRING_OPTION(flag, variable)
34#undef STRING_OPTION_DEFINITION
35
36#define BOOL_OPTION_DEFINITION(flag, variable) \
37 static bool variable = false; \
38 DEFINE_BOOL_OPTION(flag, variable)
40#undef BOOL_OPTION_DEFINITION
41
42// clang-format off
43static void PrintUsage() {
45"Usage: analyze_snapshot [<vm-flags>] [<options>] <snapshot_data> \n"
46" \n"
47"Common options: \n"
48"--help \n"
49" Display this message. \n"
50"--sdk_version \n"
51" Print the SDK version. \n"
52"--out \n"
53" Path to generate the analysis results JSON. \n"
54"If omitting [<vm-flags>] the VM parsing the snapshot is created with the \n"
55"following default flags: \n"
56"--enable_mirrors=false \n"
57"--background_compilation \n"
58"--precompilation \n"
59" \n"
60"\n");
61}
62// clang-format on
63
64const uint8_t* vm_snapshot_data = nullptr;
65const uint8_t* vm_snapshot_instructions = nullptr;
66const uint8_t* vm_isolate_data = nullptr;
67const uint8_t* vm_isolate_instructions = nullptr;
68
69// Parse out the command line arguments. Returns -1 if the arguments
70// are incorrect, 0 otherwise.
71static int ParseArguments(int argc,
72 char** argv,
73 CommandLineOptions* vm_options,
75 // Skip the binary name.
76 int i = 1;
77
78 // Parse out the vm options.
79 while ((i < argc) && OptionProcessor::IsValidShortFlag(argv[i])) {
80 if (OptionProcessor::TryProcess(argv[i], vm_options)) {
81 i += 1;
82 continue;
83 }
84 vm_options->AddArgument(argv[i]);
85 i += 1;
86 }
87
88 // Parse out remaining inputs.
89 while (i < argc) {
90 inputs->AddArgument(argv[i]);
91 i++;
92 }
93
94 if (help) {
95 PrintUsage();
97 } else if (sdk_version) {
98 Syslog::PrintErr("Dart SDK version: %s\n", Dart_VersionString());
100 }
101
102 // Verify consistency of arguments.
103 if (inputs->count() < 1) {
104 Syslog::PrintErr("At least one input is required\n");
105 return -1;
106 }
107 return 0;
108}
109
110PRINTF_ATTRIBUTE(1, 2) static void PrintErrAndExit(const char* format, ...) {
111 va_list args;
114 va_end(args);
115
119}
120
121static File* OpenFile(const char* filename) {
122 File* file = File::Open(nullptr, filename, File::kWriteTruncate);
123 if (file == nullptr) {
124 PrintErrAndExit("Error: Unable to write file: %s\n\n", filename);
125 }
126 return file;
127}
128
129static void WriteFile(const char* filename,
130 const char* buffer,
131 const intptr_t size) {
132 File* file = OpenFile(filename);
134 if (!file->WriteFully(buffer, size)) {
135 PrintErrAndExit("Error: Unable to write file: %s\n\n", filename);
136 }
137}
138
139int RunAnalyzer(int argc, char** argv) {
140 // Constant mirrors gen_snapshot binary, subject to change.
141 const int EXTRA_VM_ARGUMENTS = 7;
142 CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
144 // Parse command line arguments.
145 if (ParseArguments(argc, argv, &vm_options, &inputs) < 0) {
146 PrintUsage();
147 return kErrorExitCode;
148 }
149 if (out_path == nullptr) {
150 Syslog::PrintErr("No output path provided.\n");
151 return kErrorExitCode;
152 }
153
154 // Initialize VM with default flags if none are provided.
155 // TODO(#47924): Implement auto-parsing of flags from the snapshot file.
156 if (vm_options.count() == 0) {
157 vm_options.AddArgument("--enable_mirrors=false");
158 vm_options.AddArgument("--background_compilation");
159 vm_options.AddArgument("--precompilation");
160 }
161
162 char* error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
163 if (error != nullptr) {
164 Syslog::PrintErr("Setting VM flags failed: %s\n", error);
165 free(error);
166 return kErrorExitCode;
167 }
168
169 const char* script_name = nullptr;
170 script_name = inputs.GetArgument(0);
171
172 // Dart_LoadELF will crash on nonexistent file non-gracefully
173 // even though it should return `nullptr`.
174 File* const file = File::Open(/*namespc=*/nullptr, script_name, File::kRead);
175 if (file == nullptr) {
176 Syslog::PrintErr("Snapshot file does not exist\n");
177 return kErrorExitCode;
178 }
179 file->Release();
180
181 const char* loader_error = nullptr;
182 Dart_LoadedElf* loaded_elf = Dart_LoadELF(
183 script_name, 0, &loader_error, &vm_snapshot_data,
184 &vm_snapshot_instructions, &vm_isolate_data, &vm_isolate_instructions);
185
186 if (loaded_elf == nullptr) {
187 Syslog::PrintErr("Failure calling Dart_LoadELF:\n%s\n", loader_error);
188 return kErrorExitCode;
189 }
190
191 // Begin initialization
192 Dart_InitializeParams init_params = {};
193 memset(&init_params, 0, sizeof(init_params));
197
198 init_params.file_open = DartUtils::OpenFile;
199 init_params.file_read = DartUtils::ReadFile;
200 init_params.file_write = DartUtils::WriteFile;
201 init_params.file_close = DartUtils::CloseFile;
203#if defined(DART_HOST_OS_FUCHSIA)
204 init_params.vmex_resource = Platform::GetVMEXResource();
205#endif
206
207 error = Dart_Initialize(&init_params);
208 if (error != nullptr) {
209 Syslog::PrintErr("VM initialization failed: %s\n", error);
210 free(error);
211 return kErrorExitCode;
212 }
213
214 auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
215 new IsolateGroupData(nullptr, nullptr, nullptr, false));
216
217 Dart_IsolateFlags isolate_flags;
218 Dart_IsolateFlagsInitialize(&isolate_flags);
219
220 Dart_CreateIsolateGroup(nullptr, nullptr, vm_isolate_data,
221 vm_isolate_instructions, &isolate_flags,
222 isolate_group_data.get(),
223 /*isolate_data=*/nullptr, &error);
224
225 if (error != nullptr) {
226 Syslog::PrintErr("Dart_CreateIsolateGroup Error: %s\n", error);
227 free(error);
228 return kErrorExitCode;
229 }
230
233 vm_isolate_instructions};
234
235 char* out = nullptr;
236 intptr_t out_len = 0;
237
240 WriteFile(out_path, out, out_len);
241
242 // Since ownership of the JSON buffer is ours, free before we exit.
243 free(out);
244
247 // Unload our DartELF to avoid leaks
248 Dart_UnloadELF(loaded_elf);
249 return 0;
250}
251#endif
252} // namespace bin
253} // namespace dart
254
255int main(int argc, char** argv) {
256#ifdef SUPPORT_ANALYZE_SNAPSHOT
257 return dart::bin::RunAnalyzer(argc, argv);
258#else
259 dart::Syslog::PrintErr("Unsupported platform.\n");
261 "Requires SDK with following "
262 "flags:\n\tTARGET_ARCH_IS_64_BIT\n\tDART_PRECOMPILED_RUNTIME\n\tDART_"
263 "TARGET_OS_ANDROID || DART_TARGET_OS_LINUX");
265#endif
266}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int main(int argc, char **argv)
static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
VPrintErr(format, args)
const char ** arguments() const
Definition: dartutils.h:63
void AddArgument(const char *argument)
Definition: dartutils.h:68
static void ReadFile(uint8_t **data, intptr_t *file_len, void *stream)
Definition: dartutils.cc:273
static bool EntropySource(uint8_t *buffer, intptr_t length)
Definition: dartutils.cc:308
static void CloseFile(void *stream)
Definition: dartutils.cc:303
static void * OpenFile(const char *name, bool write)
Definition: dartutils.cc:261
static void WriteFile(const void *buffer, intptr_t num_bytes, void *stream)
Definition: dartutils.cc:294
static File * Open(Namespace *namespc, const char *path, FileOpenMode mode)
@ kWriteTruncate
Definition: file.h:60
static bool TryProcess(const char *option, CommandLineOptions *options)
Definition: options.cc:34
static bool IsValidShortFlag(const char *name)
Definition: options.cc:16
static DART_NORETURN void Exit(int exit_code)
#define DART_INITIALIZE_PARAMS_CURRENT_VERSION
Definition: dart_api.h:840
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
#define BOOL_OPTIONS_LIST(V)
#define STRING_OPTION_DEFINITION(flag, variable)
#define BOOL_OPTION_DEFINITION(flag, variable)
#define STRING_OPTIONS_LIST(V)
Definition: gen_snapshot.cc:98
char ** argv
Definition: library.h:9
void WriteFile(const void *buffer, intptr_t num_bytes, void *stream)
const uint8_t * vm_snapshot_data
Definition: main_impl.cc:52
va_start(args, format)
const uint8_t * vm_snapshot_instructions
Definition: main_impl.cc:53
static void PrintUsage()
exit(kErrorExitCode)
constexpr int kErrorExitCode
Definition: error_exit.h:18
va_end(args)
static int ParseArguments(int argc, char **argv, CommandLineOptions *vm_options, CommandLineOptions *inputs)
PRINTF_ATTRIBUTE(1, 2) static void PrintErrAndExit(const char *format
void * OpenFile(const char *name, bool write)
Dart_ShutdownIsolate()
void Dart_DumpSnapshotInformationAsJson(const Dart_SnapshotAnalyzerInformation &info, char **buffer, intptr_t *buffer_length)
Definition: dart_vm.cc:33
DART_EXPORT void Dart_EnterScope()
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags *flags)
DART_EXPORT char * Dart_Initialize(Dart_InitializeParams *params)
DART_EXPORT const char * Dart_VersionString()
DART_EXPORT Dart_Isolate Dart_CreateIsolateGroup(const char *script_uri, const char *name, const uint8_t *snapshot_data, const uint8_t *snapshot_instructions, Dart_IsolateFlags *flags, void *isolate_group_data, void *isolate_data, char **error)
DART_EXPORT char * Dart_SetVMFlags(int argc, const char **argv)
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
help
Definition: zip.py:79
Dart_FileReadCallback file_read
Definition: dart_api.h:955
const uint8_t * vm_snapshot_data
Definition: dart_api.h:911
Dart_FileOpenCallback file_open
Definition: dart_api.h:954
Dart_FileWriteCallback file_write
Definition: dart_api.h:956
Dart_EntropySource entropy_source
Definition: dart_api.h:958
const uint8_t * vm_snapshot_instructions
Definition: dart_api.h:919
Dart_FileCloseCallback file_close
Definition: dart_api.h:957
DART_EXPORT Dart_LoadedElf * Dart_LoadELF(const char *filename, uint64_t file_offset, const char **error, const uint8_t **vm_snapshot_data, const uint8_t **vm_snapshot_instrs, const uint8_t **vm_isolate_data, const uint8_t **vm_isolate_instrs)
Please see documentation for Dart_LoadElf_Fd.
Definition: elf_loader.cc:590
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf *loaded)
Definition: elf_loader.cc:643