diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ed92e13fd2a57..c93e36b178202 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -971,8 +971,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 @@ -1055,6 +1053,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 diff --git a/shell/platform/fuchsia/dart_runner/BUILD.gn b/shell/platform/fuchsia/dart_runner/BUILD.gn index 735a5dbfab716..a129ecd4a53de 100644 --- a/shell/platform/fuchsia/dart_runner/BUILD.gn +++ b/shell/platform/fuchsia/dart_runner/BUILD.gn @@ -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( - get_label_info("vmservice:vmservice_snapshot", "target_gen_dir") + - "/vmservice_data.aotsnapshot") - vmservice_instr = rebase_path( + vmservice_snapshot = 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) diff --git a/shell/platform/fuchsia/dart_runner/dart_component_controller.cc b/shell/platform/fuchsia/dart_runner/dart_component_controller.cc index d62676164b554..02f412353e706 100644 --- a/shell/platform/fuchsia/dart_runner/dart_component_controller.cc +++ b/shell/platform/fuchsia/dart_runner/dart_component_controller.cc @@ -24,6 +24,7 @@ #include #include +#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; - } - - if (!MappedResource::LoadFromNamespace( - namespace_, data_path_ + "/isolate_snapshot_instructions.bin", - isolate_snapshot_instructions_, true /* executable */)) { - 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; + } } - - return CreateIsolate(isolate_snapshot_data_.address(), - isolate_snapshot_instructions_.address()); + return CreateIsolate(isolate_data, isolate_instructions); #endif // defined(AOT_RUNTIME) } diff --git a/shell/platform/fuchsia/dart_runner/dart_component_controller.h b/shell/platform/fuchsia/dart_runner/dart_component_controller.h index 8f8f7acad2352..24b49a055c9dd 100644 --- a/shell/platform/fuchsia/dart_runner/dart_component_controller.h +++ b/shell/platform/fuchsia/dart_runner/dart_component_controller.h @@ -16,7 +16,7 @@ #include #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 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 kernel_peices_; Dart_Isolate isolate_; int32_t return_code_ = 0; diff --git a/shell/platform/fuchsia/dart_runner/dart_runner.cc b/shell/platform/fuchsia/dart_runner/dart_runner.cc index b9ded3ac468ec..54917ecd5cd5f 100644 --- a/shell/platform/fuchsia/dart_runner/dart_runner.cc +++ b/shell/platform/fuchsia/dart_runner/dart_runner.cc @@ -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"); diff --git a/shell/platform/fuchsia/dart_runner/dart_runner.h b/shell/platform/fuchsia/dart_runner/dart_runner.h index c4a0fd9c17ffe..6d5fc0c3e818d 100644 --- a/shell/platform/fuchsia/dart_runner/dart_runner.h +++ b/shell/platform/fuchsia/dart_runner/dart_runner.h @@ -9,7 +9,7 @@ #include #include -#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 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. diff --git a/shell/platform/fuchsia/dart_runner/mapped_resource.cc b/shell/platform/fuchsia/dart_runner/mapped_resource.cc deleted file mode 100644 index cd17bb177a0e3..0000000000000 --- a/shell/platform/fuchsia/dart_runner/mapped_resource.cc +++ /dev/null @@ -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 -#include -#include -#include -#include - -#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(addr); - resource.size_ = resource_vmo.size; - return true; -} - -MappedResource::~MappedResource() { - if (address_ != nullptr) { - zx::vmar::root_self()->unmap(reinterpret_cast(address_), size_); - address_ = nullptr; - size_ = 0; - } -} - -} // namespace dart_runner diff --git a/shell/platform/fuchsia/dart_runner/service_isolate.cc b/shell/platform/fuchsia/dart_runner/service_isolate.cc index c6831befb0baf..6da8a3de47e43 100644 --- a/shell/platform/fuchsia/dart_runner/service_isolate.cc +++ b/shell/platform/fuchsia/dart_runner/service_isolate.cc @@ -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(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::ToDart( reinterpret_cast(observatory_tar.address()), observatory_tar.size()); diff --git a/shell/platform/fuchsia/dart_runner/vmservice/BUILD.gn b/shell/platform/fuchsia/dart_runner/vmservice/BUILD.gn index a03c9dc16aa64..ecf3113aaa467 100644 --- a/shell/platform/fuchsia/dart_runner/vmservice/BUILD.gn +++ b/shell/platform/fuchsia/dart_runner/vmservice/BUILD.gn @@ -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. diff --git a/shell/platform/fuchsia/flutter/component.cc b/shell/platform/fuchsia/flutter/component.cc index 2cbd33586e1d8..15383723b2307 100644 --- a/shell/platform/fuchsia/flutter/component.cc +++ b/shell/platform/fuchsia/flutter/component.cc @@ -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" @@ -499,23 +500,48 @@ void Application::AttemptVMLaunchWithCurrentSettings( return; } - // Compare flutter_aot_app in flutter_app.gni. - fml::RefPtr vm_snapshot = - fml::MakeRefCounted( - 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( - CreateWithContentsOfFile( - application_assets_directory_.get() /* /pkg/data */, - "isolate_snapshot_data.bin", false), - CreateWithContentsOfFile( - application_assets_directory_.get() /* /pkg/data */, - "isolate_snapshot_instructions.bin", true)); + // Compare with flutter_aot_app in flutter_app.gni. + fml::RefPtr vm_snapshot; + + std::shared_ptr snapshot = + std::make_shared(); + 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( + std::make_shared(vm_data, 0, hold_snapshot), + std::make_shared(vm_instructions, 0, + hold_snapshot)); + isolate_snapshot_ = fml::MakeRefCounted( + std::make_shared(isolate_data, 0, hold_snapshot), + std::make_shared(isolate_instructions, 0, + hold_snapshot)); + } else { + vm_snapshot = fml::MakeRefCounted( + 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( + 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), // diff --git a/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn index 2fa666e2ec877..928af158ea885 100644 --- a/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn +++ b/shell/platform/fuchsia/runtime/dart/utils/BUILD.gn @@ -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 = 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" ] + } +} +make_utils("utils") { 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", + "//third_party/dart/runtime/bin:elf_loader", ] +} - public_configs = [ ":utils_config" ] +make_utils("utils_product") { + deps = [ + "//third_party/dart/runtime/bin:elf_loader_product", + ] } diff --git a/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.cc b/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.cc new file mode 100644 index 0000000000000..48ce40bea4b85 --- /dev/null +++ b/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.cc @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(addr); + resource.size_ = resource_vmo.size; + return true; +} + +MappedResource::~MappedResource() { + if (address_ != nullptr) { + zx::vmar::root_self()->unmap(reinterpret_cast(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 diff --git a/shell/platform/fuchsia/dart_runner/mapped_resource.h b/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.h similarity index 60% rename from shell/platform/fuchsia/dart_runner/mapped_resource.h rename to shell/platform/fuchsia/runtime/dart/utils/mapped_resource.h index fb2d1b74c0c8a..610dec8e6c4d2 100644 --- a/shell/platform/fuchsia/dart_runner/mapped_resource.h +++ b/shell/platform/fuchsia/runtime/dart/utils/mapped_resource.h @@ -7,8 +7,44 @@ #include #include +#include -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_