Coverage Report

Created: 2025-08-29 06:29

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