Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/system/allocator.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/allocator.h"
5
6
#include "common/config.h"
7
#include "common/defines.h"
8
#include "common/errcode.h"
9
10
#if WASMEDGE_OS_WINDOWS
11
#include "system/winapi.h"
12
#elif defined(HAVE_MMAP) && defined(__x86_64__) || defined(__aarch64__) ||     \
13
    defined(__arm__) || (defined(__riscv) && __riscv_xlen == 64)
14
#include <sys/mman.h>
15
#else
16
#include <cctype>
17
#include <cstdlib>
18
#include <cstring>
19
#endif
20
21
namespace WasmEdge {
22
23
namespace {
24
static inline constexpr const uint64_t kPageSize = UINT64_C(65536);
25
26
#if WASMEDGE_OS_WINDOWS || defined(HAVE_MMAP) && defined(__x86_64__) ||        \
27
    defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64)
28
// Only define these two constants on the supported platform to avoid
29
// -Wunused-const-variable error when applying -Werror.
30
static inline constexpr const uint64_t k4G = UINT64_C(0x100000000);
31
static inline constexpr const uint64_t k12G = UINT64_C(0x300000000);
32
#endif
33
34
} // namespace
35
36
0
WASMEDGE_EXPORT uint8_t *Allocator::allocate(uint32_t PageCount) noexcept {
37
#if WASMEDGE_OS_WINDOWS
38
  auto Reserved = reinterpret_cast<uint8_t *>(winapi::VirtualAlloc(
39
      nullptr, k12G, winapi::MEM_RESERVE_, winapi::PAGE_NOACCESS_));
40
  if (Reserved == nullptr) {
41
    return nullptr;
42
  }
43
  if (PageCount == 0) {
44
    return Reserved + k4G;
45
  }
46
  auto Pointer = resize(Reserved + k4G, 0, PageCount);
47
  if (Pointer == nullptr) {
48
    return nullptr;
49
  }
50
  return Pointer;
51
#elif defined(HAVE_MMAP) && defined(__x86_64__) || defined(__aarch64__) ||     \
52
    (defined(__riscv) && __riscv_xlen == 64)
53
  auto Reserved = reinterpret_cast<uint8_t *>(
54
0
      mmap(nullptr, k12G, PROT_NONE,
55
0
           MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0));
56
0
  if (Reserved == MAP_FAILED) {
57
0
    return nullptr;
58
0
  }
59
0
  if (PageCount == 0) {
60
0
    return Reserved + k4G;
61
0
  }
62
0
  auto Pointer = resize(Reserved + k4G, 0, PageCount);
63
0
  if (Pointer == nullptr) {
64
0
    return nullptr;
65
0
  }
66
0
  return Pointer;
67
#else
68
  auto Result = reinterpret_cast<uint8_t *>(std::malloc(kPageSize * PageCount));
69
  if (Result == nullptr) {
70
    return nullptr;
71
  }
72
  std::memset(Result, 0, kPageSize * PageCount);
73
  return Result;
74
#endif
75
0
}
76
77
WASMEDGE_EXPORT uint8_t *Allocator::resize(uint8_t *Pointer,
78
                                           uint32_t OldPageCount,
79
0
                                           uint32_t NewPageCount) noexcept {
80
0
  assuming(NewPageCount > OldPageCount);
81
#if WASMEDGE_OS_WINDOWS
82
  if (winapi::VirtualAlloc(Pointer + OldPageCount * kPageSize,
83
                           (NewPageCount - OldPageCount) * kPageSize,
84
                           winapi::MEM_COMMIT_,
85
                           winapi::PAGE_READWRITE_) == nullptr) {
86
    return nullptr;
87
  }
88
  return Pointer;
89
#elif defined(HAVE_MMAP) && (defined(__x86_64__) || defined(__aarch64__) ||    \
90
                             (defined(__riscv) && __riscv_xlen == 64))
91
0
  if (mmap(Pointer + OldPageCount * kPageSize,
92
0
           (NewPageCount - OldPageCount) * kPageSize, PROT_READ | PROT_WRITE,
93
0
           MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED) {
94
0
    return nullptr;
95
0
  }
96
0
  return Pointer;
97
#else
98
  auto Result = reinterpret_cast<uint8_t *>(
99
      std::realloc(Pointer, NewPageCount * kPageSize));
100
  if (Result == nullptr) {
101
    return nullptr;
102
  }
103
  std::memset(Result + OldPageCount * kPageSize, 0,
104
              (NewPageCount - OldPageCount) * kPageSize);
105
  return Result;
106
#endif
107
0
}
108
109
0
WASMEDGE_EXPORT void Allocator::release(uint8_t *Pointer, uint32_t) noexcept {
110
#if WASMEDGE_OS_WINDOWS
111
  winapi::VirtualFree(Pointer - k4G, 0, winapi::MEM_RELEASE_);
112
#elif defined(HAVE_MMAP) && (defined(__x86_64__) || defined(__aarch64__) ||    \
113
                             (defined(__riscv) && __riscv_xlen == 64))
114
0
  if (Pointer == nullptr) {
115
0
    return;
116
0
  }
117
0
  munmap(Pointer - k4G, k12G);
118
#else
119
  return std::free(Pointer);
120
#endif
121
0
}
122
123
0
uint8_t *Allocator::allocate_chunk(uint64_t Size) noexcept {
124
#if WASMEDGE_OS_WINDOWS
125
  if (auto Pointer = winapi::VirtualAlloc(nullptr, Size, winapi::MEM_COMMIT_,
126
                                          winapi::PAGE_READWRITE_);
127
      unlikely(Pointer == nullptr)) {
128
    return nullptr;
129
  } else {
130
    return reinterpret_cast<uint8_t *>(Pointer);
131
  }
132
#elif defined(HAVE_MMAP)
133
  if (auto Pointer = mmap(nullptr, Size, PROT_READ | PROT_WRITE,
134
0
                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
135
0
      unlikely(Pointer == MAP_FAILED)) {
136
0
    return nullptr;
137
0
  } else {
138
0
    return reinterpret_cast<uint8_t *>(Pointer);
139
0
  }
140
#else
141
  return std::malloc(Size);
142
#endif
143
0
}
144
145
void Allocator::release_chunk(uint8_t *Pointer,
146
0
                              uint64_t Size [[maybe_unused]]) noexcept {
147
#if WASMEDGE_OS_WINDOWS
148
  winapi::VirtualFree(Pointer, 0, winapi::MEM_RELEASE_);
149
#elif defined(HAVE_MMAP)
150
  munmap(Pointer, Size);
151
#else
152
  return std::free(Pointer);
153
#endif
154
0
}
155
156
0
bool Allocator::set_chunk_executable(uint8_t *Pointer, uint64_t Size) noexcept {
157
#if WASMEDGE_OS_WINDOWS
158
  winapi::DWORD_ OldPerm;
159
  return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_EXECUTE_READ_,
160
                                &OldPerm) != 0;
161
#elif defined(HAVE_MMAP)
162
  return mprotect(Pointer, Size, PROT_EXEC | PROT_READ) == 0;
163
#else
164
  return true;
165
#endif
166
0
}
167
168
0
bool Allocator::set_chunk_readable(uint8_t *Pointer, uint64_t Size) noexcept {
169
#if WASMEDGE_OS_WINDOWS
170
  winapi::DWORD_ OldPerm;
171
  return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_READONLY_,
172
                                &OldPerm) != 0;
173
#elif defined(HAVE_MMAP)
174
  return mprotect(Pointer, Size, PROT_READ) == 0;
175
#else
176
  return true;
177
#endif
178
0
}
179
180
bool Allocator::set_chunk_readable_writable(uint8_t *Pointer,
181
0
                                            uint64_t Size) noexcept {
182
#if WASMEDGE_OS_WINDOWS
183
  winapi::DWORD_ OldPerm;
184
  return winapi::VirtualProtect(Pointer, Size, winapi::PAGE_READWRITE_,
185
                                &OldPerm) != 0;
186
#elif defined(HAVE_MMAP)
187
  return mprotect(Pointer, Size, PROT_READ | PROT_WRITE) == 0;
188
#else
189
  return true;
190
#endif
191
0
}
192
193
} // namespace WasmEdge