Flutter Engine
The Flutter Engine
mapped_resource.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "mapped_resource.h"
6
7#include <dlfcn.h>
8#include <fcntl.h>
9#include <fuchsia/io/cpp/fidl.h>
10#include <fuchsia/mem/cpp/fidl.h>
11#include <lib/fdio/directory.h>
12#include <lib/fdio/io.h>
13#include <lib/trace/event.h>
14#include <sys/mman.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17#include <zircon/dlfcn.h>
18#include <zircon/status.h>
19
20#include "flutter/fml/logging.h"
21#include "third_party/dart/runtime/include/dart_api.h"
22
23#include "inlines.h"
24#include "vmo.h"
25
26namespace dart_utils {
27
28static bool OpenVmo(fuchsia::mem::Buffer* resource_vmo,
29 fdio_ns_t* namespc,
30 const std::string& path,
31 bool executable) {
32 TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
33
34 if (namespc == nullptr) {
35 // Opening a file in the root namespace expects an absolute path.
36 FML_CHECK(path[0] == '/');
37 if (!VmoFromFilename(path, executable, resource_vmo)) {
38 return false;
39 }
40 } else {
41 // openat of a path with a leading '/' ignores the namespace fd.
42 // require a relative path.
43 FML_CHECK(path[0] != '/');
44
45 auto root_dir = fdio_ns_opendir(namespc);
46 if (root_dir < 0) {
47 FML_LOG(ERROR) << "Failed to open namespace directory";
48 return false;
49 }
50
51 bool result =
52 dart_utils::VmoFromFilenameAt(root_dir, path, executable, resource_vmo);
53 close(root_dir);
54 if (!result) {
55 return result;
56 }
57 }
58
59 return true;
60}
61
62bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
63 const std::string& path,
65 bool executable) {
66 fuchsia::mem::Buffer resource_vmo;
67 return OpenVmo(&resource_vmo, namespc, path, executable) &&
68 LoadFromVmo(path, std::move(resource_vmo), resource, executable);
69}
70
71bool MappedResource::LoadFromVmo(const std::string& path,
72 fuchsia::mem::Buffer resource_vmo,
74 bool executable) {
75 if (resource_vmo.size == 0) {
76 return true;
77 }
78
79 uint32_t flags = ZX_VM_PERM_READ;
80 if (executable) {
81 flags |= ZX_VM_PERM_EXECUTE;
82 }
83 uintptr_t addr;
84 zx_status_t status = zx::vmar::root_self()->map(flags, 0, resource_vmo.vmo, 0,
85 resource_vmo.size, &addr);
86 if (status != ZX_OK) {
87 FML_LOG(ERROR) << "Failed to map: " << zx_status_get_string(status);
88 return false;
89 }
90
91 resource.address_ = reinterpret_cast<void*>(addr);
92 resource.size_ = resource_vmo.size;
93 return true;
94}
95
97 if (address_ != nullptr) {
98 zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
99 address_ = nullptr;
100 size_ = 0;
101 }
102}
103
104static int OpenFdExec(const std::string& path, int dirfd) {
105 int fd = -1;
106 zx_status_t result;
107 if (dirfd == AT_FDCWD) {
108 // fdio_open_fd_at does not support AT_FDCWD, by design. Use fdio_open_fd
109 // and expect an absolute path for that usage pattern.
110 FML_CHECK(path[0] == '/');
111 result = fdio_open_fd(
112 path.c_str(),
113 static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
114 fuchsia::io::OpenFlags::RIGHT_EXECUTABLE),
115 &fd);
116 } else {
117 FML_CHECK(path[0] != '/');
118 result = fdio_open_fd_at(
119 dirfd, path.c_str(),
120 static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
121 fuchsia::io::OpenFlags::RIGHT_EXECUTABLE),
122 &fd);
123 }
124 if (result != ZX_OK) {
125 FML_LOG(ERROR) << "fdio_open_fd_at(" << path << ") "
126 << "failed: " << zx_status_get_string(result);
127 return -1;
128 }
129 return fd;
130}
131
132bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
133 int root_dir = -1;
134 if (namespc == nullptr) {
135 root_dir = AT_FDCWD;
136 } else {
137 root_dir = fdio_ns_opendir(namespc);
138 if (root_dir < 0) {
139 FML_LOG(ERROR) << "Failed to open namespace directory";
140 return false;
141 }
142 }
143 return Load(root_dir, path);
144}
145
146bool ElfSnapshot::Load(int dirfd, const std::string& path) {
147 const int fd = OpenFdExec(path, dirfd);
148 if (fd < 0) {
149 FML_LOG(ERROR) << "Failed to open VMO for " << path << " from dir.";
150 return false;
151 }
152 return Load(fd);
153}
154
155bool ElfSnapshot::Load(int fd) {
156 const char* error;
157 handle_ = Dart_LoadELF_Fd(fd, 0, &error, &vm_data_, &vm_instrs_,
158 &isolate_data_, &isolate_instrs_);
159 if (handle_ == nullptr) {
160 FML_LOG(ERROR) << "Failed load ELF: " << error;
161 return false;
162 }
163 return true;
164}
165
167 Dart_UnloadELF(handle_);
168}
169
170} // namespace dart_utils
static SkString resource(SkPDFResourceType type, int index)
size_t size() const
Definition: SkString.h:131
bool Load(fdio_ns_t *namespc, const std::string &path)
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
static bool LoadFromVmo(const std::string &path, fuchsia::mem::Buffer resource_vmo, MappedResource &resource, bool executable=false)
FlutterSemanticsFlag flags
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
bool VmoFromFilenameAt(int dirfd, const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:82
static int OpenFdExec(const std::string &path, int dirfd)
bool VmoFromFilename(const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:57
static bool OpenVmo(fuchsia::mem::Buffer *resource_vmo, fdio_ns_t *namespc, const std::string &path, bool executable)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
#define ERROR(message)
Definition: elf_loader.cc:260
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf *loaded)
Definition: elf_loader.cc:643