mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Use ELF for Dart AOT snapshots on Fuchsia. (flutter/engine#13896)
We will still support loading blobs until build rules in Fuchsia are updated.
This commit is contained in:
parent
ce9df09c26
commit
5152ffa2bd
@ -982,8 +982,6 @@ FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/integration/meta/dart_
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/kernel/libraries.json
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/logging.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/main.cc
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/mapped_resource.cc
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/mapped_resource.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/meta/aot_product_runtime
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/meta/aot_runtime
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/meta/dart_aot_product_runner.cmx
|
||||
@ -1066,6 +1064,8 @@ FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exceptio
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/handle_exception.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/inlines.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/logging.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.cc
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.cc
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/tempfs.h
|
||||
FILE: ../../../flutter/shell/platform/fuchsia/runtime/dart/utils/vmo.cc
|
||||
|
||||
@ -31,8 +31,6 @@ template("runner") {
|
||||
"dart_runner.h",
|
||||
"logging.h",
|
||||
"main.cc",
|
||||
"mapped_resource.cc",
|
||||
"mapped_resource.h",
|
||||
"service_isolate.cc",
|
||||
"service_isolate.h",
|
||||
]
|
||||
@ -41,9 +39,15 @@ template("runner") {
|
||||
|
||||
dart_deps = []
|
||||
if (!invoker.product) {
|
||||
dart_deps += [ "//third_party/dart/runtime/bin:dart_io_api" ]
|
||||
dart_deps += [
|
||||
"//third_party/dart/runtime/bin:dart_io_api",
|
||||
"$flutter_root/shell/platform/fuchsia/runtime/dart/utils:utils",
|
||||
]
|
||||
} else {
|
||||
dart_deps += [ "//third_party/dart/runtime/bin:dart_io_api_product" ]
|
||||
dart_deps += [
|
||||
"//third_party/dart/runtime/bin:dart_io_api_product",
|
||||
"$flutter_root/shell/platform/fuchsia/runtime/dart/utils:utils_product",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
@ -52,7 +56,6 @@ template("runner") {
|
||||
"$flutter_root/runtime:libdart",
|
||||
"$flutter_root/shell/platform/fuchsia/dart-pkg/fuchsia",
|
||||
"$flutter_root/shell/platform/fuchsia/dart-pkg/zircon",
|
||||
"$flutter_root/shell/platform/fuchsia/runtime/dart/utils",
|
||||
"$fuchsia_sdk_root/pkg:async",
|
||||
"$fuchsia_sdk_root/pkg:async-cpp",
|
||||
"$fuchsia_sdk_root/pkg:async-default",
|
||||
@ -157,32 +160,24 @@ template("aot_runner_package") {
|
||||
|
||||
resources = []
|
||||
if (!invoker.product) {
|
||||
vmservice_data = rebase_path(
|
||||
vmservice_snapshot = rebase_path(
|
||||
get_label_info("vmservice:vmservice_snapshot", "target_gen_dir") +
|
||||
"/vmservice_data.aotsnapshot")
|
||||
vmservice_instr = rebase_path(
|
||||
get_label_info("vmservice:vmservice_snapshot", "target_gen_dir") +
|
||||
"/vmservice_instructions.aotsnapshot")
|
||||
"/vmservice_snapshot.so")
|
||||
dart_profiler_symbols = rebase_path(
|
||||
get_label_info(
|
||||
"$flutter_root/shell/platform/fuchsia/runtime/dart/profiler_symbols:dart_aot_runner",
|
||||
"target_gen_dir") + "/dart_aot_runner.dartprofilersymbols")
|
||||
|
||||
inputs = [
|
||||
vmservice_data,
|
||||
vmservice_instr,
|
||||
vmservice_snapshot,
|
||||
observatory_archive_file,
|
||||
dart_profiler_symbols,
|
||||
]
|
||||
|
||||
resources += [
|
||||
{
|
||||
path = vmservice_data
|
||||
dest = "vmservice_isolate_snapshot_data.bin"
|
||||
},
|
||||
{
|
||||
path = vmservice_instr
|
||||
dest = "vmservice_isolate_snapshot_instructions.bin"
|
||||
path = vmservice_snapshot
|
||||
dest = "vmservice_snapshot.so"
|
||||
},
|
||||
{
|
||||
path = rebase_path(observatory_archive_file)
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include <regex>
|
||||
#include <utility>
|
||||
|
||||
#include "runtime/dart/utils/files.h"
|
||||
#include "runtime/dart/utils/handle_exception.h"
|
||||
#include "runtime/dart/utils/inlines.h"
|
||||
#include "runtime/dart/utils/tempfs.h"
|
||||
@ -193,18 +194,18 @@ bool DartComponentController::SetupNamespace() {
|
||||
}
|
||||
|
||||
bool DartComponentController::SetupFromKernel() {
|
||||
MappedResource manifest;
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
dart_utils::MappedResource manifest;
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
namespace_, data_path_ + "/app.dilplist", manifest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, "pkg/data/isolate_core_snapshot_data.bin",
|
||||
isolate_snapshot_data_)) {
|
||||
return false;
|
||||
}
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, "pkg/data/isolate_core_snapshot_instructions.bin",
|
||||
isolate_snapshot_instructions_, true /* executable */)) {
|
||||
return false;
|
||||
@ -231,8 +232,9 @@ bool DartComponentController::SetupFromKernel() {
|
||||
std::string path = data_path_ + "/" + str.substr(start, end - start);
|
||||
start = end + 1;
|
||||
|
||||
MappedResource kernel;
|
||||
if (!MappedResource::LoadFromNamespace(namespace_, path, kernel)) {
|
||||
dart_utils::MappedResource kernel;
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(namespace_, path,
|
||||
kernel)) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Failed to find kernel: %s", path.c_str());
|
||||
Dart_ExitScope();
|
||||
return false;
|
||||
@ -262,25 +264,30 @@ bool DartComponentController::SetupFromKernel() {
|
||||
|
||||
bool DartComponentController::SetupFromAppSnapshot() {
|
||||
#if !defined(AOT_RUNTIME)
|
||||
// If we start generating app-jit snapshots, the code below should be able
|
||||
// handle that case without modification.
|
||||
return false;
|
||||
#else
|
||||
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
namespace_, data_path_ + "/isolate_snapshot_data.bin",
|
||||
isolate_snapshot_data_)) {
|
||||
return false;
|
||||
// Load the ELF snapshot as available, and fall back to a blobs snapshot
|
||||
// otherwise.
|
||||
const uint8_t *isolate_data, *isolate_instructions;
|
||||
if (elf_snapshot_.Load(namespace_, data_path_ + "/app_aot_snapshot.so")) {
|
||||
isolate_data = elf_snapshot_.IsolateData();
|
||||
isolate_instructions = elf_snapshot_.IsolateInstrs();
|
||||
if (isolate_data == nullptr || isolate_instructions == nullptr) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
namespace_, data_path_ + "/isolate_snapshot_data.bin",
|
||||
isolate_snapshot_data_)) {
|
||||
return false;
|
||||
}
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
namespace_, data_path_ + "/isolate_snapshot_instructions.bin",
|
||||
isolate_snapshot_instructions_, true /* executable */)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
namespace_, data_path_ + "/isolate_snapshot_instructions.bin",
|
||||
isolate_snapshot_instructions_, true /* executable */)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CreateIsolate(isolate_snapshot_data_.address(),
|
||||
isolate_snapshot_instructions_.address());
|
||||
return CreateIsolate(isolate_data, isolate_instructions);
|
||||
#endif // defined(AOT_RUNTIME)
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include <lib/zx/timer.h>
|
||||
|
||||
#include "lib/fidl/cpp/binding.h"
|
||||
#include "mapped_resource.h"
|
||||
#include "runtime/dart/utils/mapped_resource.h"
|
||||
#include "third_party/dart/runtime/include/dart_api.h"
|
||||
|
||||
namespace dart_runner {
|
||||
@ -72,9 +72,10 @@ class DartComponentController : public fuchsia::sys::ComponentController {
|
||||
fdio_ns_t* namespace_ = nullptr;
|
||||
int stdoutfd_ = -1;
|
||||
int stderrfd_ = -1;
|
||||
MappedResource isolate_snapshot_data_;
|
||||
MappedResource isolate_snapshot_instructions_;
|
||||
std::vector<MappedResource> kernel_peices_;
|
||||
dart_utils::ElfSnapshot elf_snapshot_; // AOT snapshot
|
||||
dart_utils::MappedResource isolate_snapshot_data_; // JIT snapshot
|
||||
dart_utils::MappedResource isolate_snapshot_instructions_; // JIT snapshot
|
||||
std::vector<dart_utils::MappedResource> kernel_peices_;
|
||||
|
||||
Dart_Isolate isolate_;
|
||||
int32_t return_code_ = 0;
|
||||
|
||||
@ -155,11 +155,11 @@ DartRunner::DartRunner() : context_(sys::ComponentContext::Create()) {
|
||||
params.vm_snapshot_data = ::_kDartVmSnapshotData;
|
||||
params.vm_snapshot_instructions = ::_kDartVmSnapshotInstructions;
|
||||
#else
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, "pkg/data/vm_snapshot_data.bin", vm_snapshot_data_)) {
|
||||
FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot data");
|
||||
}
|
||||
if (!MappedResource::LoadFromNamespace(
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, "pkg/data/vm_snapshot_instructions.bin",
|
||||
vm_snapshot_instructions_, true /* executable */)) {
|
||||
FX_LOG(FATAL, LOG_TAG, "Failed to load vm snapshot instructions");
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include <lib/fidl/cpp/binding_set.h>
|
||||
#include <lib/sys/cpp/component_context.h>
|
||||
|
||||
#include "mapped_resource.h"
|
||||
#include "runtime/dart/utils/mapped_resource.h"
|
||||
|
||||
namespace dart_runner {
|
||||
|
||||
@ -30,8 +30,8 @@ class DartRunner : public fuchsia::sys::Runner {
|
||||
fidl::BindingSet<fuchsia::sys::Runner> bindings_;
|
||||
|
||||
#if !defined(AOT_RUNTIME)
|
||||
MappedResource vm_snapshot_data_;
|
||||
MappedResource vm_snapshot_instructions_;
|
||||
dart_utils::MappedResource vm_snapshot_data_;
|
||||
dart_utils::MappedResource vm_snapshot_instructions_;
|
||||
#endif
|
||||
|
||||
// Disallow copy and assignment.
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "mapped_resource.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <lib/trace/event.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <zircon/status.h>
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "logging.h"
|
||||
#include "runtime/dart/utils/inlines.h"
|
||||
#include "runtime/dart/utils/vmo.h"
|
||||
|
||||
namespace dart_runner {
|
||||
|
||||
bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
|
||||
const std::string& path,
|
||||
MappedResource& resource,
|
||||
bool executable) {
|
||||
TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
|
||||
|
||||
// openat of a path with a leading '/' ignores the namespace fd.
|
||||
dart_utils::Check(path[0] != '/', LOG_TAG);
|
||||
|
||||
fuchsia::mem::Buffer resource_vmo;
|
||||
if (namespc == nullptr) {
|
||||
if (!dart_utils::VmoFromFilename(path, &resource_vmo)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto root_dir = fdio_ns_opendir(namespc);
|
||||
if (root_dir < 0) {
|
||||
FML_LOG(ERROR) << "Failed to open namespace directory";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = dart_utils::VmoFromFilenameAt(root_dir, path, &resource_vmo);
|
||||
close(root_dir);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (executable) {
|
||||
// VmoFromFilenameAt will return VMOs without ZX_RIGHT_EXECUTE,
|
||||
// so we need replace_as_executable to be able to map them as
|
||||
// ZX_VM_PERM_EXECUTE.
|
||||
// TODO(mdempsky): Update comment once SEC-42 is fixed.
|
||||
zx_status_t status =
|
||||
resource_vmo.vmo.replace_as_executable(zx::handle(), &resource_vmo.vmo);
|
||||
if (status != ZX_OK) {
|
||||
FML_LOG(ERROR) << "Failed to make VMO executable: "
|
||||
<< zx_status_get_string(status);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return LoadFromVmo(path, std::move(resource_vmo), resource, executable);
|
||||
}
|
||||
|
||||
bool MappedResource::LoadFromVmo(const std::string& path,
|
||||
fuchsia::mem::Buffer resource_vmo,
|
||||
MappedResource& resource,
|
||||
bool executable) {
|
||||
if (resource_vmo.size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t flags = ZX_VM_PERM_READ;
|
||||
if (executable) {
|
||||
flags |= ZX_VM_PERM_EXECUTE;
|
||||
}
|
||||
uintptr_t addr;
|
||||
zx_status_t status = zx::vmar::root_self()->map(
|
||||
0, resource_vmo.vmo, 0, resource_vmo.size, flags, &addr);
|
||||
if (status != ZX_OK) {
|
||||
FML_LOG(ERROR) << "Failed to map " << path << ": "
|
||||
<< zx_status_get_string(status);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
resource.address_ = reinterpret_cast<void*>(addr);
|
||||
resource.size_ = resource_vmo.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
MappedResource::~MappedResource() {
|
||||
if (address_ != nullptr) {
|
||||
zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
|
||||
address_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dart_runner
|
||||
@ -19,8 +19,10 @@
|
||||
namespace dart_runner {
|
||||
namespace {
|
||||
|
||||
MappedResource mapped_isolate_snapshot_data;
|
||||
MappedResource mapped_isolate_snapshot_instructions;
|
||||
dart_utils::ElfSnapshot elf_snapshot; // AOT snapshot
|
||||
dart_utils::MappedResource mapped_isolate_snapshot_data; // JIT snapshot
|
||||
dart_utils::MappedResource
|
||||
mapped_isolate_snapshot_instructions; // JIT snapshot
|
||||
tonic::DartLibraryNatives* service_natives = nullptr;
|
||||
|
||||
Dart_NativeFunction GetNativeFunction(Dart_Handle name,
|
||||
@ -76,12 +78,23 @@ Dart_Isolate CreateServiceIsolate(const char* uri,
|
||||
char** error) {
|
||||
Dart_SetEmbedderInformationCallback(EmbedderInformationCallback);
|
||||
|
||||
const uint8_t *vmservice_data = nullptr, *vmservice_instructions = nullptr;
|
||||
|
||||
#if defined(AOT_RUNTIME)
|
||||
// The VM service was compiled as a separate app.
|
||||
const char* snapshot_data_path =
|
||||
"pkg/data/vmservice_isolate_snapshot_data.bin";
|
||||
const char* snapshot_instructions_path =
|
||||
"pkg/data/vmservice_isolate_snapshot_instructions.bin";
|
||||
const char* snapshot_path = "pkg/data/vmservice_snapshot.so";
|
||||
if (elf_snapshot.Load(nullptr, snapshot_path)) {
|
||||
vmservice_data = elf_snapshot.IsolateData();
|
||||
vmservice_instructions = elf_snapshot.IsolateInstrs();
|
||||
if (vmservice_data == nullptr || vmservice_instructions == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
// The VM service was compiled as a separate app.
|
||||
const char* snapshot_data_path =
|
||||
"pkg/data/vmservice_isolate_snapshot_data.bin";
|
||||
const char* snapshot_instructions_path =
|
||||
"pkg/data/vmservice_isolate_snapshot_instructions.bin";
|
||||
#else
|
||||
// The VM service is embedded in the core snapshot.
|
||||
const char* snapshot_data_path = "pkg/data/isolate_core_snapshot_data.bin";
|
||||
@ -89,25 +102,30 @@ Dart_Isolate CreateServiceIsolate(const char* uri,
|
||||
"pkg/data/isolate_core_snapshot_instructions.bin";
|
||||
#endif
|
||||
|
||||
if (!MappedResource::LoadFromNamespace(nullptr, snapshot_data_path,
|
||||
mapped_isolate_snapshot_data)) {
|
||||
*error = strdup("Failed to load snapshot for service isolate");
|
||||
FX_LOG(ERROR, LOG_TAG, *error);
|
||||
return nullptr;
|
||||
}
|
||||
if (!MappedResource::LoadFromNamespace(nullptr, snapshot_instructions_path,
|
||||
mapped_isolate_snapshot_instructions,
|
||||
true /* executable */)) {
|
||||
*error = strdup("Failed to load snapshot for service isolate");
|
||||
FX_LOG(ERROR, LOG_TAG, *error);
|
||||
return nullptr;
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, snapshot_data_path, mapped_isolate_snapshot_data)) {
|
||||
*error = strdup("Failed to load snapshot for service isolate");
|
||||
FX_LOG(ERROR, LOG_TAG, *error);
|
||||
return nullptr;
|
||||
}
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, snapshot_instructions_path,
|
||||
mapped_isolate_snapshot_instructions, true /* executable */)) {
|
||||
*error = strdup("Failed to load snapshot for service isolate");
|
||||
FX_LOG(ERROR, LOG_TAG, *error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vmservice_data = mapped_isolate_snapshot_data.address();
|
||||
vmservice_instructions = mapped_isolate_snapshot_instructions.address();
|
||||
#if defined(AOT_RUNTIME)
|
||||
}
|
||||
#endif
|
||||
|
||||
auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState());
|
||||
Dart_Isolate isolate = Dart_CreateIsolateGroup(
|
||||
uri, DART_VM_SERVICE_ISOLATE_NAME, mapped_isolate_snapshot_data.address(),
|
||||
mapped_isolate_snapshot_instructions.address(), nullptr /* flags */,
|
||||
state, state, error);
|
||||
uri, DART_VM_SERVICE_ISOLATE_NAME, vmservice_data, vmservice_instructions,
|
||||
nullptr /* flags */, state, state, error);
|
||||
if (!isolate) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
|
||||
return nullptr;
|
||||
@ -176,14 +194,14 @@ Dart_Isolate CreateServiceIsolate(const char* uri,
|
||||
} // namespace dart_runner
|
||||
|
||||
Dart_Handle GetVMServiceAssetsArchiveCallback() {
|
||||
MappedResource observatory_tar;
|
||||
if (!MappedResource::LoadFromNamespace(nullptr, "pkg/data/observatory.tar",
|
||||
observatory_tar)) {
|
||||
dart_utils::MappedResource observatory_tar;
|
||||
if (!dart_utils::MappedResource::LoadFromNamespace(
|
||||
nullptr, "pkg/data/observatory.tar", observatory_tar)) {
|
||||
FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets");
|
||||
return nullptr;
|
||||
}
|
||||
// TODO(rmacnak): Should we avoid copying the tar? Or does the service library
|
||||
// not hold onto it anyway?
|
||||
// TODO(rmacnak): Should we avoid copying the tar? Or does the service
|
||||
// library not hold onto it anyway?
|
||||
return tonic::DartConverter<tonic::Uint8List>::ToDart(
|
||||
reinterpret_cast<const uint8_t*>(observatory_tar.address()),
|
||||
observatory_tar.size());
|
||||
|
||||
@ -46,22 +46,14 @@ template("aot_snapshot") {
|
||||
shim_target,
|
||||
]
|
||||
|
||||
vm_snapshot_data_path = "$target_gen_dir/${kernel_name}_vm_data.aotsnapshot"
|
||||
vm_snapshot_instructions_path =
|
||||
"$target_gen_dir/${kernel_name}_vm_instructions.aotsnapshot"
|
||||
snapshot_data_path = "$target_gen_dir/${kernel_name}_data.aotsnapshot"
|
||||
snapshot_instructions_path =
|
||||
"$target_gen_dir/${kernel_name}_instructions.aotsnapshot"
|
||||
snapshot_path = "$target_gen_dir/${kernel_name}_snapshot.so"
|
||||
|
||||
inputs = [
|
||||
shim_kernel,
|
||||
]
|
||||
|
||||
outputs = [
|
||||
vm_snapshot_data_path,
|
||||
vm_snapshot_instructions_path,
|
||||
snapshot_data_path,
|
||||
snapshot_instructions_path,
|
||||
snapshot_path,
|
||||
]
|
||||
|
||||
if (product) {
|
||||
@ -73,13 +65,8 @@ template("aot_snapshot") {
|
||||
args = [
|
||||
"--no_causal_async_stacks",
|
||||
"--deterministic",
|
||||
"--snapshot_kind=app-aot-blobs",
|
||||
"--vm_snapshot_data=" + rebase_path(vm_snapshot_data_path),
|
||||
"--vm_snapshot_instructions=" +
|
||||
rebase_path(vm_snapshot_instructions_path),
|
||||
"--isolate_snapshot_data=" + rebase_path(snapshot_data_path),
|
||||
"--isolate_snapshot_instructions=" +
|
||||
rebase_path(snapshot_instructions_path),
|
||||
"--snapshot_kind=app-aot-elf",
|
||||
"--elf=" + rebase_path(snapshot_path),
|
||||
]
|
||||
|
||||
# No asserts in debug or release product.
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "lib/fdio/io.h"
|
||||
#include "runtime/dart/utils/files.h"
|
||||
#include "runtime/dart/utils/handle_exception.h"
|
||||
#include "runtime/dart/utils/mapped_resource.h"
|
||||
#include "runtime/dart/utils/tempfs.h"
|
||||
#include "runtime/dart/utils/vmo.h"
|
||||
|
||||
@ -498,23 +499,48 @@ void Application::AttemptVMLaunchWithCurrentSettings(
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare flutter_aot_app in flutter_app.gni.
|
||||
fml::RefPtr<flutter::DartSnapshot> vm_snapshot =
|
||||
fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"vm_snapshot_data.bin", false),
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"vm_snapshot_instructions.bin", true));
|
||||
// Compare with flutter_aot_app in flutter_app.gni.
|
||||
fml::RefPtr<flutter::DartSnapshot> vm_snapshot;
|
||||
|
||||
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"isolate_snapshot_data.bin", false),
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"isolate_snapshot_instructions.bin", true));
|
||||
std::shared_ptr<dart_utils::ElfSnapshot> snapshot =
|
||||
std::make_shared<dart_utils::ElfSnapshot>();
|
||||
if (snapshot->Load(application_assets_directory_.get(),
|
||||
"app_aot_snapshot.so")) {
|
||||
const uint8_t* isolate_data = snapshot->IsolateData();
|
||||
const uint8_t* isolate_instructions = snapshot->IsolateInstrs();
|
||||
const uint8_t* vm_data = snapshot->VmData();
|
||||
const uint8_t* vm_instructions = snapshot->VmInstrs();
|
||||
if (isolate_data == nullptr || isolate_instructions == nullptr ||
|
||||
vm_data == nullptr || vm_instructions == nullptr) {
|
||||
FML_LOG(FATAL) << "ELF snapshot missing AOT symbols.";
|
||||
return;
|
||||
}
|
||||
auto hold_snapshot = [snapshot](const uint8_t* _, size_t __) {};
|
||||
vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
std::make_shared<fml::NonOwnedMapping>(vm_data, 0, hold_snapshot),
|
||||
std::make_shared<fml::NonOwnedMapping>(vm_instructions, 0,
|
||||
hold_snapshot));
|
||||
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
std::make_shared<fml::NonOwnedMapping>(isolate_data, 0, hold_snapshot),
|
||||
std::make_shared<fml::NonOwnedMapping>(isolate_instructions, 0,
|
||||
hold_snapshot));
|
||||
} else {
|
||||
vm_snapshot = fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"vm_snapshot_data.bin", false),
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"vm_snapshot_instructions.bin", true));
|
||||
|
||||
isolate_snapshot_ = fml::MakeRefCounted<flutter::DartSnapshot>(
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"isolate_snapshot_data.bin", false),
|
||||
CreateWithContentsOfFile(
|
||||
application_assets_directory_.get() /* /pkg/data */,
|
||||
"isolate_snapshot_instructions.bin", true));
|
||||
}
|
||||
|
||||
auto vm = flutter::DartVMRef::Create(settings_, //
|
||||
std::move(vm_snapshot), //
|
||||
|
||||
@ -5,41 +5,59 @@
|
||||
assert(is_fuchsia)
|
||||
|
||||
import("//build/fuchsia/sdk.gni")
|
||||
import("$flutter_root/common/config.gni")
|
||||
|
||||
config("utils_config") {
|
||||
include_dirs = [ "../../.." ]
|
||||
}
|
||||
|
||||
source_set("utils") {
|
||||
sources = [
|
||||
"files.cc",
|
||||
"files.h",
|
||||
"handle_exception.cc",
|
||||
"handle_exception.h",
|
||||
"inlines.h",
|
||||
"logging.h",
|
||||
"tempfs.cc",
|
||||
"tempfs.h",
|
||||
"vmo.cc",
|
||||
"vmo.h",
|
||||
"vmservice_object.cc",
|
||||
"vmservice_object.h",
|
||||
]
|
||||
template("make_utils") {
|
||||
source_set(target_name) {
|
||||
sources = [
|
||||
"files.cc",
|
||||
"files.h",
|
||||
"handle_exception.cc",
|
||||
"handle_exception.h",
|
||||
"inlines.h",
|
||||
"logging.h",
|
||||
"mapped_resource.cc",
|
||||
"mapped_resource.h",
|
||||
"tempfs.cc",
|
||||
"tempfs.h",
|
||||
"vmo.cc",
|
||||
"vmo.h",
|
||||
"vmservice_object.cc",
|
||||
"vmservice_object.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$fuchsia_sdk_root/fidl:fuchsia.feedback",
|
||||
"$fuchsia_sdk_root/fidl:fuchsia.mem",
|
||||
"$fuchsia_sdk_root/pkg:async-loop",
|
||||
"$fuchsia_sdk_root/pkg:async-loop-cpp",
|
||||
"$fuchsia_sdk_root/pkg:async-loop-default",
|
||||
"$fuchsia_sdk_root/pkg:fdio",
|
||||
"$fuchsia_sdk_root/pkg:memfs",
|
||||
"$fuchsia_sdk_root/pkg:sys_cpp",
|
||||
"$fuchsia_sdk_root/pkg:syslog",
|
||||
"$fuchsia_sdk_root/pkg:vfs_cpp",
|
||||
"$fuchsia_sdk_root/pkg:zx",
|
||||
"//third_party/tonic",
|
||||
]
|
||||
deps = invoker.deps + [
|
||||
"$fuchsia_sdk_root/fidl:fuchsia.feedback",
|
||||
"$fuchsia_sdk_root/fidl:fuchsia.mem",
|
||||
"$fuchsia_sdk_root/pkg:async-loop",
|
||||
"$fuchsia_sdk_root/pkg:async-loop-cpp",
|
||||
"$fuchsia_sdk_root/pkg:async-loop-default",
|
||||
"$fuchsia_sdk_root/pkg:fdio",
|
||||
"$fuchsia_sdk_root/pkg:memfs",
|
||||
"$fuchsia_sdk_root/pkg:sys_cpp",
|
||||
"$fuchsia_sdk_root/pkg:syslog",
|
||||
"$fuchsia_sdk_root/pkg:trace",
|
||||
"$fuchsia_sdk_root/pkg:vfs_cpp",
|
||||
"$fuchsia_sdk_root/pkg:zx",
|
||||
"//third_party/tonic",
|
||||
]
|
||||
|
||||
public_configs = [ ":utils_config" ]
|
||||
public_configs = [ ":utils_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
make_utils("utils") {
|
||||
deps = [
|
||||
"//third_party/dart/runtime/bin:elf_loader",
|
||||
]
|
||||
}
|
||||
|
||||
make_utils("utils_product") {
|
||||
deps = [
|
||||
"//third_party/dart/runtime/bin:elf_loader_product",
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,166 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "mapped_resource.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <fuchsia/io/cpp/fidl.h>
|
||||
#include <fuchsia/mem/cpp/fidl.h>
|
||||
#include <lib/fdio/directory.h>
|
||||
#include <lib/fdio/io.h>
|
||||
#include <lib/syslog/global.h>
|
||||
#include <lib/trace/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <zircon/dlfcn.h>
|
||||
#include <zircon/status.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "runtime/dart/utils/inlines.h"
|
||||
#include "runtime/dart/utils/logging.h"
|
||||
#include "runtime/dart/utils/vmo.h"
|
||||
#include "third_party/dart/runtime/include/dart_api.h"
|
||||
|
||||
namespace dart_utils {
|
||||
|
||||
static bool OpenVmo(fuchsia::mem::Buffer* resource_vmo,
|
||||
fdio_ns_t* namespc,
|
||||
const std::string& path,
|
||||
bool executable) {
|
||||
TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
|
||||
|
||||
// openat of a path with a leading '/' ignores the namespace fd.
|
||||
dart_utils::Check(path[0] != '/', LOG_TAG);
|
||||
|
||||
if (namespc == nullptr) {
|
||||
return dart_utils::VmoFromFilename(path, resource_vmo);
|
||||
} else {
|
||||
auto root_dir = fdio_ns_opendir(namespc);
|
||||
if (root_dir < 0) {
|
||||
FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = dart_utils::VmoFromFilenameAt(root_dir, path, resource_vmo);
|
||||
close(root_dir);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (executable) {
|
||||
// VmoFromFilenameAt will return VMOs without ZX_RIGHT_EXECUTE,
|
||||
// so we need replace_as_executable to be able to map them as
|
||||
// ZX_VM_PERM_EXECUTE.
|
||||
// TODO(mdempsky): Update comment once SEC-42 is fixed.
|
||||
zx_status_t status = resource_vmo->vmo.replace_as_executable(
|
||||
zx::handle(), &resource_vmo->vmo);
|
||||
if (status != ZX_OK) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Failed to make VMO executable: %s",
|
||||
zx_status_get_string(status));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
|
||||
const std::string& path,
|
||||
MappedResource& resource,
|
||||
bool executable) {
|
||||
fuchsia::mem::Buffer resource_vmo;
|
||||
return OpenVmo(&resource_vmo, namespc, path, executable) &&
|
||||
LoadFromVmo(path, std::move(resource_vmo), resource, executable);
|
||||
}
|
||||
|
||||
bool MappedResource::LoadFromVmo(const std::string& path,
|
||||
fuchsia::mem::Buffer resource_vmo,
|
||||
MappedResource& resource,
|
||||
bool executable) {
|
||||
if (resource_vmo.size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t flags = ZX_VM_PERM_READ;
|
||||
if (executable) {
|
||||
flags |= ZX_VM_PERM_EXECUTE;
|
||||
}
|
||||
uintptr_t addr;
|
||||
zx_status_t status = zx::vmar::root_self()->map(
|
||||
0, resource_vmo.vmo, 0, resource_vmo.size, flags, &addr);
|
||||
if (status != ZX_OK) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Failed to map: %s", zx_status_get_string(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
resource.address_ = reinterpret_cast<void*>(addr);
|
||||
resource.size_ = resource_vmo.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
MappedResource::~MappedResource() {
|
||||
if (address_ != nullptr) {
|
||||
zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
|
||||
address_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int OpenFdExec(const std::string& path, int dirfd) {
|
||||
int fd = -1;
|
||||
zx_status_t result = fdio_open_fd_at(
|
||||
dirfd, path.c_str(),
|
||||
fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_EXECUTABLE,
|
||||
&fd);
|
||||
if (result != ZX_OK) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd_at(%s) failed: %s", path.c_str(),
|
||||
zx_status_get_string(result));
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
|
||||
int root_dir = -1;
|
||||
if (namespc == nullptr) {
|
||||
root_dir = AT_FDCWD;
|
||||
} else {
|
||||
root_dir = fdio_ns_opendir(namespc);
|
||||
if (root_dir < 0) {
|
||||
FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Load(root_dir, path);
|
||||
}
|
||||
|
||||
bool ElfSnapshot::Load(int dirfd, const std::string& path) {
|
||||
const int fd = OpenFdExec(path, dirfd);
|
||||
if (fd < 0) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Failed to open VMO for %s from dir.",
|
||||
path.c_str());
|
||||
return false;
|
||||
}
|
||||
return Load(fd);
|
||||
}
|
||||
|
||||
bool ElfSnapshot::Load(int fd) {
|
||||
const char* error;
|
||||
handle_ = Dart_LoadELF_Fd(fd, 0, &error, &vm_data_, &vm_instrs_,
|
||||
&isolate_data_, &isolate_instrs_);
|
||||
if (handle_ == nullptr) {
|
||||
FX_LOGF(ERROR, LOG_TAG, "Failed load ELF: %s", error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ElfSnapshot::~ElfSnapshot() {
|
||||
Dart_UnloadELF(handle_);
|
||||
}
|
||||
|
||||
} // namespace dart_utils
|
||||
@ -7,8 +7,44 @@
|
||||
|
||||
#include <fuchsia/mem/cpp/fidl.h>
|
||||
#include <lib/fdio/namespace.h>
|
||||
#include <third_party/dart/runtime/bin/elf_loader.h>
|
||||
|
||||
namespace dart_runner {
|
||||
namespace dart_utils {
|
||||
|
||||
class ElfSnapshot {
|
||||
public:
|
||||
ElfSnapshot() {}
|
||||
~ElfSnapshot();
|
||||
ElfSnapshot(ElfSnapshot&& other) : handle_(other.handle_) {
|
||||
other.handle_ = nullptr;
|
||||
}
|
||||
ElfSnapshot& operator=(ElfSnapshot&& other) {
|
||||
std::swap(handle_, other.handle_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Load(fdio_ns_t* namespc, const std::string& path);
|
||||
bool Load(int dirfd, const std::string& path);
|
||||
|
||||
const uint8_t* VmData() const { return vm_data_; }
|
||||
const uint8_t* VmInstrs() const { return vm_instrs_; }
|
||||
const uint8_t* IsolateData() const { return isolate_data_; }
|
||||
const uint8_t* IsolateInstrs() const { return isolate_instrs_; }
|
||||
|
||||
private:
|
||||
bool Load(int fd);
|
||||
|
||||
Dart_LoadedElf* handle_ = nullptr;
|
||||
|
||||
const uint8_t* vm_data_ = nullptr;
|
||||
const uint8_t* vm_instrs_ = nullptr;
|
||||
const uint8_t* isolate_data_ = nullptr;
|
||||
const uint8_t* isolate_instrs_ = nullptr;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ElfSnapshot(const ElfSnapshot&) = delete;
|
||||
ElfSnapshot& operator=(const ElfSnapshot&) = delete;
|
||||
};
|
||||
|
||||
class MappedResource {
|
||||
public:
|
||||
@ -37,6 +73,13 @@ class MappedResource {
|
||||
MappedResource& resource,
|
||||
bool executable = false);
|
||||
|
||||
// Same as LoadFromNamespace, but takes a file descriptor to an opened
|
||||
// directory instead of a namespace.
|
||||
static bool LoadFromDir(int dirfd,
|
||||
const std::string& path,
|
||||
MappedResource& resource,
|
||||
bool executable = false);
|
||||
|
||||
// Maps a VMO into the current process's address space. The content is
|
||||
// unmapped when the MappedResource goes out of scope. Returns true on
|
||||
// success. The path is used only for error messages.
|
||||
@ -59,6 +102,6 @@ class MappedResource {
|
||||
MappedResource& operator=(const MappedResource&) = delete;
|
||||
};
|
||||
|
||||
} // namespace dart_runner
|
||||
} // namespace dart_utils
|
||||
|
||||
#endif // APPS_DART_RUNNER_MAPPED_RESOURCE_H_
|
||||
Loading…
x
Reference in New Issue
Block a user