未验证 提交 09c434d2 编写于 作者: S sjindel-google 提交者: GitHub

Use ELF for Dart AOT snapshots on Fuchsia. (#13896)

We will still support loading blobs until build rules in Fuchsia are updated.
上级 bb118c65
......@@ -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(
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)
......
......@@ -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;
}
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)
}
......
......@@ -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.
......
......@@ -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));
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));
// Compare with flutter_aot_app in flutter_app.gni.
fml::RefPtr<flutter::DartSnapshot> vm_snapshot;
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 = 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",
]
}
......@@ -4,41 +4,47 @@
#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 "flutter/fml/logging.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_runner {
namespace dart_utils {
bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
const std::string& path,
MappedResource& resource,
bool executable) {
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);
fuchsia::mem::Buffer resource_vmo;
if (namespc == nullptr) {
if (!dart_utils::VmoFromFilename(path, &resource_vmo)) {
return false;
}
return dart_utils::VmoFromFilename(path, resource_vmo);
} else {
auto root_dir = fdio_ns_opendir(namespc);
if (root_dir < 0) {
FML_LOG(ERROR) << "Failed to open namespace directory";
FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
return false;
}
bool result = dart_utils::VmoFromFilenameAt(root_dir, path, &resource_vmo);
bool result = dart_utils::VmoFromFilenameAt(root_dir, path, resource_vmo);
close(root_dir);
if (!result) {
return result;
......@@ -50,16 +56,25 @@ bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
// 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);
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);
FX_LOGF(ERROR, LOG_TAG, "Failed to make VMO executable: %s",
zx_status_get_string(status));
return false;
}
}
return LoadFromVmo(path, std::move(resource_vmo), resource, executable);
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,
......@@ -78,9 +93,7 @@ bool MappedResource::LoadFromVmo(const std::string& path,
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);
FX_LOGF(ERROR, LOG_TAG, "Failed to map: %s", zx_status_get_string(status));
return false;
}
......@@ -97,4 +110,57 @@ MappedResource::~MappedResource() {
}
}
} // namespace dart_runner
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_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册