/src/WasmEdge/lib/loader/aot_section.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 "loader/aot_section.h" |
5 | | #include "common/spdlog.h" |
6 | | #include "system/allocator.h" |
7 | | |
8 | | #if WASMEDGE_OS_LINUX || WASMEDGE_OS_MACOS |
9 | | extern "C" { |
10 | | extern void __register_frame(void *); |
11 | | extern void __deregister_frame(void *); |
12 | | } |
13 | | #endif |
14 | | |
15 | | using namespace std::literals; |
16 | | |
17 | | namespace { |
18 | 0 | inline constexpr uint64_t roundDownPageBoundary(const uint64_t Value) { |
19 | | // ARM64 Mac has a special page size |
20 | | #if WASMEDGE_OS_MACOS && defined(__aarch64__) |
21 | | return Value & ~UINT64_C(16383); |
22 | | #else |
23 | 0 | return Value & ~UINT64_C(4095); |
24 | 0 | #endif |
25 | 0 | } |
26 | 0 | inline constexpr uint64_t roundUpPageBoundary(const uint64_t Value) { |
27 | | // ARM64 Mac has a special page size |
28 | | #if WASMEDGE_OS_MACOS && defined(__aarch64__) |
29 | | return roundDownPageBoundary(Value + UINT64_C(16383)); |
30 | | #else |
31 | 0 | return roundDownPageBoundary(Value + UINT64_C(4095)); |
32 | 0 | #endif |
33 | 0 | } |
34 | | } // namespace |
35 | | |
36 | | namespace WasmEdge::Loader { |
37 | | |
38 | 0 | Expect<void> AOTSection::load(const AST::AOTSection &AOTSec) noexcept { |
39 | 0 | BinarySize = 0; |
40 | 0 | for (const auto &Section : AOTSec.getSections()) { |
41 | 0 | const auto Offset = std::get<1>(Section); |
42 | 0 | const auto Size = std::get<2>(Section); |
43 | 0 | BinarySize = std::max(BinarySize, Offset + Size); |
44 | 0 | } |
45 | 0 | BinarySize = roundUpPageBoundary(BinarySize); |
46 | |
|
47 | 0 | Binary = Allocator::allocate_chunk(BinarySize); |
48 | 0 | if (unlikely(!Binary)) { |
49 | 0 | spdlog::error(ErrCode::Value::MemoryOutOfBounds); |
50 | 0 | return Unexpect(ErrCode::Value::MemoryOutOfBounds); |
51 | 0 | } |
52 | | |
53 | 0 | std::vector<std::pair<uint8_t *, uint64_t>> ExecutableRanges; |
54 | 0 | for (const auto &Section : AOTSec.getSections()) { |
55 | 0 | const auto Offset = std::get<1>(Section); |
56 | 0 | const auto Size = std::get<2>(Section); |
57 | 0 | const auto &Content = std::get<3>(Section); |
58 | 0 | if (Size > BinarySize || Offset > BinarySize || |
59 | 0 | Offset + Size > BinarySize || Content.size() > Size) { |
60 | 0 | return Unexpect(ErrCode::Value::IntegerTooLarge); |
61 | 0 | } |
62 | 0 | std::copy(Content.begin(), Content.end(), Binary + Offset); |
63 | 0 | switch (std::get<0>(Section)) { |
64 | 0 | case 1: { // Text |
65 | 0 | const auto O = roundDownPageBoundary(Offset); |
66 | 0 | const auto S = roundUpPageBoundary(Size + (Offset - O)); |
67 | 0 | ExecutableRanges.emplace_back(Binary + O, S); |
68 | 0 | break; |
69 | 0 | } |
70 | 0 | case 2: // Data |
71 | 0 | break; |
72 | 0 | case 3: // BSS |
73 | 0 | break; |
74 | 0 | #if WASMEDGE_OS_LINUX |
75 | 0 | case 4: // EHFrame |
76 | 0 | EHFrameAddress = reinterpret_cast<void *>(Binary + Offset); |
77 | 0 | break; |
78 | | #elif WASMEDGE_OS_MACOS |
79 | | case 4: // EHFrame |
80 | | EHFrameAddress = reinterpret_cast<uint8_t *>(Binary + Offset); |
81 | | EHFrameSize = Size; |
82 | | break; |
83 | | #elif WASMEDGE_OS_WINDOWS |
84 | | case 4: // PData |
85 | | PDataAddress = reinterpret_cast<void *>(Binary + Offset); |
86 | | PDataSize = |
87 | | static_cast<uint32_t>(Size / sizeof(winapi::RUNTIME_FUNCTION_)); |
88 | | break; |
89 | | #endif |
90 | 0 | default: |
91 | 0 | return Unexpect(ErrCode::Value::IntegerTooLarge); |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | 0 | for (const auto &[Pointer, Size] : ExecutableRanges) { |
96 | 0 | if (!Allocator::set_chunk_executable(Pointer, Size)) { |
97 | 0 | spdlog::error(ErrCode::Value::MemoryOutOfBounds); |
98 | 0 | spdlog::error(" set_chunk_executable failed:{}"sv, |
99 | 0 | std::strerror(errno)); |
100 | 0 | return Unexpect(ErrCode::Value::MemoryOutOfBounds); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | 0 | IntrinsicsAddress = AOTSec.getIntrinsicsAddress(); |
105 | 0 | TypesAddress = AOTSec.getTypesAddress(); |
106 | 0 | CodesAddress = AOTSec.getCodesAddress(); |
107 | |
|
108 | 0 | #if WASMEDGE_OS_LINUX |
109 | 0 | if (EHFrameAddress) { |
110 | 0 | __register_frame(EHFrameAddress); |
111 | 0 | } |
112 | | #elif WASMEDGE_OS_MACOS |
113 | | if (EHFrameAddress) { |
114 | | auto Iter = EHFrameAddress; |
115 | | const auto End = EHFrameAddress + EHFrameSize - 4; |
116 | | |
117 | | while (Iter < End) { |
118 | | if (Iter != EHFrameAddress) { |
119 | | __register_frame(Iter); |
120 | | } |
121 | | const uint32_t Length = *reinterpret_cast<const uint32_t *>(Iter); |
122 | | Iter += Length + 4; |
123 | | } |
124 | | } |
125 | | #elif WASMEDGE_OS_WINDOWS |
126 | | if (PDataSize != 0) { |
127 | | winapi::RtlAddFunctionTable( |
128 | | static_cast<winapi::PRUNTIME_FUNCTION_>(PDataAddress), PDataSize, |
129 | | reinterpret_cast<winapi::ULONG_PTR_>(Binary)); |
130 | | } |
131 | | #endif |
132 | |
|
133 | 0 | return {}; |
134 | 0 | } |
135 | | |
136 | 0 | void AOTSection::unload() noexcept { |
137 | 0 | if (Binary) { |
138 | 0 | #if WASMEDGE_OS_LINUX |
139 | 0 | if (EHFrameAddress) { |
140 | 0 | __deregister_frame(EHFrameAddress); |
141 | 0 | } |
142 | | #elif WASMEDGE_OS_MACOS |
143 | | if (EHFrameAddress) { |
144 | | auto Iter = EHFrameAddress; |
145 | | const auto End = EHFrameAddress + EHFrameSize - 4; |
146 | | |
147 | | while (Iter < End) { |
148 | | if (Iter != EHFrameAddress) { |
149 | | __deregister_frame(Iter); |
150 | | } |
151 | | const uint32_t Length = *reinterpret_cast<const uint32_t *>(Iter); |
152 | | Iter += Length + 4; |
153 | | } |
154 | | } |
155 | | #elif WASMEDGE_OS_WINDOWS |
156 | | if (PDataSize != 0) { |
157 | | winapi::RtlDeleteFunctionTable( |
158 | | static_cast<winapi::PRUNTIME_FUNCTION_>(PDataAddress)); |
159 | | } |
160 | | #endif |
161 | 0 | Allocator::set_chunk_readable_writable(Binary, BinarySize); |
162 | 0 | Allocator::release_chunk(Binary, BinarySize); |
163 | 0 | Binary = nullptr; |
164 | 0 | } |
165 | 0 | } |
166 | | |
167 | | } // namespace WasmEdge::Loader |