/src/WasmEdge/lib/system/mmap.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: 2019-2024 Second State INC |
3 | | |
4 | | #include "system/mmap.h" |
5 | | |
6 | | #include "common/config.h" |
7 | | #include "common/defines.h" |
8 | | |
9 | | #include <cstdint> |
10 | | #include <memory> |
11 | | #include <utility> |
12 | | |
13 | | #ifdef HAVE_MMAP |
14 | | #include <fcntl.h> |
15 | | #include <sys/mman.h> |
16 | | #include <sys/stat.h> |
17 | | #include <unistd.h> |
18 | | #elif WASMEDGE_OS_WINDOWS |
19 | | #include "system/winapi.h" |
20 | | #endif |
21 | | |
22 | | namespace WasmEdge { |
23 | | |
24 | | namespace { |
25 | | #ifdef HAVE_MMAP |
26 | | static inline bool kSupported = true; |
27 | | struct Implement { |
28 | | void *Address = MAP_FAILED; |
29 | | int File = -1; |
30 | | uint64_t Size = 0; |
31 | 0 | Implement(const std::filesystem::path &Path) noexcept { |
32 | 0 | File = open(Path.native().c_str(), O_RDONLY); |
33 | 0 | if (File < 0) { |
34 | 0 | return; |
35 | 0 | } |
36 | | |
37 | 0 | { |
38 | 0 | struct stat Stat; |
39 | 0 | if (fstat(File, &Stat) < 0) { |
40 | 0 | return; |
41 | 0 | } |
42 | 0 | Size = Stat.st_size; |
43 | 0 | } |
44 | | |
45 | 0 | Address = mmap(nullptr, Size, PROT_READ, MAP_SHARED, File, 0); |
46 | 0 | } |
47 | 0 | ~Implement() noexcept { |
48 | 0 | if (Address != MAP_FAILED) { |
49 | 0 | munmap(Address, Size); |
50 | 0 | } |
51 | 0 | if (File >= 0) { |
52 | 0 | close(File); |
53 | 0 | } |
54 | 0 | } |
55 | 0 | bool ok() const noexcept { return Address != MAP_FAILED; } |
56 | | }; |
57 | | #elif WASMEDGE_OS_WINDOWS |
58 | | static inline bool kSupported = true; |
59 | | struct Implement { |
60 | | void *Address = nullptr; |
61 | | winapi::HANDLE_ File = nullptr; |
62 | | winapi::HANDLE_ Map = nullptr; |
63 | | Implement(const std::filesystem::path &Path) noexcept { |
64 | | |
65 | | #if NTDDI_VERSION >= NTDDI_WIN8 |
66 | | winapi::CREATEFILE2_EXTENDED_PARAMETERS_ Create2ExParams; |
67 | | Create2ExParams.dwSize = sizeof(Create2ExParams); |
68 | | Create2ExParams.dwFileAttributes = 0; |
69 | | Create2ExParams.dwFileFlags = winapi::FILE_FLAG_SEQUENTIAL_SCAN_; |
70 | | Create2ExParams.dwSecurityQosFlags = 0; |
71 | | Create2ExParams.lpSecurityAttributes = nullptr; |
72 | | Create2ExParams.hTemplateFile = nullptr; |
73 | | |
74 | | File = winapi::CreateFile2(Path.c_str(), winapi::GENERIC_READ_, |
75 | | winapi::FILE_SHARE_VALID_FLAGS_, |
76 | | winapi::OPEN_EXISTING_, &Create2ExParams); |
77 | | #else |
78 | | File = winapi::CreateFileW(Path.c_str(), winapi::GENERIC_READ_, |
79 | | winapi::FILE_SHARE_VALID_FLAGS_, nullptr, |
80 | | winapi::OPEN_EXISTING_, |
81 | | winapi::FILE_FLAG_SEQUENTIAL_SCAN_, nullptr); |
82 | | #endif |
83 | | if (File == winapi::INVALID_HANDLE_VALUE_) { |
84 | | File = nullptr; |
85 | | return; |
86 | | } |
87 | | |
88 | | winapi::LARGE_INTEGER_ Size; |
89 | | winapi::GetFileSizeEx(File, &Size); |
90 | | |
91 | | #if NTDDI_VERSION >= NTDDI_WIN8 |
92 | | Map = winapi::CreateFileMappingFromApp( |
93 | | File, nullptr, winapi::PAGE_READONLY_, |
94 | | static_cast<WasmEdge::winapi::ULONG64_>(Size.QuadPart), nullptr); |
95 | | #else |
96 | | Map = winapi::CreateFileMappingW(File, nullptr, winapi::PAGE_READONLY_, |
97 | | static_cast<winapi::ULONG_>(Size.HighPart), |
98 | | Size.LowPart, nullptr); |
99 | | #endif |
100 | | if (Map == nullptr) { |
101 | | return; |
102 | | } |
103 | | |
104 | | #if NTDDI_VERSION >= NTDDI_WIN8 |
105 | | Address = winapi::MapViewOfFileFromApp(Map, winapi::FILE_MAP_READ_, 0, 0); |
106 | | #else |
107 | | Address = winapi::MapViewOfFile(Map, winapi::FILE_MAP_READ_, 0, 0, 0); |
108 | | #endif |
109 | | if (Address == nullptr) { |
110 | | return; |
111 | | } |
112 | | } |
113 | | ~Implement() noexcept { |
114 | | if (Address) { |
115 | | winapi::UnmapViewOfFile(Address); |
116 | | } |
117 | | if (Map) { |
118 | | winapi::CloseHandle(Map); |
119 | | } |
120 | | if (File) { |
121 | | winapi::CloseHandle(File); |
122 | | } |
123 | | } |
124 | | bool ok() const noexcept { return Address != nullptr; } |
125 | | }; |
126 | | #else |
127 | | static inline bool kSupported = false; |
128 | | struct Implement { |
129 | | Implement(const std::filesystem::path &Path) noexcept = default; |
130 | | bool ok() const noexcept { return false; } |
131 | | } |
132 | | #endif |
133 | | } // namespace |
134 | | |
135 | 0 | MMap::MMap(const std::filesystem::path &Path) noexcept : Handle(nullptr) { |
136 | 0 | auto NativeHandle = std::make_unique<Implement>(Path); |
137 | 0 | if (!NativeHandle->ok()) { |
138 | 0 | return; |
139 | 0 | } |
140 | | |
141 | 0 | Handle = NativeHandle.release(); |
142 | 0 | } |
143 | | |
144 | 0 | MMap::~MMap() noexcept { |
145 | 0 | if (!Handle) { |
146 | 0 | return; |
147 | 0 | } |
148 | | |
149 | 0 | std::unique_ptr<Implement> NativeHandle( |
150 | 0 | reinterpret_cast<Implement *>(std::exchange(Handle, nullptr))); |
151 | 0 | } |
152 | | |
153 | 0 | void *MMap::address() const noexcept { |
154 | 0 | if (!Handle) { |
155 | 0 | return nullptr; |
156 | 0 | } |
157 | 0 | return reinterpret_cast<const Implement *>(Handle)->Address; |
158 | 0 | } |
159 | | |
160 | 0 | bool MMap::supported() noexcept { return kSupported; } |
161 | | |
162 | | } // namespace WasmEdge |