-
Notifications
You must be signed in to change notification settings - Fork 79
Extract common code from runtime implementations. #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
4d46e16
Extract common code from runtime implementations.
mathetake 57bb777
Add license
mathetake 700d5b8
review: stop copying source
mathetake 7172764
Fix build
mathetake d951111
Fix doc comment
mathetake c5b123c
rename files for better alignment
mathetake cefe656
Check Wasm header
mathetake d749021
Simplify Wasmtime
mathetake 265de54
Add precompiled section test on runtime
mathetake a103f8f
fix build
mathetake d807f06
Use BytecodeUtil in WAVM for precompiled section
mathetake 0f7eac3
Rename wasm_util -> bytecode_util
mathetake 305d48d
Add ABI parse in BytecodeUtil
mathetake 41a9ac6
Use BytecodeUtil in getAbiVersion on WasmVm except NullVm
mathetake 808a869
Construct string only when it is function export.
mathetake 1dd2bc1
review: fix style and remove redundant WasmHeader check
mathetake ed0f3a5
review: copy original bytecode.
mathetake c639e2c
style: align var names across v8 and wasmtime
mathetake File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| // Copyright 2021 Google LLC | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #include "src/common/bytecode_util.h" | ||
| #include <cstring> | ||
|
|
||
| namespace proxy_wasm { | ||
| namespace common { | ||
|
|
||
| bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) { | ||
| // Wasm file header is 8 bytes (magic number + version). | ||
| static const uint8_t wasm_magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; | ||
| return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4); | ||
| } | ||
|
|
||
| bool BytecodeUtil::getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersion &ret) { | ||
mathetake marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ret = proxy_wasm::AbiVersion::Unknown; | ||
| // Check Wasm header. | ||
| if (!checkWasmHeader(bytecode)) { | ||
| return false; | ||
| } | ||
mathetake marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Skip the Wasm header. | ||
| const char *pos = bytecode.data() + 8; | ||
| const char *end = bytecode.data() + bytecode.size(); | ||
| while (pos < end) { | ||
| if (pos + 1 > end) { | ||
| return false; | ||
| } | ||
| const auto section_type = *pos++; | ||
| uint32_t section_len = 0; | ||
| if (!parseVarint(pos, end, section_len) || pos + section_len > end) { | ||
| return false; | ||
| } | ||
| if (section_type == 7 /* export section */) { | ||
| uint32_t export_vector_size = 0; | ||
| if (!parseVarint(pos, end, export_vector_size) || pos + export_vector_size > end) { | ||
| return false; | ||
| } | ||
| // Search thourgh exports. | ||
| for (uint32_t i = 0; i < export_vector_size; i++) { | ||
| // Parse name of the export. | ||
| uint32_t export_name_size = 0; | ||
| if (!parseVarint(pos, end, export_name_size) || pos + export_name_size > end) { | ||
| return false; | ||
| } | ||
| const auto name_begin = pos; | ||
| pos += export_name_size; | ||
| if (pos + 1 > end) { | ||
| return false; | ||
| } | ||
| // Check if it is a function type export | ||
| if (*pos++ == 0x00) { | ||
| const std::string export_name = {name_begin, export_name_size}; | ||
| // Check the name of the function. | ||
| if (export_name == "proxy_abi_version_0_1_0") { | ||
| ret = AbiVersion::ProxyWasm_0_1_0; | ||
| return true; | ||
| } else if (export_name == "proxy_abi_version_0_2_0") { | ||
| ret = AbiVersion::ProxyWasm_0_2_0; | ||
| return true; | ||
| } else if (export_name == "proxy_abi_version_0_2_1") { | ||
| ret = AbiVersion::ProxyWasm_0_2_1; | ||
| return true; | ||
| } | ||
| } | ||
| // Skip export's index. | ||
| if (!parseVarint(pos, end, export_name_size)) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } else { | ||
| pos += section_len; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool BytecodeUtil::getCustomSection(std::string_view bytecode, std::string_view name, | ||
| std::string_view &ret) { | ||
| // Check Wasm header. | ||
| if (!checkWasmHeader(bytecode)) { | ||
| return false; | ||
| } | ||
|
|
||
| // Skip the Wasm header. | ||
| const char *pos = bytecode.data() + 8; | ||
| const char *end = bytecode.data() + bytecode.size(); | ||
| while (pos < end) { | ||
| if (pos + 1 > end) { | ||
| return false; | ||
| } | ||
| const auto section_type = *pos++; | ||
| uint32_t section_len = 0; | ||
| if (!parseVarint(pos, end, section_len) || pos + section_len > end) { | ||
| return false; | ||
| } | ||
| if (section_type == 0) { | ||
| // Custom section. | ||
| const auto section_data_start = pos; | ||
| uint32_t section_name_len = 0; | ||
| if (!BytecodeUtil::parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { | ||
| return false; | ||
| } | ||
| if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) { | ||
| pos += section_name_len; | ||
| ret = {pos, static_cast<size_t>(section_data_start + section_len - pos)}; | ||
| return true; | ||
| } | ||
| pos = section_data_start + section_len; | ||
| } else { | ||
| // Skip other sections. | ||
| pos += section_len; | ||
| } | ||
| } | ||
| return true; | ||
| }; | ||
|
|
||
| bool BytecodeUtil::getFunctionNameIndex(std::string_view bytecode, | ||
| std::unordered_map<uint32_t, std::string> &ret) { | ||
| std::string_view name_section = {}; | ||
| if (!BytecodeUtil::getCustomSection(bytecode, "name", name_section)) { | ||
| return false; | ||
| }; | ||
| if (!name_section.empty()) { | ||
| const char *pos = name_section.data(); | ||
| const char *end = name_section.data() + name_section.size(); | ||
| while (pos < end) { | ||
| const auto subsection_id = *pos++; | ||
| uint32_t subsection_size = 0; | ||
| if (!parseVarint(pos, end, subsection_size) || pos + subsection_size > end) { | ||
| return false; | ||
| } | ||
|
|
||
| if (subsection_id != 1) { | ||
| // Skip other subsctions. | ||
| pos += subsection_size; | ||
| } else { | ||
| // Enters function name subsection. | ||
| const auto start = pos; | ||
| uint32_t namemap_vector_size = 0; | ||
| if (!parseVarint(pos, end, namemap_vector_size) || pos + namemap_vector_size > end) { | ||
| return false; | ||
| } | ||
| for (uint32_t i = 0; i < namemap_vector_size; i++) { | ||
| uint32_t func_index = 0; | ||
| if (!parseVarint(pos, end, func_index)) { | ||
| return false; | ||
| } | ||
|
|
||
| uint32_t func_name_size = 0; | ||
| if (!parseVarint(pos, end, func_name_size) || pos + func_name_size > end) { | ||
| return false; | ||
| } | ||
| ret.insert({func_index, std::string(pos, func_name_size)}); | ||
| pos += func_name_size; | ||
| } | ||
| if (start + subsection_size != pos) { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { | ||
| // Check Wasm header. | ||
| if (!checkWasmHeader(bytecode)) { | ||
| return false; | ||
| } | ||
|
|
||
| // Skip the Wasm header. | ||
| const char *pos = bytecode.data() + 8; | ||
| const char *end = bytecode.data() + bytecode.size(); | ||
| while (pos < end) { | ||
| const auto section_start = pos; | ||
| if (pos + 1 > end) { | ||
| return false; | ||
| } | ||
| const auto section_type = *pos++; | ||
| uint32_t section_len = 0; | ||
| if (!parseVarint(pos, end, section_len) || pos + section_len > end) { | ||
| return false; | ||
| } | ||
| if (section_type == 0 /* custom section */) { | ||
| const auto section_data_start = pos; | ||
| uint32_t section_name_len = 0; | ||
| if (!parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { | ||
| return false; | ||
| } | ||
| auto section_name = std::string_view(pos, section_name_len); | ||
| if (section_name.find("precompiled_") != std::string::npos) { | ||
| // If this is the first "precompiled_" section, then save everything | ||
| // before it, otherwise skip it. | ||
| if (ret.empty()) { | ||
| const char *start = bytecode.data(); | ||
| ret.append(start, section_start); | ||
| } | ||
| } | ||
| pos = section_data_start + section_len; | ||
| } else { | ||
| pos += section_len; | ||
| // Save this section if we already saw a custom "precompiled_" section. | ||
| if (!ret.empty()) { | ||
| ret.append(section_start, pos); | ||
| } | ||
| } | ||
| } | ||
| if (ret.empty()) { | ||
| // Copy the original source code if it is empty. | ||
| ret = std::string(bytecode); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool BytecodeUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret) { | ||
| uint32_t shift = 0; | ||
| char b; | ||
| do { | ||
| if (pos + 1 > end) { | ||
| return false; | ||
| } | ||
| b = *pos++; | ||
| ret += (b & 0x7f) << shift; | ||
| shift += 7; | ||
| } while ((b & 0x80) != 0); | ||
| return ret != static_cast<uint32_t>(-1); | ||
| } | ||
|
|
||
| } // namespace common | ||
| } // namespace proxy_wasm | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| // Copyright 2021 Google LLC | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
| #pragma once | ||
|
|
||
| #include <string_view> | ||
| #include <vector> | ||
| #include <unordered_map> | ||
|
|
||
| #include "include/proxy-wasm/wasm_vm.h" | ||
|
|
||
| namespace proxy_wasm { | ||
| namespace common { | ||
|
|
||
| // Utilitiy functions which directly operate on Wasm bytecodes. | ||
| class BytecodeUtil { | ||
| public: | ||
| /** | ||
| * checkWasmHeader validates Wasm header. | ||
| * @param bytecode is the target bytecode. | ||
| * @return indicates whether the bytecode has valid Wasm header. | ||
| */ | ||
| static bool checkWasmHeader(std::string_view bytecode); | ||
|
|
||
| /** | ||
| * getAbiVersion extracts ABI version from the bytecode. | ||
| * @param bytecode is the target bytecode. | ||
| * @param ret is the reference to store the extracted ABI version or UnKnown if it doesn't exist. | ||
| * @return indicates whether parsing succeeded or not. | ||
| */ | ||
| static bool getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersion &ret); | ||
|
|
||
| /** | ||
| * getCustomSection extract the view of the custom section for a given name. | ||
| * @param bytecode is the target bytecode. | ||
| * @param name is the name of the custom section. | ||
| * @param ret is the reference to store the resulting view to the custom section. | ||
| * @return indicates whether parsing succeeded or not. | ||
| */ | ||
| static bool getCustomSection(std::string_view bytecode, std::string_view name, | ||
| std::string_view &ret); | ||
|
|
||
| /** | ||
| * getFunctionNameIndex constructs the map from function indexes to function names stored in | ||
| * the function name subsection in "name" custom section. | ||
| * See https://webassembly.github.io/spec/core/appendix/custom.html#binary-funcnamesec for detail. | ||
| * @param bytecode is the target bytecode. | ||
| * @param ret is the reference to store map from function indexes to function names. | ||
| * @return indicates whether parsing succeeded or not. | ||
| */ | ||
| static bool getFunctionNameIndex(std::string_view bytecode, | ||
| std::unordered_map<uint32_t, std::string> &ret); | ||
|
|
||
| /** | ||
| * getStrippedSource gets Wasm module without Custom Sections to save some memory in workers. | ||
| * @param bytecode is the original bytecode. | ||
| * @param ret is the reference to the stripped bytecode or a copy of the original bytecode. | ||
| * @return indicates whether parsing succeeded or not. | ||
| */ | ||
| static bool getStrippedSource(std::string_view bytecode, std::string &ret); | ||
|
|
||
| private: | ||
| static bool parseVarint(const char *&begin, const char *end, uint32_t &ret); | ||
| }; | ||
|
|
||
| } // namespace common | ||
| } // namespace proxy_wasm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.