/src/WasmEdge/lib/loader/ast/component/component.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/loader.h" |
5 | | |
6 | | using namespace std::literals; |
7 | | |
8 | | namespace WasmEdge { |
9 | | namespace Loader { |
10 | | |
11 | 9.30k | Expect<std::pair<std::vector<Byte>, std::vector<Byte>>> Loader::loadPreamble() { |
12 | | // component ::= <preamble> s*:<section>* => (component flatten(s*)) |
13 | | // preamble ::= <magic> <version> <layer> |
14 | | // magic ::= 0x00 0x61 0x73 0x6D |
15 | | // version ::= 0x0a 0x00 |
16 | | // layer ::= 0x01 0x00 |
17 | | |
18 | | // The combination of version and layer is corresponding to the version of |
19 | | // core wasm. |
20 | | // The core module has same magic but the different version: |
21 | | // 0x01 0x00 0x00 0x00 |
22 | 9.30k | auto Magic = FMgr.readBytes(4); |
23 | 9.30k | if (!Magic) { |
24 | 31 | return logLoadError(Magic.error(), FMgr.getLastOffset(), |
25 | 31 | ASTNodeAttr::Module); |
26 | 31 | } |
27 | 9.27k | std::vector<Byte> WasmMagic = {0x00, 0x61, 0x73, 0x6D}; |
28 | 9.27k | if (*Magic != WasmMagic) { |
29 | 79 | auto M = *Magic; |
30 | 79 | spdlog::error("Might an invalid wasm file, magic expected, but got 0x{:X} " |
31 | 79 | "0x{:X} 0x{:X} 0x{:X}"sv, |
32 | 79 | M[0], M[1], M[2], M[3]); |
33 | 79 | return logLoadError(ErrCode::Value::MalformedMagic, FMgr.getLastOffset(), |
34 | 79 | ASTNodeAttr::Module); |
35 | 79 | } |
36 | 9.19k | auto Ver = FMgr.readBytes(4); |
37 | 9.19k | if (!Ver) { |
38 | 1 | return logLoadError(Ver.error(), FMgr.getLastOffset(), ASTNodeAttr::Module); |
39 | 1 | } |
40 | 9.19k | return std::make_pair(*Magic, *Ver); |
41 | 9.19k | } |
42 | | |
43 | | Expect<void> Loader::loadComponent(AST::Component::Component &Comp, |
44 | 0 | std::optional<uint64_t> Bound) { |
45 | 0 | auto ReportError = [](auto E) { |
46 | 0 | spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); |
47 | 0 | return E; |
48 | 0 | }; |
49 | | // component ::= <preamble> s*:<section>* => (component flatten(s*)) |
50 | | // section ::= section_0(<core:custom>) => ϵ |
51 | | // | m: section_1(<core:module>) => [core-prefix(m)] |
52 | | // | i*:section_2(vec(<core:instance>)) => core-prefix(i)* |
53 | | // | t*:section_3(vec(<core:type>)) => core-prefix(t)* |
54 | | // | c: section_4(<component>) => [c] |
55 | | // | i*:section_5(vec(<instance>)) => i* |
56 | | // | a*:section_6(vec(<alias>)) => a* |
57 | | // | t*:section_7(vec(<type>)) => t* |
58 | | // | c*:section_8(vec(<canon>)) => c* |
59 | | // | s: section_9(<start>) => [s] |
60 | | // | i*:section_10(vec(<import>)) => i* |
61 | | // | e*:section_11(vec(<export>)) => e* |
62 | | // | v*:section_12(vec(<value>)) => v* 🪙 |
63 | 0 | uint64_t StartOffset = FMgr.getOffset(); |
64 | 0 | uint64_t Offset = FMgr.getOffset(); |
65 | 0 | Expect<Byte> ResSecId; |
66 | |
|
67 | 0 | while ((!Bound.has_value() || *Bound > Offset - StartOffset) && |
68 | 0 | (ResSecId = FMgr.readByte())) { |
69 | 0 | if (!ResSecId) { |
70 | 0 | return logLoadError(ResSecId.error(), FMgr.getLastOffset(), |
71 | 0 | ASTNodeAttr::Component); |
72 | 0 | } |
73 | | // keep going only if we have new section ID |
74 | 0 | uint8_t NewSectionId = *ResSecId; |
75 | 0 | Comp.getSections().emplace_back(); |
76 | 0 | auto &Sec = Comp.getSections().back(); |
77 | |
|
78 | 0 | switch (NewSectionId) { |
79 | 0 | case 0x00: |
80 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::CustomSection>()) |
81 | 0 | .map_error(ReportError)); |
82 | 0 | break; |
83 | 0 | case 0x01: |
84 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CoreModuleSection>()) |
85 | 0 | .map_error(ReportError)); |
86 | 0 | break; |
87 | 0 | case 0x02: |
88 | 0 | EXPECTED_TRY( |
89 | 0 | loadSection(Sec.emplace<AST::Component::CoreInstanceSection>()) |
90 | 0 | .map_error(ReportError)); |
91 | 0 | break; |
92 | 0 | case 0x03: |
93 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CoreTypeSection>()) |
94 | 0 | .map_error(ReportError)); |
95 | 0 | break; |
96 | 0 | case 0x04: |
97 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ComponentSection>()) |
98 | 0 | .map_error(ReportError)); |
99 | 0 | break; |
100 | 0 | case 0x05: |
101 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::InstanceSection>()) |
102 | 0 | .map_error(ReportError)); |
103 | 0 | break; |
104 | 0 | case 0x06: |
105 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::AliasSection>()) |
106 | 0 | .map_error(ReportError)); |
107 | 0 | break; |
108 | 0 | case 0x07: |
109 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::TypeSection>()) |
110 | 0 | .map_error(ReportError)); |
111 | 0 | break; |
112 | 0 | case 0x08: |
113 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CanonSection>()) |
114 | 0 | .map_error(ReportError)); |
115 | 0 | break; |
116 | 0 | case 0x09: |
117 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::StartSection>()) |
118 | 0 | .map_error(ReportError)); |
119 | 0 | break; |
120 | 0 | case 0x0A: |
121 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ImportSection>()) |
122 | 0 | .map_error(ReportError)); |
123 | 0 | break; |
124 | 0 | case 0x0B: |
125 | 0 | EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ExportSection>()) |
126 | 0 | .map_error(ReportError)); |
127 | 0 | break; |
128 | 0 | default: |
129 | 0 | return logLoadError(ErrCode::Value::MalformedSection, |
130 | 0 | FMgr.getLastOffset(), ASTNodeAttr::Component); |
131 | 0 | } |
132 | 0 | Offset = FMgr.getOffset(); |
133 | 0 | } |
134 | 0 | return {}; |
135 | 0 | } |
136 | | |
137 | | } // namespace Loader |
138 | | } // namespace WasmEdge |