Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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,
74 CommandLineOptions* inputs) {
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);
143 CommandLineOptions inputs(argc);
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
239 Dart_DumpSnapshotInformationAsJson(info, &out, &out_len);
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
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:277
static bool EntropySource(uint8_t *buffer, intptr_t length)
Definition dartutils.cc:312
static void CloseFile(void *stream)
Definition dartutils.cc:307
static void * OpenFile(const char *name, bool write)
Definition dartutils.cc:265
static void WriteFile(const void *buffer, intptr_t num_bytes, void *stream)
Definition dartutils.cc:298
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:839
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
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)
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:56
va_start(args, format)
const uint8_t * vm_snapshot_instructions
Definition main_impl.cc:57
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)
void * OpenFile(const char *name, bool write)
Dart_ShutdownIsolate()
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)
Definition main.py:1
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition globals.h:697
Dart_FileReadCallback file_read
Definition dart_api.h:954
const uint8_t * vm_snapshot_data
Definition dart_api.h:910
Dart_FileOpenCallback file_open
Definition dart_api.h:953
Dart_FileWriteCallback file_write
Definition dart_api.h:955
Dart_EntropySource entropy_source
Definition dart_api.h:957
const uint8_t * vm_snapshot_instructions
Definition dart_api.h:918
Dart_FileCloseCallback file_close
Definition dart_api.h:956
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.
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf *loaded)