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(),
115  &fd);
116  } else {
117  dart_utils::Check(path[0] != '/', LOG_TAG);
118  result = fdio_open_fd_at(
119  dirfd, path.c_str(),
121  &fd);
122  }
123  if (result != ZX_OK) {
124  FX_LOGF(ERROR, LOG_TAG, "fdio_open_fd_at(%s) failed: %s", path.c_str(),
125  zx_status_get_string(result));
126  return -1;
127  }
128  return fd;
129 }
130 
131 bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
132  int root_dir = -1;
133  if (namespc == nullptr) {
134  root_dir = AT_FDCWD;
135  } else {
136  root_dir = fdio_ns_opendir(namespc);
137  if (root_dir < 0) {
138  FX_LOG(ERROR, LOG_TAG, "Failed to open namespace directory");
139  return false;
140  }
141  }
142  return Load(root_dir, path);
143 }
144 
145 bool ElfSnapshot::Load(int dirfd, const std::string& path) {
146  const int fd = OpenFdExec(path, dirfd);
147  if (fd < 0) {
148  FX_LOGF(ERROR, LOG_TAG, "Failed to open VMO for %s from dir.",
149  path.c_str());
150  return false;
151  }
152  return Load(fd);
153 }
154 
155 bool 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  FX_LOGF(ERROR, LOG_TAG, "Failed load ELF: %s", error);
161  return false;
162  }
163  return true;
164 }
165 
167  Dart_UnloadELF(handle_);
168 }
169 
170 } // namespace dart_utils
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
constexpr uint32_t OPEN_RIGHT_EXECUTABLE
Definition: component.cc:50
static bool OpenVmo(fuchsia::mem::Buffer *resource_vmo, fdio_ns_t *namespc, const std::string &path, bool executable)
FlMethodResponse GError ** error
bool VmoFromFilenameAt(int dirfd, const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:76
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)
#define LOG_TAG
Definition: logging.h:11
bool VmoFromFilename(const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition: vmo.cc:54
static int OpenFdExec(const std::string &path, int dirfd)
constexpr uint32_t OPEN_RIGHT_READABLE
Definition: component.cc:47
DEF_SWITCHES_START snapshot asset Path to the directory containing the four files specified by VmSnapshotInstructions and IsolateSnapshotInstructions vm snapshot The VM instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present isolate snapshot The isolate instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present icu symbol Prefix for the symbols representing ICU data linked into the Flutter library dart flags
Definition: switches.h:66