1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/native_library.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
8*6777b538SAndroid Build Coastguard Worker #include <fuchsia/io/cpp/fidl.h>
9*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/directory.h>
10*6777b538SAndroid Build Coastguard Worker #include <lib/fdio/io.h>
11*6777b538SAndroid Build Coastguard Worker #include <lib/zx/vmo.h>
12*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
13*6777b538SAndroid Build Coastguard Worker #include <zircon/dlfcn.h>
14*6777b538SAndroid Build Coastguard Worker #include <zircon/status.h>
15*6777b538SAndroid Build Coastguard Worker #include <zircon/syscalls.h>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/base_paths.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/fuchsia_logging.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/path_service.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/posix/safe_strerror.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
29*6777b538SAndroid Build Coastguard Worker #include "base_paths.h"
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker namespace base {
32*6777b538SAndroid Build Coastguard Worker
ToString() const33*6777b538SAndroid Build Coastguard Worker std::string NativeLibraryLoadError::ToString() const {
34*6777b538SAndroid Build Coastguard Worker return message;
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
LoadNativeLibraryWithOptions(const FilePath & library_path,const NativeLibraryOptions & options,NativeLibraryLoadError * error)37*6777b538SAndroid Build Coastguard Worker NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path,
38*6777b538SAndroid Build Coastguard Worker const NativeLibraryOptions& options,
39*6777b538SAndroid Build Coastguard Worker NativeLibraryLoadError* error) {
40*6777b538SAndroid Build Coastguard Worker FilePath computed_path;
41*6777b538SAndroid Build Coastguard Worker FilePath library_root_path =
42*6777b538SAndroid Build Coastguard Worker base::PathService::CheckedGet(DIR_ASSETS).Append("lib");
43*6777b538SAndroid Build Coastguard Worker if (library_path.IsAbsolute()) {
44*6777b538SAndroid Build Coastguard Worker // See more info in fxbug.dev/105910.
45*6777b538SAndroid Build Coastguard Worker if (!library_root_path.IsParent(library_path)) {
46*6777b538SAndroid Build Coastguard Worker auto error_message =
47*6777b538SAndroid Build Coastguard Worker base::StringPrintf("Absolute library paths must begin with %s",
48*6777b538SAndroid Build Coastguard Worker library_root_path.value().c_str());
49*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << error_message;
50*6777b538SAndroid Build Coastguard Worker if (error) {
51*6777b538SAndroid Build Coastguard Worker error->message = std::move(error_message);
52*6777b538SAndroid Build Coastguard Worker }
53*6777b538SAndroid Build Coastguard Worker return nullptr;
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker computed_path = library_path;
56*6777b538SAndroid Build Coastguard Worker } else {
57*6777b538SAndroid Build Coastguard Worker computed_path = library_root_path.Append(library_path);
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker // Use fdio_open_fd (a Fuchsia-specific API) here so we can pass the
61*6777b538SAndroid Build Coastguard Worker // appropriate FS rights flags to request executability.
62*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1018538): Teach base::File about FLAG_WIN_EXECUTE on
63*6777b538SAndroid Build Coastguard Worker // Fuchsia, and then use it here instead of using fdio_open_fd() directly.
64*6777b538SAndroid Build Coastguard Worker base::ScopedFD fd;
65*6777b538SAndroid Build Coastguard Worker zx_status_t status = fdio_open_fd(
66*6777b538SAndroid Build Coastguard Worker computed_path.value().c_str(),
67*6777b538SAndroid Build Coastguard Worker static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
68*6777b538SAndroid Build Coastguard Worker fuchsia::io::OpenFlags::RIGHT_EXECUTABLE),
69*6777b538SAndroid Build Coastguard Worker base::ScopedFD::Receiver(fd).get());
70*6777b538SAndroid Build Coastguard Worker if (status != ZX_OK) {
71*6777b538SAndroid Build Coastguard Worker if (error) {
72*6777b538SAndroid Build Coastguard Worker error->message =
73*6777b538SAndroid Build Coastguard Worker base::StringPrintf("fdio_open_fd: %s", zx_status_get_string(status));
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker return nullptr;
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker zx::vmo vmo;
79*6777b538SAndroid Build Coastguard Worker status = fdio_get_vmo_exec(fd.get(), vmo.reset_and_get_address());
80*6777b538SAndroid Build Coastguard Worker if (status != ZX_OK) {
81*6777b538SAndroid Build Coastguard Worker if (error) {
82*6777b538SAndroid Build Coastguard Worker error->message = base::StringPrintf("fdio_get_vmo_exec: %s",
83*6777b538SAndroid Build Coastguard Worker zx_status_get_string(status));
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker return nullptr;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker NativeLibrary result = dlopen_vmo(vmo.get(), RTLD_LAZY | RTLD_LOCAL);
89*6777b538SAndroid Build Coastguard Worker return result;
90*6777b538SAndroid Build Coastguard Worker }
91*6777b538SAndroid Build Coastguard Worker
UnloadNativeLibrary(NativeLibrary library)92*6777b538SAndroid Build Coastguard Worker void UnloadNativeLibrary(NativeLibrary library) {
93*6777b538SAndroid Build Coastguard Worker // dlclose() is a no-op on Fuchsia, so do nothing here.
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
GetFunctionPointerFromNativeLibrary(NativeLibrary library,const char * name)96*6777b538SAndroid Build Coastguard Worker void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
97*6777b538SAndroid Build Coastguard Worker const char* name) {
98*6777b538SAndroid Build Coastguard Worker return dlsym(library, name);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker
GetNativeLibraryName(StringPiece name)101*6777b538SAndroid Build Coastguard Worker std::string GetNativeLibraryName(StringPiece name) {
102*6777b538SAndroid Build Coastguard Worker return StrCat({"lib", name, ".so"});
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker
GetLoadableModuleName(StringPiece name)105*6777b538SAndroid Build Coastguard Worker std::string GetLoadableModuleName(StringPiece name) {
106*6777b538SAndroid Build Coastguard Worker return GetNativeLibraryName(name);
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker } // namespace base
110