Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
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"
23#include "third_party/dart/runtime/include/dart_api.h"
24
25namespace dart_utils {
26
27static bool OpenVmo(fuchsia::mem::Buffer* resource_vmo,
28 fdio_ns_t* namespc,
29 const std::string& path,
30 bool executable) {
31 TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
32
33 if (namespc == nullptr) {
34 // Opening a file in the root namespace expects an absolute path.
35 FML_CHECK(path[0] == '/');
36 if (!VmoFromFilename(path, executable, resource_vmo)) {
37 return false;
38 }
39 } else {
40 // openat of a path with a leading '/' ignores the namespace fd.
41 // require a relative path.
42 FML_CHECK(path[0] != '/');
43
44 auto root_dir = fdio_ns_opendir(namespc);
45 if (root_dir < 0) {
46 FML_LOG(ERROR) << "Failed to open namespace directory";
47 return false;
48 }
49
50 bool result =
51 dart_utils::VmoFromFilenameAt(root_dir, path, executable, resource_vmo);
52 close(root_dir);
53 if (!result) {
54 return result;
55 }
56 }
57
58 return true;
59}
60
61bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
62 const std::string& path,
63 MappedResource& resource,
64 bool executable) {
65 fuchsia::mem::Buffer resource_vmo;
66 return OpenVmo(&resource_vmo, namespc, path, executable) &&
67 LoadFromVmo(path, std::move(resource_vmo), resource, executable);
68}
69
70bool MappedResource::LoadFromVmo(const std::string& path,
71 fuchsia::mem::Buffer resource_vmo,
72 MappedResource& resource,
73 bool executable) {
74 if (resource_vmo.size == 0) {
75 return true;
76 }
77
78 uint32_t flags = ZX_VM_PERM_READ;
79 if (executable) {
80 flags |= ZX_VM_PERM_EXECUTE;
81 }
82 uintptr_t addr;
83 zx_status_t status = zx::vmar::root_self()->map(flags, 0, resource_vmo.vmo, 0,
84 resource_vmo.size, &addr);
85 if (status != ZX_OK) {
86 FML_LOG(ERROR) << "Failed to map: " << zx_status_get_string(status);
87 return false;
88 }
89
90 resource.address_ = reinterpret_cast<void*>(addr);
91 resource.size_ = resource_vmo.size;
92 return true;
93}
94
96 if (address_ != nullptr) {
97 zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
98 address_ = nullptr;
99 size_ = 0;
100 }
101}
102
103static int OpenFdExec(const std::string& path, int dirfd) {
104 int fd = -1;
105 // fdio_open3_fd_at only allows relative paths
106 const char* path_ptr = path.c_str();
107 if (path_ptr && path_ptr[0] == '/') {
108 ++path_ptr;
109 }
110 zx_status_t result = fdio_open3_fd_at(
111 dirfd, path_ptr,
112 uint64_t{fuchsia::io::PERM_READABLE | fuchsia::io::PERM_EXECUTABLE}, &fd);
113 if (result != ZX_OK) {
114 FML_LOG(ERROR) << "fdio_open3_fd_at(" << path << ") "
115 << "failed: " << zx_status_get_string(result);
116 return -1;
117 }
118 return fd;
119}
120
121bool ElfSnapshot::Load(fdio_ns_t* namespc, const std::string& path) {
122 int root_dir = -1;
123 if (namespc == nullptr) {
124 root_dir = AT_FDCWD;
125 } else {
126 root_dir = fdio_ns_opendir(namespc);
127 if (root_dir < 0) {
128 FML_LOG(ERROR) << "Failed to open namespace directory";
129 return false;
130 }
131 }
132 return Load(root_dir, path);
133}
134
135bool ElfSnapshot::Load(int dirfd, const std::string& path) {
136 fml::UniqueFD fd(OpenFdExec(path, dirfd));
137 if (!fd.is_valid()) {
138 FML_LOG(ERROR) << "Failed to open VMO for " << path << " from dir.";
139 return false;
140 }
141 return Load(fd);
142}
143
144bool ElfSnapshot::Load(const fml::UniqueFD& fd) {
145 zx_handle_t vmo = ZX_HANDLE_INVALID;
146 zx_status_t status = fdio_get_vmo_exec(fd.get(), &vmo);
147 if (status != ZX_OK) {
148 FML_LOG(ERROR) << "Failed load ELF: " << zx_status_get_string(status);
149 return false;
150 }
151 handle_ = dlopen_vmo(vmo, RTLD_LAZY);
152 if (handle_ == nullptr) {
153 const char* error = dlerror();
154 FML_LOG(ERROR) << "Failed load ELF: " << error;
155 return false;
156 }
157
158 vm_data_ =
159 reinterpret_cast<const uint8_t*>(dlsym(handle_, kVmSnapshotDataCSymbol));
160 vm_instrs_ = reinterpret_cast<const uint8_t*>(
161 dlsym(handle_, kVmSnapshotInstructionsCSymbol));
162 isolate_data_ = reinterpret_cast<const uint8_t*>(
163 dlsym(handle_, kIsolateSnapshotDataCSymbol));
164 isolate_instrs_ = reinterpret_cast<const uint8_t*>(
165 dlsym(handle_, kIsolateSnapshotInstructionsCSymbol));
166 if (vm_data_ == nullptr || vm_instrs_ == nullptr ||
167 isolate_data_ == nullptr || isolate_instrs_ == nullptr) {
168 FML_LOG(ERROR) << "Failed to load ELF symbols";
169 return false;
170 }
171
172 return true;
173}
174
176 dlclose(handle_);
177}
178
179} // namespace dart_utils
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)
bool is_valid() const
const T & get() const
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
bool VmoFromFilenameAt(int dirfd, const std::string &filename, bool executable, fuchsia::mem::Buffer *buffer)
Definition vmo.cc:63
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)