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/syslog/global.h>
14 #include <lib/trace/event.h>
15 #include <sys/mman.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <zircon/dlfcn.h>
19 #include <zircon/status.h>
20 
21 #include "third_party/dart/runtime/include/dart_api.h"
22 
23 #include "inlines.h"
24 #include "logging.h"
25 #include "vmo.h"
26 
27 namespace dart_utils {
28 
29 static bool OpenVmo(fuchsia::mem::Buffer* resource_vmo,
30  fdio_ns_t* namespc,
31  const std::string& path,
32  bool executable) {
33  TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
34 
35  if (namespc == nullptr) {
36  // Opening a file in the root namespace expects an absolute path.
37  dart_utils::Check(path[0] == '/', LOG_TAG);
38  if (!VmoFromFilename(path, executable, resource_vmo)) {
39  return false;
40  }
41  } else {
42  // openat of a path with a leading '/' ignores the namespace fd.
43  // require a relative path.
44  dart_utils::Check(path[0] != '/', LOG_TAG);
45 
46  auto root_dir = fdio_ns_opendir(namespc);
47  if (root_dir < 0) {
48  FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
49  return false;
50  }
51 
52  bool result =
53  dart_utils::VmoFromFilenameAt(root_dir, path, executable, resource_vmo);
54  close(root_dir);
55  if (!result) {
56  return result;
57  }
58  }
59 
60  return true;
61 }
62 
63 bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
64  const std::string& path,
65  MappedResource& resource,
66  bool executable) {
67  fuchsia::mem::Buffer resource_vmo;
68  return OpenVmo(&resource_vmo, namespc, path, executable) &&
69  LoadFromVmo(path, std::move(resource_vmo), resource, executable);
70 }
71 
72 bool MappedResource::LoadFromVmo(const std::string& path,
73  fuchsia::mem::Buffer resource_vmo,
74  MappedResource& resource,
75  bool executable) {
76  if (resource_vmo.size == 0) {
77  return true;
78  }
79 
80  uint32_t flags = ZX_VM_PERM_READ;
81  if (executable) {
82  flags |= ZX_VM_PERM_EXECUTE;
83  }
84  uintptr_t addr;
85  zx_status_t status = zx::vmar::root_self()->map(flags, 0, resource_vmo.vmo, 0,
86  resource_vmo.size, &addr);
87  if (status != ZX_OK) {
88  FX_LOGF(ERROR, LOG_TAG, "Failed to map: %s", zx_status_get_string(status));
89  return false;
90  }
91 
92  resource.address_ = reinterpret_cast<void*>(addr);
93  resource.size_ = resource_vmo.size;
94  return true;
95 }
96 
98  if (address_ != nullptr) {
99  zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
100  address_ = nullptr;
101  size_ = 0;
102  }
103 }
104 
105 static int OpenFdExec(const std::string& path, int dirfd) {
106  int fd = -1;
107  zx_status_t result;
108  if (dirfd == AT_FDCWD) {
109  // fdio_open_fd_at does not support AT_FDCWD, by design. Use fdio_open_fd
110  // and expect an absolute path for that usage pattern.
111  dart_utils::Check(path[0] == '/', LOG_TAG);
112  result = fdio_open_fd(
113  path.c_str(),
114  static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
115  fuchsia::io::OpenFlags::RIGHT_EXECUTABLE),
116  &fd);
117  } else {
118  dart_utils::Check(path[0] != '/', LOG_TAG);
119  result = fdio_open_fd_at(
120  dirfd, path.c_str(),
121  static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
122  fuchsia::io::OpenFlags::RIGHT_EXECUTABLE),
123  &fd);
124  }
125  if (result != ZX_OK) {
126  FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd_at(%s) failed: %s", path.c_str(),
127  zx_status_get_string(result));
128  return -1;
129  }
130  return fd;
131 }
132 
133 bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
134  int root_dir = -1;
135  if (namespc == nullptr) {
136  root_dir = AT_FDCWD;
137  } else {
138  root_dir = fdio_ns_opendir(namespc);
139  if (root_dir < 0) {
140  FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
141  return false;
142  }
143  }
144  return Load(root_dir, path);
145 }
146 
147 bool ElfSnapshot::Load(int dirfd, const std::string& path) {
148  const int fd = OpenFdExec(path, dirfd);
149  if (fd < 0) {
150  FX_LOGF(ERROR, LOG_TAG, "Failed to open VMO for %s from dir.",
151  path.c_str());
152  return false;
153  }
154  return Load(fd);
155 }
156 
157 bool ElfSnapshot::Load(int fd) {
158  const char* error;
159  handle_ = Dart_LoadELF_Fd(fd, 0, &error, &vm_data_, &vm_instrs_,
160  &isolate_data_, &isolate_instrs_);
161  if (handle_ == nullptr) {
162  FX_LOGF(ERROR, LOG_TAG, "Failed load ELF: %s", error);
163  return false;
164  }
165  return true;
166 }
167 
169  Dart_UnloadELF(handle_);
170 }
171 
172 } // namespace dart_utils
const uint8_t uint32_t uint32_t GError ** error
static bool OpenVmo(fuchsia::mem::Buffer *resource_vmo, fdio_ns_t *namespc, const std::string &path, bool executable)
GAsyncResult * result
bool VmoFromFilenameAt(int dirfd, const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:80
FlutterSemanticsFlag flags
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)
void Check(bool condition, const char *tag, const char *message="")
Definition: inlines.h:12
bool Load(fdio_ns_t *namespc, const std::string &path)
fuchsia::ui::composition::ParentViewportWatcherHandle handle_
#define LOG_TAG
Definition: logging.h:11
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
bool VmoFromFilename(const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:56
static int OpenFdExec(const std::string &path, int dirfd)