Skip to content

Commit 4d46e16

Browse files
committed
Extract common code from runtime implementations.
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent c81a554 commit 4d46e16

File tree

15 files changed

+421
-316
lines changed

15 files changed

+421
-316
lines changed

include/proxy-wasm/null_vm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ struct NullVm : public WasmVm {
4444
bool setWord(uint64_t pointer, Word data) override;
4545
bool getWord(uint64_t pointer, Word *data) override;
4646
size_t getWordSize() override;
47-
std::string_view getCustomSection(std::string_view name) override;
4847
std::string_view getPrecompiledSectionName() override;
4948

5049
#define _FORWARD_GET_FUNCTION(_T) \

include/proxy-wasm/wasm_vm.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,6 @@ class WasmVm {
248248
*/
249249
virtual size_t getWordSize() = 0;
250250

251-
/**
252-
* Get the contents of the custom section with the given name or "" if it does not exist.
253-
* @param name the name of the custom section to get.
254-
* @return the contents of the custom section (if any). The result will be empty if there
255-
* is no such section.
256-
*/
257-
virtual std::string_view getCustomSection(std::string_view name) = 0;
258-
259251
/**
260252
* Get the name of the custom section that contains precompiled module.
261253
* @return the name of the custom section that contains precompiled module.

src/common/wasm_util.cc

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "src/common/wasm_util.h"
16+
#include <cstdio>
17+
#include <string.h>
18+
19+
namespace proxy_wasm {
20+
namespace common {
21+
22+
bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_view name,
23+
std::string_view &ret) {
24+
// Skip the Wasm header.
25+
const char *pos = begin + 8;
26+
while (pos < end) {
27+
if (pos + 1 > end) {
28+
return false;
29+
}
30+
const auto section_type = *pos++;
31+
uint32_t section_len = 0;
32+
if (!parseVarint(pos, end, section_len) || pos + section_len > end) {
33+
return false;
34+
}
35+
if (section_type == 0) {
36+
// Custom section.
37+
const auto section_data_start = pos;
38+
uint32_t section_name_len = 0;
39+
if (!WasmUtil::parseVarint(pos, end, section_name_len) || pos + section_name_len > end) {
40+
return false;
41+
}
42+
if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) {
43+
pos += section_name_len;
44+
ret = {pos, static_cast<size_t>(section_data_start + section_len - pos)};
45+
return true;
46+
}
47+
pos = section_data_start + section_len;
48+
} else {
49+
// Skip other sections.
50+
pos += section_len;
51+
}
52+
}
53+
return true;
54+
};
55+
56+
bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end,
57+
std::unordered_map<uint32_t, std::string> &ret) {
58+
std::string_view name_section = {};
59+
if (!WasmUtil::getCustomSection(begin, end, "name", name_section)) {
60+
return false;
61+
};
62+
if (!name_section.empty()) {
63+
const char *pos = name_section.data();
64+
const char *end = name_section.data() + name_section.size();
65+
while (pos < end) {
66+
const auto subsection_id = *pos++;
67+
uint32_t subsection_size = 0;
68+
if (!parseVarint(pos, end, subsection_size) || pos + subsection_size > end) {
69+
return false;
70+
}
71+
72+
if (subsection_id != 1) {
73+
// Skip other subsctions.
74+
pos += subsection_size;
75+
} else {
76+
// Enters function name subsection.
77+
const auto start = pos;
78+
uint32_t namemap_vector_size = 0;
79+
if (!parseVarint(pos, end, namemap_vector_size) || pos + namemap_vector_size > end) {
80+
return false;
81+
}
82+
for (uint32_t i = 0; i < namemap_vector_size; i++) {
83+
uint32_t func_index = 0;
84+
if (!parseVarint(pos, end, func_index)) {
85+
return false;
86+
}
87+
88+
uint32_t func_name_size = 0;
89+
if (!parseVarint(pos, end, func_name_size) || pos + func_name_size > end) {
90+
return false;
91+
}
92+
ret.insert({func_index, std::string(pos, func_name_size)});
93+
pos += func_name_size;
94+
}
95+
if (start + subsection_size != pos) {
96+
return false;
97+
}
98+
}
99+
}
100+
}
101+
return true;
102+
}
103+
104+
bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector<char> &ret) {
105+
// Skip the Wasm header.
106+
const char *pos = begin + 8;
107+
while (pos < end) {
108+
const auto section_start = pos;
109+
if (pos + 1 > end) {
110+
return false;
111+
}
112+
const auto section_type = *pos++;
113+
uint32_t section_len = 0;
114+
if (!parseVarint(pos, end, section_len) || pos + section_len > end) {
115+
return false;
116+
}
117+
if (section_type == 0 /* custom section */) {
118+
const auto section_data_start = pos;
119+
uint32_t section_name_len = 0;
120+
if (!parseVarint(pos, end, section_name_len) || pos + section_name_len > end) {
121+
return false;
122+
}
123+
auto section_name = std::string_view(pos, section_name_len);
124+
if (section_name.find("precompiled_") != std::string::npos) {
125+
// If this is the first "precompiled_" section, then save everything
126+
// before it, otherwise skip it.
127+
if (ret.empty()) {
128+
const char *start = begin;
129+
ret.insert(ret.end(), start, section_start);
130+
}
131+
}
132+
pos = section_data_start + section_len;
133+
} else {
134+
pos += section_len;
135+
// Save this section if we already saw a custom "precompiled_" section.
136+
if (!ret.empty()) {
137+
ret.insert(ret.end(), section_start, pos /* section end */);
138+
}
139+
}
140+
}
141+
return true;
142+
}
143+
144+
bool WasmUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret) {
145+
uint32_t shift = 0;
146+
char b;
147+
do {
148+
if (pos + 1 > end) {
149+
return false;
150+
}
151+
b = *pos++;
152+
ret += (b & 0x7f) << shift;
153+
shift += 7;
154+
} while ((b & 0x80) != 0);
155+
return ret != static_cast<uint32_t>(-1);
156+
}
157+
158+
} // namespace common
159+
} // namespace proxy_wasm

src/common/wasm_util.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#pragma once
15+
16+
#include <string_view>
17+
#include <vector>
18+
#include <unordered_map>
19+
20+
namespace proxy_wasm {
21+
namespace common {
22+
23+
// Utilitiy functions which directly operate on Wasm bytecodes.
24+
class WasmUtil {
25+
public:
26+
/**
27+
* getCustomSection extract the view of the custom section for a given name.
28+
* @param begin is the beggining of bytecode.
29+
* @param end is the end of bytecode.
30+
* @param name is the name of the custom section.
31+
* @param ret is the reference to store the resulting view to the custom section.
32+
* @return indicates whether parsing succeeded or not.
33+
*/
34+
static bool getCustomSection(const char *begin, const char *end, std::string_view name,
35+
std::string_view &ret);
36+
37+
/**
38+
* getFunctionNameIndex constructs the map from function indexes to function names stored in
39+
* the function name subsection in "name" custom section.
40+
* See https://webassembly.github.io/spec/core/appendix/custom.html#binary-funcnamesec for detail.
41+
* @param begin is the beggining of bytecode.
42+
* @param end is the end of bytecode.
43+
* @param ret the reference to store map from function indexes to function names.
44+
* @return indicates whether parsing succeeded or not.
45+
*/
46+
static bool getFunctionNameIndex(const char *begin, const char *end,
47+
std::unordered_map<uint32_t, std::string> &ret);
48+
49+
/**
50+
* getStrippedSource gets Wasm module without Custom Sections to save some memory in workers.
51+
* @param begin is the beggining of original bytecode.
52+
* @param end is the end of original bytecode.
53+
* @param ret the reference to the stripped bytecode.
54+
* @return indicates whether parsing succeeded or not.
55+
*/
56+
static bool getStrippedSource(const char *begin, const char *end, std::vector<char> &ret);
57+
58+
/**
59+
* parseVarint parses the bytecode following LEB128.
60+
* @param begin is the postion where parsing starts.
61+
* @param end is the end of bytecode.
62+
* @param ret is the reference to store the resulting value.
63+
* @return indicates whether parsing succeeded or not.
64+
*/
65+
static bool parseVarint(const char *&begin, const char *end, uint32_t &ret);
66+
};
67+
68+
} // namespace common
69+
} // namespace proxy_wasm

src/null/null_vm.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ bool NullVm::getWord(uint64_t pointer, Word *data) {
104104

105105
size_t NullVm::getWordSize() { return sizeof(uint64_t); }
106106

107-
std::string_view NullVm::getCustomSection(std::string_view /* name */) {
108-
// Return nothing: there is no WASM file.
109-
return {};
110-
}
111-
112107
std::string_view NullVm::getPrecompiledSectionName() {
113108
// Return nothing: there is no WASM file.
114109
return {};

0 commit comments

Comments
 (0)