/src/WasmEdge/lib/loader/serialize/serial_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/serialize.h" |
5 | | |
6 | | namespace WasmEdge { |
7 | | namespace Loader { |
8 | | |
9 | | // Serialize custom section. See "include/loader/serialize.h". |
10 | | Expect<void> |
11 | | Serializer::serializeSection(const AST::CustomSection &Sec, |
12 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
13 | | // Custom section: 0x00 + size:u32 + name:vec(byte) + content:byte*. |
14 | | // Section ID. |
15 | 0 | OutVec.push_back(0x00U); |
16 | 0 | auto OrgSize = OutVec.size(); |
17 | | // Name: vec(byte). |
18 | 0 | serializeU32(static_cast<uint32_t>(Sec.getName().size()), OutVec); |
19 | 0 | OutVec.insert(OutVec.end(), Sec.getName().begin(), Sec.getName().end()); |
20 | | // Content: byte*. |
21 | 0 | OutVec.insert(OutVec.end(), Sec.getContent().begin(), Sec.getContent().end()); |
22 | | // Backward insert the section size. |
23 | 0 | serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec, |
24 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
25 | 0 | return {}; |
26 | 0 | } |
27 | | |
28 | | // Serialize type section. See "include/loader/serialize.h". |
29 | | Expect<void> |
30 | | Serializer::serializeSection(const AST::TypeSection &Sec, |
31 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
32 | | // Type section: 0x01 + size:u32 + content:vec(rectype). |
33 | 0 | auto STypes = Sec.getContent(); |
34 | | |
35 | | // record the recursive type vector size. |
36 | 0 | if (STypes.size() > 0) { |
37 | | // Section ID. |
38 | 0 | OutVec.push_back(0x01U); |
39 | 0 | auto OrgSize = OutVec.size(); |
40 | 0 | uint32_t RecCnt = 0; |
41 | | // Content: vec(rectype). |
42 | 0 | for (uint32_t I = 0; I < STypes.size(); I++) { |
43 | 0 | auto RecInfo = STypes[I].getRecursiveInfo(); |
44 | 0 | if (!RecInfo.has_value()) { |
45 | 0 | RecCnt++; |
46 | 0 | } else if (RecInfo->Index == 0) { |
47 | | // First element of recursive type. |
48 | 0 | if (!Conf.hasProposal(Proposal::GC)) { |
49 | 0 | return logNeedProposal(ErrCode::Value::MalformedValType, Proposal::GC, |
50 | 0 | ASTNodeAttr::Sec_Type); |
51 | 0 | } |
52 | 0 | OutVec.push_back(static_cast<uint8_t>(TypeCode::Rec)); |
53 | 0 | serializeU32(RecInfo->RecTypeSize, OutVec); |
54 | 0 | RecCnt++; |
55 | 0 | } |
56 | 0 | EXPECTED_TRY(serializeType(STypes[I], OutVec).map_error([](auto E) { |
57 | 0 | spdlog::error(ASTNodeAttr::Sec_Type); |
58 | 0 | return E; |
59 | 0 | })); |
60 | 0 | } |
61 | | // Backward insert the recursive type vector size. |
62 | 0 | serializeU32(RecCnt, OutVec, |
63 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
64 | | // Backward insert the section size. |
65 | 0 | serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec, |
66 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
67 | 0 | } |
68 | 0 | return {}; |
69 | 0 | } |
70 | | |
71 | | // Serialize import section. See "include/loader/serialize.h". |
72 | | Expect<void> |
73 | | Serializer::serializeSection(const AST::ImportSection &Sec, |
74 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
75 | | // Import section: 0x02 + size:u32 + content:vec(importdesc). |
76 | 0 | return serializeSectionContent( |
77 | 0 | Sec, 0x02U, OutVec, |
78 | 0 | [=](const AST::ImportDesc &R, std::vector<uint8_t> &V) { |
79 | 0 | return serializeDesc(R, V); |
80 | 0 | }); |
81 | 0 | } |
82 | | |
83 | | // Serialize function section. See "include/loader/serialize.h". |
84 | | Expect<void> |
85 | | Serializer::serializeSection(const AST::FunctionSection &Sec, |
86 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
87 | | // Function section: 0x03 + size:u32 + content:vec(u32). |
88 | 0 | return serializeSectionContent( |
89 | 0 | Sec, 0x03U, OutVec, |
90 | 0 | [=](const uint32_t &R, std::vector<uint8_t> &V) -> Expect<void> { |
91 | 0 | serializeU32(R, V); |
92 | 0 | return {}; |
93 | 0 | }); |
94 | 0 | } |
95 | | |
96 | | // Serialize table section. See "include/loader/serialize.h". |
97 | | Expect<void> |
98 | | Serializer::serializeSection(const AST::TableSection &Sec, |
99 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
100 | | // Table section: 0x04 + size:u32 + content:vec(tabletype). |
101 | 0 | return serializeSectionContent( |
102 | 0 | Sec, 0x04U, OutVec, |
103 | 0 | [=](const AST::TableSegment &R, std::vector<uint8_t> &V) { |
104 | 0 | return serializeSegment(R, V); |
105 | 0 | }); |
106 | 0 | } |
107 | | |
108 | | // Serialize memory section. See "include/loader/serialize.h". |
109 | | Expect<void> |
110 | | Serializer::serializeSection(const AST::MemorySection &Sec, |
111 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
112 | | // Memory section: 0x05 + size:u32 + content:vec(memorytype). |
113 | 0 | return serializeSectionContent( |
114 | 0 | Sec, 0x05U, OutVec, |
115 | 0 | [=](const AST::MemoryType &R, std::vector<uint8_t> &V) { |
116 | 0 | return serializeType(R, V); |
117 | 0 | }); |
118 | 0 | } |
119 | | |
120 | | // Serialize global section. See "include/loader/serialize.h". |
121 | | Expect<void> |
122 | | Serializer::serializeSection(const AST::GlobalSection &Sec, |
123 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
124 | | // Global section: 0x06 + size:u32 + content:vec(globaltype). |
125 | 0 | return serializeSectionContent( |
126 | 0 | Sec, 0x06U, OutVec, |
127 | 0 | [=](const AST::GlobalSegment &R, std::vector<uint8_t> &V) { |
128 | 0 | return serializeSegment(R, V); |
129 | 0 | }); |
130 | 0 | } |
131 | | |
132 | | // Serialize export section. See "include/loader/serialize.h". |
133 | | Expect<void> |
134 | | Serializer::serializeSection(const AST::ExportSection &Sec, |
135 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
136 | | // Export section: 0x07 + size:u32 + content:vec(exportdesc). |
137 | 0 | return serializeSectionContent( |
138 | 0 | Sec, 0x07U, OutVec, |
139 | 0 | [=](const AST::ExportDesc &R, std::vector<uint8_t> &V) { |
140 | 0 | return serializeDesc(R, V); |
141 | 0 | }); |
142 | 0 | } |
143 | | |
144 | | // Serialize start section. See "include/loader/serialize.h". |
145 | | Expect<void> |
146 | | Serializer::serializeSection(const AST::StartSection &Sec, |
147 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
148 | | // Start section: 0x08 + size:u32 + idx:u32. |
149 | 0 | if (Sec.getContent()) { |
150 | | // Section ID. |
151 | 0 | OutVec.push_back(0x08U); |
152 | 0 | auto OrgSize = OutVec.size(); |
153 | | // Idx: u32. |
154 | 0 | serializeU32(*Sec.getContent(), OutVec); |
155 | | // Backward insert the section size. |
156 | 0 | serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec, |
157 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
158 | 0 | } |
159 | 0 | return {}; |
160 | 0 | } |
161 | | |
162 | | // Serialize element section. See "include/loader/serialize.h". |
163 | | Expect<void> |
164 | | Serializer::serializeSection(const AST::ElementSection &Sec, |
165 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
166 | | // Element section: 0x09 + size:u32 + content:vec(elemseg). |
167 | 0 | return serializeSectionContent( |
168 | 0 | Sec, 0x09U, OutVec, |
169 | 0 | [=](const AST::ElementSegment &R, std::vector<uint8_t> &V) { |
170 | 0 | return serializeSegment(R, V); |
171 | 0 | }); |
172 | 0 | } |
173 | | |
174 | | // Serialize code section. See "include/loader/serialize.h". |
175 | | Expect<void> |
176 | | Serializer::serializeSection(const AST::CodeSection &Sec, |
177 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
178 | | // Code section: 0x0A + size:u32 + content:vec(codeseg). |
179 | 0 | return serializeSectionContent( |
180 | 0 | Sec, 0x0AU, OutVec, |
181 | 0 | [=](const AST::CodeSegment &R, std::vector<uint8_t> &V) { |
182 | 0 | return serializeSegment(R, V); |
183 | 0 | }); |
184 | 0 | } |
185 | | |
186 | | // Serialize data section. See "include/loader/serialize.h". |
187 | | Expect<void> |
188 | | Serializer::serializeSection(const AST::DataSection &Sec, |
189 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
190 | | // Data section: 0x0B + size:u32 + content:vec(dataseg). |
191 | 0 | return serializeSectionContent( |
192 | 0 | Sec, 0x0BU, OutVec, |
193 | 0 | [=](const AST::DataSegment &R, std::vector<uint8_t> &V) { |
194 | 0 | return serializeSegment(R, V); |
195 | 0 | }); |
196 | 0 | } |
197 | | |
198 | | // Serialize datacount section. See "include/loader/serialize.h". |
199 | | Expect<void> |
200 | | Serializer::serializeSection(const AST::DataCountSection &Sec, |
201 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
202 | | // Datacount section: 0x0C + size:u32 + idx:u32. |
203 | 0 | if (Sec.getContent()) { |
204 | | // This section is for BulkMemoryOperations or ReferenceTypes proposal. |
205 | 0 | if (!Conf.hasProposal(Proposal::BulkMemoryOperations) && |
206 | 0 | !Conf.hasProposal(Proposal::ReferenceTypes)) { |
207 | 0 | return logNeedProposal(ErrCode::Value::MalformedSection, |
208 | 0 | Proposal::BulkMemoryOperations, |
209 | 0 | ASTNodeAttr::Sec_DataCount); |
210 | 0 | } |
211 | | // Section ID. |
212 | 0 | OutVec.push_back(0x0CU); |
213 | 0 | auto OrgSize = OutVec.size(); |
214 | | // Idx: u32. |
215 | 0 | serializeU32(*Sec.getContent(), OutVec); |
216 | | // Backward insert the section size. |
217 | 0 | serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec, |
218 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
219 | 0 | } |
220 | 0 | return {}; |
221 | 0 | } |
222 | | |
223 | | // Serialize tag section. See "include/loader/serialize.h". |
224 | | Expect<void> |
225 | | Serializer::serializeSection(const AST::TagSection &Sec, |
226 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
227 | | // Tag section: 0x0D + size:u32 + content:vec(tag) |
228 | 0 | return serializeSectionContent( |
229 | 0 | Sec, 0x0DU, OutVec, [=](const AST::TagType &R, std::vector<uint8_t> &V) { |
230 | 0 | return serializeType(R, V); |
231 | 0 | }); |
232 | 0 | } |
233 | | |
234 | | } // namespace Loader |
235 | | } // namespace WasmEdge |