From 32db961e692f7fdc05199320ac7786e02803ffab Mon Sep 17 00:00:00 2001 From: Protryon Date: Tue, 12 Dec 2023 12:18:00 -0800 Subject: [PATCH 1/5] dyn vm implementation fix comments format and lints Signed-off-by: Protryon --- .gitignore | 1 + BUILD | 28 +++ bazel/BUILD | 5 + bazel/select.bzl | 7 + include/proxy-wasm/dyn_vm.h | 70 ++++++++ include/proxy-wasm/dyn_vm_plugin.h | 45 +++++ include/proxy-wasm/exports.h | 4 + src/dyn/dyn.cc | 22 +++ src/dyn/dyn_ffi.cc | 267 +++++++++++++++++++++++++++++ src/dyn/dyn_vm.cc | 135 +++++++++++++++ src/dyn/dyn_vm_plugin.cc | 217 +++++++++++++++++++++++ src/exports.cc | 210 +++++++++++++++++++++-- src/wasm.cc | 9 + 13 files changed, 1003 insertions(+), 17 deletions(-) create mode 100644 include/proxy-wasm/dyn_vm.h create mode 100644 include/proxy-wasm/dyn_vm_plugin.h create mode 100644 src/dyn/dyn.cc create mode 100644 src/dyn/dyn_ffi.cc create mode 100644 src/dyn/dyn_vm.cc create mode 100644 src/dyn/dyn_vm_plugin.cc diff --git a/.gitignore b/.gitignore index a6ef824c1..b7fc7a81a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /bazel-* +.vscode diff --git a/BUILD b/BUILD index 215459eb2..c82e0fa8c 100644 --- a/BUILD +++ b/BUILD @@ -14,6 +14,7 @@ load( "@proxy_wasm_cpp_host//bazel:select.bzl", + "proxy_wasm_select_engine_dyn", "proxy_wasm_select_engine_null", "proxy_wasm_select_engine_v8", "proxy_wasm_select_engine_wamr", @@ -122,6 +123,31 @@ cc_library( ], ) +cc_library( + name = "dyn_lib", + srcs = [ + "src/dyn/dyn.cc", + "src/dyn/dyn_ffi.cc", + "src/dyn/dyn_vm.cc", + "src/dyn/dyn_vm_plugin.cc", + ], + hdrs = [ + "include/proxy-wasm/dyn_vm.h", + "include/proxy-wasm/dyn_vm_plugin.h", + "include/proxy-wasm/wasm_api_impl.h", + ], + defines = [ + "PROXY_WASM_HAS_RUNTIME_DYN", + "PROXY_WASM_HOST_ENGINE_DYN", + ], + deps = [ + ":headers", + "@com_google_protobuf//:protobuf_lite", + "@proxy_wasm_cpp_sdk//:api_lib", + ], + alwayslink = 1, +) + cc_library( name = "v8_lib", srcs = [ @@ -315,6 +341,8 @@ cc_library( ":base_lib", ] + proxy_wasm_select_engine_null( [":null_lib"], + ) + proxy_wasm_select_engine_dyn( + [":dyn_lib"], ) + proxy_wasm_select_engine_v8( [":v8_lib"], ) + proxy_wasm_select_engine_wamr( diff --git a/bazel/BUILD b/bazel/BUILD index 650fa29d8..752f4f81f 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -21,6 +21,11 @@ config_setting( values = {"define": "engine=null"}, ) +config_setting( + name = "engine_dyn", + values = {"define": "engine=dyn"}, +) + config_setting( name = "engine_v8", values = {"define": "engine=v8"}, diff --git a/bazel/select.bzl b/bazel/select.bzl index 747aef33c..3ef5df512 100644 --- a/bazel/select.bzl +++ b/bazel/select.bzl @@ -19,6 +19,13 @@ def proxy_wasm_select_engine_null(xs): "//conditions:default": [], }) +def proxy_wasm_select_engine_dyn(xs): + return select({ + "@proxy_wasm_cpp_host//bazel:engine_dyn": xs, + "@proxy_wasm_cpp_host//bazel:multiengine": xs, + "//conditions:default": [], + }) + def proxy_wasm_select_engine_v8(xs): return select({ "@proxy_wasm_cpp_host//bazel:engine_v8": xs, diff --git a/include/proxy-wasm/dyn_vm.h b/include/proxy-wasm/dyn_vm.h new file mode 100644 index 000000000..bd9b72a47 --- /dev/null +++ b/include/proxy-wasm/dyn_vm.h @@ -0,0 +1,70 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 +#include +#include + +#include "include/proxy-wasm/dyn_vm_plugin.h" +#include "include/proxy-wasm/wasm_vm.h" + +namespace proxy_wasm { + +class WasmVm; +std::unique_ptr createDynVm(); + +// The DynVm wraps a C++ Wasm plugin which has been compiled with the Wasm API +// and dynamically linked into the proxy. +struct DynVm : public WasmVm { + DynVm() : WasmVm() {} + + // WasmVm + std::string_view getEngineName() override { return "dyn"; } + Cloneable cloneable() override { return Cloneable::InstantiatedModule; }; + std::unique_ptr clone() override; + bool load(std::string_view plugin_name, std::string_view precompiled, + const std::unordered_map &function_names) override; + bool link(std::string_view debug_name) override; + uint64_t getMemorySize() override; + std::optional getMemory(uint64_t pointer, uint64_t size) override; + bool setMemory(uint64_t pointer, uint64_t size, const void *data) override; + bool setWord(uint64_t pointer, Word data) override; + bool getWord(uint64_t pointer, Word *data) override; + size_t getWordSize() override; + std::string_view getPrecompiledSectionName() override; + +#define _FORWARD_GET_FUNCTION(_T) \ + void getFunction(std::string_view function_name, _T *f) override { \ + plugin_->getFunction(function_name, f); \ + } + FOR_ALL_WASM_VM_EXPORTS(_FORWARD_GET_FUNCTION) +#undef _FORWARD_GET_FUNCTION + + // These are not needed for DynVm which invokes the handlers directly. +#define _REGISTER_CALLBACK(_T) \ + void registerCallback(std::string_view, std::string_view, _T, \ + typename ConvertFunctionTypeWordToUint32<_T>::type) override{}; + FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK) +#undef _REGISTER_CALLBACK + + void terminate() override {} + bool usesWasmByteOrder() override { return false; } + + std::unique_ptr plugin_; +}; + +} // namespace proxy_wasm diff --git a/include/proxy-wasm/dyn_vm_plugin.h b/include/proxy-wasm/dyn_vm_plugin.h new file mode 100644 index 000000000..7454c1ea7 --- /dev/null +++ b/include/proxy-wasm/dyn_vm_plugin.h @@ -0,0 +1,45 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 "include/proxy-wasm/wasm_vm.h" + +namespace proxy_wasm { + +class DynVmPluginSource { +public: + virtual ~DynVmPluginSource(); + void *dl_handle = nullptr; + int memfd = -1; +}; + +// A wrapper for the dynamically linked DynVm plugin which implements the Wasm ABI. +class DynVmPlugin { +public: + DynVmPlugin() = default; + virtual ~DynVmPlugin() = default; + + // NB: These are defined rather than declared PURE because gmock uses __LINE__ internally for + // uniqueness, making it impossible to use FOR_ALL_WASM_VM_EXPORTS with MOCK_METHOD. +#define _DEFINE_GET_FUNCTION(_T) virtual void getFunction(std::string_view, _T *f); + FOR_ALL_WASM_VM_EXPORTS(_DEFINE_GET_FUNCTION) +#undef _DEFINE_GET_FUNCTION + + WasmVm *wasm_vm_ = nullptr; + std::shared_ptr source; +}; + +} // namespace proxy_wasm diff --git a/include/proxy-wasm/exports.h b/include/proxy-wasm/exports.h index 376a4d3b6..f89069d1b 100644 --- a/include/proxy-wasm/exports.h +++ b/include/proxy-wasm/exports.h @@ -149,6 +149,10 @@ Word wasi_unstable_random_get(Word, Word); Word pthread_equal(Word left, Word right); void emscripten_notify_memory_growth(Word); +Word set_effective_context(Word context_id); +void setLimitedEffectiveContext(ContextBase *context); +ContextBase *getBaseContext(); + // Support for embedders, not exported to Wasm. #define FOR_ALL_HOST_FUNCTIONS(_f) \ diff --git a/src/dyn/dyn.cc b/src/dyn/dyn.cc new file mode 100644 index 000000000..cba231af5 --- /dev/null +++ b/src/dyn/dyn.cc @@ -0,0 +1,22 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 "include/proxy-wasm/dyn_vm.h" + +namespace proxy_wasm { + +std::unique_ptr createDynVm() { return std::make_unique(); } + +} // namespace proxy_wasm diff --git a/src/dyn/dyn_ffi.cc b/src/dyn/dyn_ffi.cc new file mode 100644 index 000000000..81110d3f7 --- /dev/null +++ b/src/dyn/dyn_ffi.cc @@ -0,0 +1,267 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 "include/proxy-wasm/wasm_vm.h" +#include "include/proxy-wasm/wasm_api_impl.h" + +inline uint32_t wasmResultToWord(proxy_wasm::WasmResult result) { + return static_cast(result); +} + +extern "C" { + +// Configuration and Status +extern size_t proxy_get_configuration(const char **configuration_ptr, size_t *configuration_size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_get_configuration(configuration_ptr, configuration_size)); +} + +uint32_t proxy_get_status(uint32_t *code_ptr, const char **ptr, size_t *size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_status(code_ptr, ptr, size)); +} + +// Logging +uint32_t proxy_log(proxy_wasm::LogLevel level, const char *logMessage, size_t messageSize) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_log(level, logMessage, messageSize)); +} +uint32_t proxy_get_log_level(proxy_wasm::LogLevel *level) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_log_level(level)); +} + +// Timer +uint32_t proxy_set_tick_period_milliseconds(uint64_t millisecond) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_tick_period_milliseconds(millisecond)); +} +uint32_t proxy_get_current_time_nanoseconds(uint64_t *result) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_current_time_nanoseconds(result)); +} + +// State accessors +uint32_t proxy_get_property(const char *path_ptr, size_t path_size, const char **value_ptr_ptr, + size_t *value_size_ptr) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_property( + path_ptr, path_size, value_ptr_ptr, value_size_ptr)); +} +uint32_t proxy_set_property(const char *key_ptr, size_t key_size, const char *value_ptr, + size_t value_size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_set_property(key_ptr, key_size, value_ptr, value_size)); +} + +// Continue +uint32_t proxy_continue_request() { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_request()); +} +uint32_t proxy_continue_response() { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_response()); +} +uint32_t proxy_continue_stream(proxy_wasm::WasmStreamType stream_type) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_stream(stream_type)); +} +uint32_t proxy_close_stream(proxy_wasm::WasmStreamType stream_type) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_close_stream(stream_type)); +} +uint32_t proxy_send_local_response(uint32_t response_code, const char *response_code_details_ptr, + size_t response_code_details_size, const char *body_ptr, + size_t body_size, + const char *additional_response_header_pairs_ptr, + size_t additional_response_header_pairs_size, + uint32_t grpc_status) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_send_local_response( + response_code, response_code_details_ptr, response_code_details_size, body_ptr, body_size, + additional_response_header_pairs_ptr, additional_response_header_pairs_size, grpc_status)); +} + +uint32_t proxy_clear_route_cache() { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_clear_route_cache()); +} + +// SharedData +uint32_t proxy_get_shared_data(const char *key_ptr, size_t key_size, const char **value_ptr, + size_t *value_size, uint32_t *cas) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_shared_data( + key_ptr, key_size, value_ptr, value_size, cas)); +} +// If cas != 0 and cas != the current cas for 'key' return false, otherwise set the value and +// return true. +uint32_t proxy_set_shared_data(const char *key_ptr, size_t key_size, const char *value_ptr, + size_t value_size, uint64_t cas) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_shared_data( + key_ptr, key_size, value_ptr, value_size, cas)); +} + +// SharedQueue +// Note: Registering the same queue_name will overwrite the old registration while preseving any +// pending data. Consequently it should typically be followed by a call to +// proxy_dequeue_shared_queue. Returns unique token for the queue. +uint32_t proxy_register_shared_queue(const char *queue_name_ptr, size_t queue_name_size, + uint32_t *token) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_register_shared_queue(queue_name_ptr, queue_name_size, token)); +} +// Returns unique token for the queue. +uint32_t proxy_resolve_shared_queue(const char *vm_id_ptr, size_t vm_id_size, + const char *queue_name_ptr, size_t queue_name_size, + uint32_t *token) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_resolve_shared_queue( + vm_id_ptr, vm_id_size, queue_name_ptr, queue_name_size, token)); +} +// Returns true on end-of-stream (no more data available). +uint32_t proxy_dequeue_shared_queue(uint32_t token, const char **data_ptr, size_t *data_size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_dequeue_shared_queue(token, data_ptr, data_size)); +} +// Returns false if the queue was not found and the data was not enqueued. +uint32_t proxy_enqueue_shared_queue(uint32_t token, const char *data_ptr, size_t data_size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_enqueue_shared_queue(token, data_ptr, data_size)); +} + +// Buffer +uint32_t proxy_get_buffer_bytes(proxy_wasm::WasmBufferType type, size_t start, size_t length, + const char **ptr, size_t *size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_get_buffer_bytes(type, start, length, ptr, size)); +} + +uint32_t proxy_get_buffer_status(proxy_wasm::WasmBufferType type, size_t *length_ptr, + uint32_t *flags_ptr) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_get_buffer_status(type, length_ptr, flags_ptr)); +} + +uint32_t proxy_set_buffer_bytes(proxy_wasm::WasmBufferType type, uint64_t start, uint64_t length, + const char *data, size_t size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_set_buffer_bytes(type, start, length, data, size)); +} + +// Headers/Trailers/Metadata Maps +uint32_t proxy_add_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, + size_t key_size, const char *value_ptr, size_t value_size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_add_header_map_value( + type, key_ptr, key_size, value_ptr, value_size)); +} +uint32_t proxy_get_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, + size_t key_size, const char **value_ptr, size_t *value_size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_value( + type, key_ptr, key_size, value_ptr, value_size)); +} +uint32_t proxy_get_header_map_pairs(proxy_wasm::WasmHeaderMapType type, const char **ptr, + size_t *size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_pairs(type, ptr, size)); +} +uint32_t proxy_set_header_map_pairs(proxy_wasm::WasmHeaderMapType type, const char *ptr, + size_t size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_header_map_pairs(type, ptr, size)); +} +uint32_t proxy_replace_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, + size_t key_size, const char *value_ptr, size_t value_size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_replace_header_map_value( + type, key_ptr, key_size, value_ptr, value_size)); +} +uint32_t proxy_remove_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, + size_t key_size) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_remove_header_map_value(type, key_ptr, key_size)); +} +uint32_t proxy_get_header_map_size(proxy_wasm::WasmHeaderMapType type, size_t *size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_size(type, size)); +} + +// HTTP +// Returns token, used in callback onHttpCallResponse +uint32_t proxy_http_call(const char *uri_ptr, size_t uri_size, void *header_pairs_ptr, + size_t header_pairs_size, const char *body_ptr, size_t body_size, + void *trailer_pairs_ptr, size_t trailer_pairs_size, + uint64_t timeout_milliseconds, uint32_t *token_ptr) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_http_call( + uri_ptr, uri_size, header_pairs_ptr, header_pairs_size, body_ptr, body_size, + trailer_pairs_ptr, trailer_pairs_size, timeout_milliseconds, token_ptr)); +} +// gRPC +// Returns token, used in gRPC callbacks (onGrpc...) +uint32_t proxy_grpc_call(const char *service_ptr, size_t service_size, const char *service_name_ptr, + size_t service_name_size, const char *method_name_ptr, + size_t method_name_size, void *initial_metadata_ptr, + size_t initial_metadata_size, const char *request_ptr, size_t request_size, + uint64_t timeout_milliseconds, uint32_t *token_ptr) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_call( + service_ptr, service_size, service_name_ptr, service_name_size, method_name_ptr, + method_name_size, initial_metadata_ptr, initial_metadata_size, request_ptr, request_size, + timeout_milliseconds, token_ptr)); +} +uint32_t proxy_grpc_stream(const char *service_ptr, size_t service_size, + const char *service_name_ptr, size_t service_name_size, + const char *method_name_ptr, size_t method_name_size, + void *initial_metadata_ptr, size_t initial_metadata_size, + uint32_t *token_ptr) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_stream( + service_ptr, service_size, service_name_ptr, service_name_size, method_name_ptr, + method_name_size, initial_metadata_ptr, initial_metadata_size, token_ptr)); +} +uint32_t proxy_grpc_cancel(uint64_t token) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_cancel(token)); +} +uint32_t proxy_grpc_close(uint64_t token) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_close(token)); +} +uint32_t proxy_grpc_send(uint64_t token, const char *message_ptr, size_t message_size, + uint64_t end_stream) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_grpc_send(token, message_ptr, message_size, end_stream)); +} + +// Metrics +// Returns a metric_id which can be used to report a metric. On error returns 0. +uint32_t proxy_define_metric(proxy_wasm::MetricType type, const char *name_ptr, size_t name_size, + uint32_t *metric_id) { + return wasmResultToWord( + proxy_wasm::null_plugin::proxy_define_metric(type, name_ptr, name_size, metric_id)); +} +uint32_t proxy_increment_metric(uint32_t metric_id, int64_t offset) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_increment_metric(metric_id, offset)); +} +uint32_t proxy_record_metric(uint32_t metric_id, uint64_t value) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_record_metric(metric_id, value)); +} +uint32_t proxy_get_metric(uint32_t metric_id, uint64_t *value) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_metric(metric_id, value)); +} + +// System +uint32_t proxy_set_effective_context(uint64_t context_id) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_effective_context(context_id)); +} +uint32_t proxy_done() { return wasmResultToWord(proxy_wasm::null_plugin::proxy_done()); } + +uint32_t proxy_call_foreign_function(const char *function_name, size_t function_name_size, + const char *arguments, size_t arguments_size, char **results, + size_t *results_size) { + return wasmResultToWord(proxy_wasm::null_plugin::proxy_call_foreign_function( + function_name, function_name_size, arguments, arguments_size, results, results_size)); +} + +// following functions only exposed in dyn native contexts + +void *proxy_dyn_get_thread_context() { + return reinterpret_cast(proxy_wasm::exports::getBaseContext()); +} + +void proxy_dyn_set_limited_thread_context(void *thread_context) { + proxy_wasm::exports::setLimitedEffectiveContext( + reinterpret_cast(thread_context)); +} +} \ No newline at end of file diff --git a/src/dyn/dyn_vm.cc b/src/dyn/dyn_vm.cc new file mode 100644 index 000000000..a62d78e52 --- /dev/null +++ b/src/dyn/dyn_vm.cc @@ -0,0 +1,135 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 "include/proxy-wasm/dyn_vm.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace proxy_wasm { + +std::unique_ptr DynVm::clone() { + auto cloned_vm = std::make_unique(); + if (integration()) { + cloned_vm->integration().reset(integration()->clone()); + } + cloned_vm->plugin_ = std::make_unique(); + cloned_vm->plugin_->source = plugin_->source; + cloned_vm->plugin_->wasm_vm_ = cloned_vm.get(); + + return cloned_vm; +} + +// "Load" the plugin by obtaining a pointer to it from the factory. +bool DynVm::load(std::string_view shared_lib, std::string_view /*precompiled*/, + const std::unordered_map & /*function_names*/) { + plugin_ = std::make_unique(); + plugin_->source = std::make_shared(); + // We make the syscall directly w/o the glibc wrapper, as glibc 1.27 is required, but Ubuntu 16 + // which Istio uses runs glibc 1.23. plugin_->source->memfd = memfd_create("dyn_plugin", 0); + plugin_->source->memfd = + static_cast(syscall(SYS_memfd_create, static_cast("dyn_plugin"), 0)); + if (plugin_->source->memfd < 0) { + integration()->error("failed to open memfd for dl: " + std::string(strerror(errno))); + return false; + } + char path[100]; + snprintf(path, sizeof(path), "/proc/%u/fd/%d", getpid(), plugin_->source->memfd); + + size_t written = 0; + ssize_t wrote; + const char *data = shared_lib.data(); + while (written < shared_lib.size()) { + wrote = write(plugin_->source->memfd, data + written, shared_lib.length() - written); + if (wrote < 0) { + integration()->error("failed to write to memfd: " + std::string(strerror(errno))); + return false; + } else if (wrote == 0) { + integration()->error("failed to write to memfd, EOF on write"); + return false; + } + written += wrote; + } + fsync(plugin_->source->memfd); + + plugin_->source->dl_handle = dlopen(path, RTLD_NOW); + if (plugin_->source->dl_handle == nullptr) { + integration()->error("failed to open dl handle: " + std::string(dlerror())); + return false; + } + + plugin_->wasm_vm_ = this; + return true; +} + +bool DynVm::link(std::string_view /* name */) { return true; } + +uint64_t DynVm::getMemorySize() { return std::numeric_limits::max(); } + +// NulVm pointers are just native pointers. +std::optional DynVm::getMemory(uint64_t pointer, uint64_t size) { + if (pointer == 0 && size != 0) { + return std::nullopt; + } + return std::string_view(reinterpret_cast(pointer), static_cast(size)); +} + +bool DynVm::setMemory(uint64_t pointer, uint64_t size, const void *data) { + if (pointer == 0 || data == nullptr) { + if (size != 0) { + return false; + } + return true; + } + auto *p = reinterpret_cast(pointer); + memcpy(p, data, size); + return true; +} + +bool DynVm::setWord(uint64_t pointer, Word data) { + if (pointer == 0) { + return false; + } + auto *p = reinterpret_cast(pointer); + memcpy(p, &data.u64_, sizeof(data.u64_)); + return true; +} + +bool DynVm::getWord(uint64_t pointer, Word *data) { + if (pointer == 0) { + return false; + } + auto *p = reinterpret_cast(pointer); + memcpy(&data->u64_, p, sizeof(data->u64_)); + return true; +} + +size_t DynVm::getWordSize() { return sizeof(uint64_t); } + +std::string_view DynVm::getPrecompiledSectionName() { + // Return nothing: there is no WASM file. + return {}; +} + +} // namespace proxy_wasm diff --git a/src/dyn/dyn_vm_plugin.cc b/src/dyn/dyn_vm_plugin.cc new file mode 100644 index 000000000..52964f65a --- /dev/null +++ b/src/dyn/dyn_vm_plugin.cc @@ -0,0 +1,217 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 "include/proxy-wasm/wasm_vm.h" + +#include "include/proxy-wasm/dyn_vm_plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace proxy_wasm { + +std::string get_tid() { + auto tid = std::this_thread::get_id(); + std::stringstream stream; + stream << tid; + return stream.str(); +} + +std::string call_format(std::string_view function_name, int count, ...) { + std::stringstream out; + out << "dynamic call<" << get_tid() << ">: " << function_name << "("; + std::va_list args; + va_start(args, count); + for (int i = 0; i < count; ++i) { + uint64_t num = va_arg(args, uint64_t); + if (i > 0) { + out << ", "; + } + out << num; + } + out << ")"; + va_end(args); + return out.str(); +} + +DynVmPluginSource::~DynVmPluginSource() { + if (dl_handle != nullptr) { + dlclose(dl_handle); + } + if (memfd >= 0) { + close(memfd); + } +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<0> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + void (*target_func)() = reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 0)); + target_func(); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<1> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + void (*target_func)(uint64_t) = reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 1, w1)); + target_func(w1.u64_); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<2> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + void (*target_func)(uint64_t, uint64_t) = reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, + proxy_wasm::Word w2) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 2, w1, w2)); + target_func(w1.u64_, w2.u64_); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<3> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + void (*target_func)(uint64_t, uint64_t, uint64_t) = + reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, + proxy_wasm::Word w2, proxy_wasm::Word w3) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 3, w1, w2, w3)); + target_func(w1.u64_, w2.u64_, w3.u64_); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<5> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + void (*target_func)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) = + reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, + proxy_wasm::Word w2, proxy_wasm::Word w3, + proxy_wasm::Word w4, proxy_wasm::Word w5) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 5, w1, w2, w3, w4, w5)); + target_func(w1.u64_, w2.u64_, w3.u64_, w4.u64_, w5.u64_); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<1> *f) { + if (source->dl_handle == NULL || function_name == "malloc") { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + uint64_t (*target_func)(uint64_t) = reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 1, w1)); + return proxy_wasm::Word(target_func(w1.u64_)); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<2> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + uint64_t (*target_func)(uint64_t, uint64_t) = + reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, + proxy_wasm::Word w2) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 2, w1, w2)); + return proxy_wasm::Word(target_func(w1.u64_, w2.u64_)); + }; +} + +void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<3> *f) { + if (source->dl_handle == NULL) { + *f = nullptr; + return; + } + void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); + if (target == NULL) { + *f = nullptr; + return; + } + uint64_t (*target_func)(uint64_t, uint64_t, uint64_t) = + reinterpret_cast(target); + *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, + proxy_wasm::Word w2, proxy_wasm::Word w3) { + proxy_wasm::SaveRestoreContext saved_context(context); + wasm_vm_->integration()->trace(call_format(function_name, 3, w1, w2, w3)); + return proxy_wasm::Word(target_func(w1.u64_, w2.u64_, w3.u64_)); + }; +} + +} // namespace proxy_wasm \ No newline at end of file diff --git a/src/exports.cc b/src/exports.cc index 0290dcf0f..7d9ec65ad 100644 --- a/src/exports.cc +++ b/src/exports.cc @@ -23,7 +23,8 @@ namespace proxy_wasm { -thread_local ContextBase *current_context_; +thread_local ContextBase *limited_context_ = nullptr; +thread_local ContextBase *current_context_ = nullptr; thread_local uint32_t effective_context_id_ = 0; // Any currently executing Wasm call context. @@ -39,6 +40,21 @@ ContextBase *contextOrEffectiveContext() { return current_context_; }; +ContextBase *contextOrEffectiveContextRoot() { + auto *context = contextOrEffectiveContext(); + if (context != nullptr) { + return context->root_context(); + } + return nullptr; +}; + +ContextBase *getLimitedContext() { + if (limited_context_ != nullptr) { + return limited_context_; + } + return contextOrEffectiveContext(); +} + std::unordered_map &foreignFunctions() { static auto *ptr = new std::unordered_map; return *ptr; @@ -59,10 +75,17 @@ RegisterForeignFunction::RegisterForeignFunction(const std::string &name, WasmFo namespace exports { +ContextBase *getBaseContext() { return current_context_; } + +void setLimitedEffectiveContext(ContextBase *context) { limited_context_ = context; } + // General ABI. Word set_property(Word key_ptr, Word key_size, Word value_ptr, Word value_size) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); auto value = context->wasmVm()->getMemory(value_ptr, value_size); if (!key || !value) { @@ -74,6 +97,9 @@ Word set_property(Word key_ptr, Word key_size, Word value_ptr, Word value_size) // Generic selector Word get_property(Word path_ptr, Word path_size, Word value_ptr_ptr, Word value_size_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto path = context->wasmVm()->getMemory(path_ptr, path_size); if (!path.has_value()) { return WasmResult::InvalidMemoryAccess; @@ -91,6 +117,9 @@ Word get_property(Word path_ptr, Word path_size, Word value_ptr_ptr, Word value_ Word get_configuration(Word value_ptr_ptr, Word value_size_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto value = context->getConfiguration(); if (!context->wasm()->copyToPointerSize(value, value_ptr_ptr, value_size_ptr)) { return WasmResult::InvalidMemoryAccess; @@ -99,7 +128,10 @@ Word get_configuration(Word value_ptr_ptr, Word value_size_ptr) { } Word get_status(Word code_ptr, Word value_ptr_ptr, Word value_size_ptr) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto status = context->getStatus(); if (!context->wasm()->setDatatype(code_ptr, status.first)) { return WasmResult::InvalidMemoryAccess; @@ -115,16 +147,25 @@ Word get_status(Word code_ptr, Word value_ptr_ptr, Word value_size_ptr) { // Continue/Reply/Route Word continue_request() { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->continueStream(WasmStreamType::Request); } Word continue_response() { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->continueStream(WasmStreamType::Response); } Word continue_stream(Word type) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } if (type > static_cast(WasmStreamType::MAX)) { return WasmResult::BadArgument; } @@ -133,6 +174,9 @@ Word continue_stream(Word type) { Word close_stream(Word type) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } if (type > static_cast(WasmStreamType::MAX)) { return WasmResult::BadArgument; } @@ -144,6 +188,9 @@ Word send_local_response(Word response_code, Word response_code_details_ptr, Word additional_response_header_pairs_ptr, Word additional_response_header_pairs_size, Word grpc_status) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto details = context->wasmVm()->getMemory(response_code_details_ptr, response_code_details_size); auto body = context->wasmVm()->getMemory(body_ptr, body_size); @@ -161,12 +208,18 @@ Word send_local_response(Word response_code, Word response_code_details_ptr, Word clear_route_cache() { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } context->clearRouteCache(); return WasmResult::Ok; } Word set_effective_context(Word context_id) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto cid = static_cast(context_id); auto *c = context->wasm()->getContext(cid); if (c == nullptr) { @@ -178,12 +231,18 @@ Word set_effective_context(Word context_id) { Word done() { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->wasm()->done(context); } Word call_foreign_function(Word function_name, Word function_name_size, Word arguments, Word arguments_size, Word results, Word results_size) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto function = context->wasmVm()->getMemory(function_name, function_name_size); if (!function) { return WasmResult::InvalidMemoryAccess; @@ -227,6 +286,9 @@ Word call_foreign_function(Word function_name, Word function_name_size, Word arg Word get_shared_data(Word key_ptr, Word key_size, Word value_ptr_ptr, Word value_size_ptr, Word cas_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); if (!key) { return WasmResult::InvalidMemoryAccess; @@ -247,6 +309,9 @@ Word get_shared_data(Word key_ptr, Word key_size, Word value_ptr_ptr, Word value Word set_shared_data(Word key_ptr, Word key_size, Word value_ptr, Word value_size, Word cas) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); auto value = context->wasmVm()->getMemory(value_ptr, value_size); if (!key || !value) { @@ -257,6 +322,9 @@ Word set_shared_data(Word key_ptr, Word key_size, Word value_ptr, Word value_siz Word register_shared_queue(Word queue_name_ptr, Word queue_name_size, Word token_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto queue_name = context->wasmVm()->getMemory(queue_name_ptr, queue_name_size); if (!queue_name) { return WasmResult::InvalidMemoryAccess; @@ -274,6 +342,9 @@ Word register_shared_queue(Word queue_name_ptr, Word queue_name_size, Word token Word dequeue_shared_queue(Word token, Word data_ptr_ptr, Word data_size_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } std::string data; WasmResult result = context->dequeueSharedQueue(token.u32(), &data); if (result != WasmResult::Ok) { @@ -288,6 +359,9 @@ Word dequeue_shared_queue(Word token, Word data_ptr_ptr, Word data_size_ptr) { Word resolve_shared_queue(Word vm_id_ptr, Word vm_id_size, Word queue_name_ptr, Word queue_name_size, Word token_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto vm_id = context->wasmVm()->getMemory(vm_id_ptr, vm_id_size); auto queue_name = context->wasmVm()->getMemory(queue_name_ptr, queue_name_size); if (!vm_id || !queue_name) { @@ -306,6 +380,9 @@ Word resolve_shared_queue(Word vm_id_ptr, Word vm_id_size, Word queue_name_ptr, Word enqueue_shared_queue(Word token, Word data_ptr, Word data_size) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto data = context->wasmVm()->getMemory(data_ptr, data_size); if (!data) { return WasmResult::InvalidMemoryAccess; @@ -319,6 +396,9 @@ Word add_header_map_value(Word type, Word key_ptr, Word key_size, Word value_ptr return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); auto value = context->wasmVm()->getMemory(value_ptr, value_size); if (!key || !value) { @@ -334,6 +414,9 @@ Word get_header_map_value(Word type, Word key_ptr, Word key_size, Word value_ptr return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); if (!key) { return WasmResult::InvalidMemoryAccess; @@ -356,6 +439,9 @@ Word replace_header_map_value(Word type, Word key_ptr, Word key_size, Word value return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); auto value = context->wasmVm()->getMemory(value_ptr, value_size); if (!key || !value) { @@ -370,6 +456,9 @@ Word remove_header_map_value(Word type, Word key_ptr, Word key_size) { return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto key = context->wasmVm()->getMemory(key_ptr, key_size); if (!key) { return WasmResult::InvalidMemoryAccess; @@ -382,6 +471,9 @@ Word get_header_map_pairs(Word type, Word ptr_ptr, Word size_ptr) { return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } Pairs pairs; auto result = context->getHeaderMapPairs(static_cast(type.u64_), &pairs); if (result != WasmResult::Ok) { @@ -416,6 +508,9 @@ Word set_header_map_pairs(Word type, Word ptr, Word size) { return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto data = context->wasmVm()->getMemory(ptr, size); if (!data) { return WasmResult::InvalidMemoryAccess; @@ -429,6 +524,9 @@ Word get_header_map_size(Word type, Word result_ptr) { return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } uint32_t size; auto result = context->getHeaderMapSize(static_cast(type.u64_), &size); if (result != WasmResult::Ok) { @@ -446,6 +544,9 @@ Word get_buffer_bytes(Word type, Word start, Word length, Word ptr_ptr, Word siz return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto *buffer = context->getBuffer(static_cast(type.u64_)); if (buffer == nullptr) { return WasmResult::NotFound; @@ -477,6 +578,9 @@ Word get_buffer_status(Word type, Word length_ptr, Word flags_ptr) { return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto *buffer = context->getBuffer(static_cast(type.u64_)); if (buffer == nullptr) { return WasmResult::NotFound; @@ -497,6 +601,9 @@ Word set_buffer_bytes(Word type, Word start, Word length, Word data_ptr, Word da return WasmResult::BadArgument; } auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto *buffer = context->getBuffer(static_cast(type.u64_)); if (buffer == nullptr) { return WasmResult::NotFound; @@ -511,7 +618,10 @@ Word set_buffer_bytes(Word type, Word start, Word length, Word data_ptr, Word da Word http_call(Word uri_ptr, Word uri_size, Word header_pairs_ptr, Word header_pairs_size, Word body_ptr, Word body_size, Word trailer_pairs_ptr, Word trailer_pairs_size, Word timeout_milliseconds, Word token_ptr) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto uri = context->wasmVm()->getMemory(uri_ptr, uri_size); auto body = context->wasmVm()->getMemory(body_ptr, body_size); auto header_pairs = context->wasmVm()->getMemory(header_pairs_ptr, header_pairs_size); @@ -535,6 +645,9 @@ Word http_call(Word uri_ptr, Word uri_size, Word header_pairs_ptr, Word header_p Word define_metric(Word metric_type, Word name_ptr, Word name_size, Word metric_id_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto name = context->wasmVm()->getMemory(name_ptr, name_size); if (!name) { return WasmResult::InvalidMemoryAccess; @@ -553,16 +666,25 @@ Word define_metric(Word metric_type, Word name_ptr, Word name_size, Word metric_ Word increment_metric(Word metric_id, int64_t offset) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->incrementMetric(metric_id, offset); } Word record_metric(Word metric_id, uint64_t value) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->recordMetric(metric_id, value); } Word get_metric(Word metric_id, Word result_uint64_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } uint64_t value = 0; auto result = context->getMetric(metric_id, &value); if (result != WasmResult::Ok) { @@ -578,7 +700,10 @@ Word grpc_call(Word service_ptr, Word service_size, Word service_name_ptr, Word Word method_name_ptr, Word method_name_size, Word initial_metadata_ptr, Word initial_metadata_size, Word request_ptr, Word request_size, Word timeout_milliseconds, Word token_ptr) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto service = context->wasmVm()->getMemory(service_ptr, service_size); auto service_name = context->wasmVm()->getMemory(service_name_ptr, service_name_size); auto method_name = context->wasmVm()->getMemory(method_name_ptr, method_name_size); @@ -605,7 +730,10 @@ Word grpc_call(Word service_ptr, Word service_size, Word service_name_ptr, Word Word grpc_stream(Word service_ptr, Word service_size, Word service_name_ptr, Word service_name_size, Word method_name_ptr, Word method_name_size, Word initial_metadata_ptr, Word initial_metadata_size, Word token_ptr) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto service = context->wasmVm()->getMemory(service_ptr, service_size); auto service_name = context->wasmVm()->getMemory(service_name_ptr, service_name_size); auto method_name = context->wasmVm()->getMemory(method_name_ptr, method_name_size); @@ -628,17 +756,26 @@ Word grpc_stream(Word service_ptr, Word service_size, Word service_name_ptr, Wor } Word grpc_cancel(Word token) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->grpcCancel(token); } Word grpc_close(Word token) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } return context->grpcClose(token); } Word grpc_send(Word token, Word message_ptr, Word message_size, Word end_stream) { - auto *context = contextOrEffectiveContext()->root_context(); + auto *context = contextOrEffectiveContextRoot(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto message = context->wasmVm()->getMemory(message_ptr, message_size); if (!message) { return WasmResult::InvalidMemoryAccess; @@ -670,6 +807,9 @@ Word wasi_unstable_fd_prestat_dir_name(Word /*fd*/, Word /*path_ptr*/, Word /*pa // logs. Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } // Read syscall args. uint64_t log_level; @@ -721,6 +861,9 @@ Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) { // size_t iovs_len, size_t* nwritten); Word wasi_unstable_fd_write(Word fd, Word iovs, Word iovs_len, Word nwritten_ptr) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } Word nwritten(0); auto result = writevImpl(fd, iovs, iovs_len, &nwritten); @@ -745,6 +888,9 @@ Word wasi_unstable_fd_read(Word /*fd*/, Word /*iovs_ptr*/, Word /*iovs_len*/, Wo Word wasi_unstable_fd_seek(Word /*fd*/, int64_t /*offset*/, Word /*whence*/, Word /*newoffset_ptr*/) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } context->error("wasi_unstable fd_seek"); return 0; } @@ -752,6 +898,9 @@ Word wasi_unstable_fd_seek(Word /*fd*/, int64_t /*offset*/, Word /*whence*/, // __wasi_errno_t __wasi_fd_close(__wasi_fd_t fd); Word wasi_unstable_fd_close(Word /*fd*/) { auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } context->error("wasi_unstable fd_close"); return 0; } @@ -771,6 +920,9 @@ Word wasi_unstable_fd_fdstat_get(Word fd, Word statOut) { wasi_fdstat[2] = 0; auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } context->wasmVm()->setMemory(statOut, 3 * sizeof(uint64_t), &wasi_fdstat); return 0; // __WASI_ESUCCESS @@ -778,7 +930,10 @@ Word wasi_unstable_fd_fdstat_get(Word fd, Word statOut) { // __wasi_errno_t __wasi_environ_get(char **environ, char *environ_buf); Word wasi_unstable_environ_get(Word environ_array_ptr, Word environ_buf) { - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto word_size = context->wasmVm()->getWordSize(); const auto &envs = context->wasm()->envs(); for (const auto &e : envs) { @@ -805,7 +960,10 @@ Word wasi_unstable_environ_get(Word environ_array_ptr, Word environ_buf) { // __wasi_errno_t __wasi_environ_sizes_get(size_t *environ_count, size_t // *environ_buf_size); Word wasi_unstable_environ_sizes_get(Word count_ptr, Word buf_size_ptr) { - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } const auto &envs = context->wasm()->envs(); if (!context->wasmVm()->setWord(count_ptr, Word(envs.size()))) { return 21; // __WASI_EFAULT @@ -844,7 +1002,10 @@ Word wasi_unstable_clock_time_get(Word clock_id, uint64_t /*precision*/, Word result_time_uint64_ptr) { uint64_t result = 0; - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } switch (clock_id) { case 0 /* realtime */: result = context->getCurrentTimeNanoseconds(); @@ -870,7 +1031,10 @@ Word wasi_unstable_random_get(Word result_buf_ptr, Word buf_len) { if (buf_len == 0) { return 0; // __WASI_ESUCCESS } - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } std::vector random(buf_len); RAND_bytes(random.data(), random.size()); if (!context->wasmVm()->setMemory(result_buf_ptr, random.size(), random.data())) { @@ -891,12 +1055,18 @@ void emscripten_notify_memory_growth(Word /*memory_index*/) {} Word set_tick_period_milliseconds(Word period_milliseconds) { TimerToken token = 0; - return contextOrEffectiveContext()->setTimerPeriod(std::chrono::milliseconds(period_milliseconds), - &token); + auto *context = contextOrEffectiveContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } + return context->setTimerPeriod(std::chrono::milliseconds(period_milliseconds), &token); } Word get_current_time_nanoseconds(Word result_uint64_ptr) { - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } uint64_t result = context->getCurrentTimeNanoseconds(); if (!context->wasm()->setDatatype(result_uint64_ptr, result)) { return WasmResult::InvalidMemoryAccess; @@ -908,7 +1078,10 @@ Word log(Word level, Word address, Word size) { if (level > static_cast(LogLevel::Max)) { return WasmResult::BadArgument; } - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } auto message = context->wasmVm()->getMemory(address, size); if (!message) { return WasmResult::InvalidMemoryAccess; @@ -917,7 +1090,10 @@ Word log(Word level, Word address, Word size) { } Word get_log_level(Word result_level_uint32_ptr) { - auto *context = contextOrEffectiveContext(); + auto *context = getLimitedContext(); + if (context == nullptr) { + return WasmResult::InternalFailure; + } uint32_t level = context->getLogLevel(); if (!context->wasm()->setDatatype(result_level_uint32_ptr, level)) { return WasmResult::InvalidMemoryAccess; diff --git a/src/wasm.cc b/src/wasm.cc index cb1dd9b3a..f1eb1195b 100644 --- a/src/wasm.cc +++ b/src/wasm.cc @@ -261,6 +261,15 @@ bool WasmBase::load(const std::string &code, bool allow_precompiled) { abi_version_ = AbiVersion::ProxyWasm_0_2_1; return true; } + if (wasm_vm_->getEngineName() == "dyn") { + auto ok = wasm_vm_->load(code, {}, {}); + if (!ok) { + fail(FailState::UnableToInitializeCode, "Failed to load DynVM plugin"); + return false; + } + abi_version_ = AbiVersion::ProxyWasm_0_2_1; + return true; + } // Verify signature. std::string message; From 2b3c40d415bcd09adaadcdf9414371a15178c856 Mon Sep 17 00:00:00 2001 From: Protryon Date: Tue, 26 Mar 2024 11:38:26 -0700 Subject: [PATCH 2/5] add tests for dynvm Signed-off-by: Protryon --- .github/workflows/test.yml | 6 ++++ BUILD | 1 + bazel/wasm.bzl | 39 ++++++++++++++++++++++++++ include/proxy-wasm/dyn_vm.h | 3 -- src/dyn/dyn.cc | 1 + src/dyn/dyn_vm.cc | 20 ++++++------- src/dyn/dyn_vm_plugin.cc | 56 ++++++++++++++++++------------------- test/BUILD | 15 ++++++++++ test/test_data/BUILD | 6 ++++ test/utility.cc | 11 ++++++++ test/utility.h | 7 +++++ 11 files changed, 124 insertions(+), 41 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 811c6a369..3c9cbfa66 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -113,6 +113,12 @@ jobs: arch: x86_64 action: test flags: --config=gcc + - name: 'DynVM on Linux/x86_64' + engine: 'dyn' + os: ubuntu-20.04 + arch: x86_64 + action: test + flags: --config=gcc - name: 'NullVM on Linux/x86_64 with ASan' engine: 'null' os: ubuntu-22.04 diff --git a/BUILD b/BUILD index c82e0fa8c..92cf3e7ad 100644 --- a/BUILD +++ b/BUILD @@ -132,6 +132,7 @@ cc_library( "src/dyn/dyn_vm_plugin.cc", ], hdrs = [ + "include/proxy-wasm/dyn.h", "include/proxy-wasm/dyn_vm.h", "include/proxy-wasm/dyn_vm_plugin.h", "include/proxy-wasm/wasm_api_impl.h", diff --git a/bazel/wasm.bzl b/bazel/wasm.bzl index 192823047..a1cf26c4b 100644 --- a/bazel/wasm.bzl +++ b/bazel/wasm.bzl @@ -13,6 +13,7 @@ # limitations under the License. load("@rules_rust//rust:defs.bzl", "rust_binary") +load("@rules_rust//rust:defs.bzl", "rust_shared_library") def _wasm_rust_transition_impl(settings, attr): return { @@ -59,6 +60,17 @@ def _wasm_binary_impl(ctx): return [DefaultInfo(files = depset([out]), runfiles = ctx.runfiles([out]))] +def _dyn_binary_impl(ctx): + out = ctx.actions.declare_file(ctx.label.name) + ctx.actions.run( + executable = "cp", + arguments = [ctx.files.binary[0].path, out.path], + outputs = [out], + inputs = ctx.files.binary, + ) + + return [DefaultInfo(files = depset([out]), runfiles = ctx.runfiles([out]))] + def _wasm_attrs(transition): return { "binary": attr.label(mandatory = True, cfg = transition), @@ -67,6 +79,11 @@ def _wasm_attrs(transition): "_whitelist_function_transition": attr.label(default = "@bazel_tools//tools/whitelists/function_transition_whitelist"), } +def _dyn_attrs(): + return { + "binary": attr.label(mandatory = True), + } + wasm_rust_binary_rule = rule( implementation = _wasm_binary_impl, attrs = _wasm_attrs(wasm_rust_transition), @@ -77,6 +94,11 @@ wasi_rust_binary_rule = rule( attrs = _wasm_attrs(wasi_rust_transition), ) +dyn_rust_binary_rule = rule( + implementation = _dyn_binary_impl, + attrs = _dyn_attrs(), +) + def wasm_rust_binary(name, tags = [], wasi = False, signing_key = [], **kwargs): wasm_name = "_wasm_" + name.replace(".", "_") kwargs.setdefault("visibility", ["//visibility:public"]) @@ -100,3 +122,20 @@ def wasm_rust_binary(name, tags = [], wasi = False, signing_key = [], **kwargs): signing_key = signing_key, tags = tags + ["manual"], ) + +def dyn_rust_library(name, tags = [], **kwargs): + dyn_name = "_dyn_" + name.replace(".", "_") + kwargs.setdefault("visibility", ["//visibility:public"]) + + rust_shared_library( + name = dyn_name, + edition = "2018", + tags = ["manual"], + **kwargs + ) + + dyn_rust_binary_rule( + name = name, + binary = ":" + dyn_name, + tags = tags + ["manual"], + ) diff --git a/include/proxy-wasm/dyn_vm.h b/include/proxy-wasm/dyn_vm.h index bd9b72a47..3ce190fd7 100644 --- a/include/proxy-wasm/dyn_vm.h +++ b/include/proxy-wasm/dyn_vm.h @@ -24,9 +24,6 @@ namespace proxy_wasm { -class WasmVm; -std::unique_ptr createDynVm(); - // The DynVm wraps a C++ Wasm plugin which has been compiled with the Wasm API // and dynamically linked into the proxy. struct DynVm : public WasmVm { diff --git a/src/dyn/dyn.cc b/src/dyn/dyn.cc index cba231af5..8c6b1e9d4 100644 --- a/src/dyn/dyn.cc +++ b/src/dyn/dyn.cc @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "include/proxy-wasm/dyn.h" #include "include/proxy-wasm/dyn_vm.h" namespace proxy_wasm { diff --git a/src/dyn/dyn_vm.cc b/src/dyn/dyn_vm.cc index a62d78e52..85a8e32e5 100644 --- a/src/dyn/dyn_vm.cc +++ b/src/dyn/dyn_vm.cc @@ -16,16 +16,15 @@ #include "include/proxy-wasm/dyn_vm.h" #include - +#include #include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include namespace proxy_wasm { @@ -42,7 +41,7 @@ std::unique_ptr DynVm::clone() { } // "Load" the plugin by obtaining a pointer to it from the factory. -bool DynVm::load(std::string_view shared_lib, std::string_view /*precompiled*/, +bool DynVm::load(std::string_view plugin_name, std::string_view /*precompiled*/, const std::unordered_map & /*function_names*/) { plugin_ = std::make_unique(); plugin_->source = std::make_shared(); @@ -59,13 +58,14 @@ bool DynVm::load(std::string_view shared_lib, std::string_view /*precompiled*/, size_t written = 0; ssize_t wrote; - const char *data = shared_lib.data(); - while (written < shared_lib.size()) { - wrote = write(plugin_->source->memfd, data + written, shared_lib.length() - written); + const char *data = plugin_name.data(); + while (written < plugin_name.size()) { + wrote = write(plugin_->source->memfd, data + written, plugin_name.length() - written); if (wrote < 0) { integration()->error("failed to write to memfd: " + std::string(strerror(errno))); return false; - } else if (wrote == 0) { + } + if (wrote == 0) { integration()->error("failed to write to memfd, EOF on write"); return false; } diff --git a/src/dyn/dyn_vm_plugin.cc b/src/dyn/dyn_vm_plugin.cc index 52964f65a..84e016565 100644 --- a/src/dyn/dyn_vm_plugin.cc +++ b/src/dyn/dyn_vm_plugin.cc @@ -16,14 +16,14 @@ #include "include/proxy-wasm/wasm_vm.h" #include "include/proxy-wasm/dyn_vm_plugin.h" -#include +#include #include -#include +#include #include -#include #include +#include +#include #include -#include namespace proxy_wasm { @@ -61,16 +61,16 @@ DynVmPluginSource::~DynVmPluginSource() { } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<0> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - void (*target_func)() = reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context) { proxy_wasm::SaveRestoreContext saved_context(context); wasm_vm_->integration()->trace(call_format(function_name, 0)); @@ -79,16 +79,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<1> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - void (*target_func)(uint64_t) = reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1) { proxy_wasm::SaveRestoreContext saved_context(context); wasm_vm_->integration()->trace(call_format(function_name, 1, w1)); @@ -97,16 +97,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<2> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - void (*target_func)(uint64_t, uint64_t) = reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2) { proxy_wasm::SaveRestoreContext saved_context(context); @@ -116,16 +116,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<3> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - void (*target_func)(uint64_t, uint64_t, uint64_t) = + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2, proxy_wasm::Word w3) { @@ -136,16 +136,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallVoid<5> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - void (*target_func)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) = + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2, proxy_wasm::Word w3, @@ -157,16 +157,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<1> *f) { - if (source->dl_handle == NULL || function_name == "malloc") { + if (source->dl_handle == nullptr || function_name == "malloc") { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - uint64_t (*target_func)(uint64_t) = reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1) { proxy_wasm::SaveRestoreContext saved_context(context); wasm_vm_->integration()->trace(call_format(function_name, 1, w1)); @@ -175,16 +175,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<2> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - uint64_t (*target_func)(uint64_t, uint64_t) = + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2) { @@ -195,16 +195,16 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa } void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCallWord<3> *f) { - if (source->dl_handle == NULL) { + if (source->dl_handle == nullptr) { *f = nullptr; return; } void *target = dlsym(source->dl_handle, std::string(function_name).c_str()); - if (target == NULL) { + if (target == nullptr) { *f = nullptr; return; } - uint64_t (*target_func)(uint64_t, uint64_t, uint64_t) = + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2, proxy_wasm::Word w3) { diff --git a/test/BUILD b/test/BUILD index 61973ce17..83f33d666 100644 --- a/test/BUILD +++ b/test/BUILD @@ -180,6 +180,21 @@ cc_test( ], ) +cc_test( + name = "dyn_vm_test", + srcs = ["dyn_vm_test.cc"], + data = [ + "//test/test_data:abi_export.so", + ], + linkstatic = 1, + deps = [ + ":utility_lib", + "//:lib", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "wasm_vm_test", timeout = "long", diff --git a/test/test_data/BUILD b/test/test_data/BUILD index bd70b8eb9..39d959e6e 100644 --- a/test/test_data/BUILD +++ b/test/test_data/BUILD @@ -13,6 +13,7 @@ # limitations under the License. load("@proxy_wasm_cpp_host//bazel:wasm.bzl", "wasm_rust_binary") +load("@proxy_wasm_cpp_host//bazel:wasm.bzl", "dyn_rust_library") load("@proxy_wasm_cpp_sdk//bazel:defs.bzl", "proxy_wasm_cc_binary") licenses(["notice"]) # Apache 2 @@ -24,6 +25,11 @@ wasm_rust_binary( srcs = ["abi_export.rs"], ) +dyn_rust_library( + name = "abi_export.so", + srcs = ["abi_export.rs"], +) + wasm_rust_binary( name = "abi_export.signed.with.key1.wasm", srcs = ["abi_export.rs"], diff --git a/test/utility.cc b/test/utility.cc index ee6f2b951..d17424fe3 100644 --- a/test/utility.cc +++ b/test/utility.cc @@ -41,6 +41,17 @@ std::vector getWasmEngines() { return engines; } +std::vector getDynEngines() { + std::vector engines = { +#if defined(PROXY_WASM_HOST_ENGINE_DYN) + "dyn", +#endif + "" + }; + engines.pop_back(); + return engines; +} + std::string readTestWasmFile(const std::string &filename) { auto path = "test/test_data/" + filename; std::ifstream file(path, std::ios::binary); diff --git a/test/utility.h b/test/utility.h index 27b3b0493..01f165afd 100644 --- a/test/utility.h +++ b/test/utility.h @@ -39,6 +39,9 @@ #if defined(PROXY_WASM_HOST_ENGINE_WAMR) #include "include/proxy-wasm/wamr.h" #endif +#if defined(PROXY_WASM_HOST_ENGINE_DYN) +#include "include/proxy-wasm/dyn.h" +#endif namespace proxy_wasm { @@ -185,6 +188,10 @@ class TestVm : public testing::TestWithParam { #if defined(PROXY_WASM_HOST_ENGINE_WAMR) } else if (engine == "wamr") { vm = proxy_wasm::createWamrVm(); +#endif +#if defined(PROXY_WASM_HOST_ENGINE_DYN) + } else if (engine == "dyn") { + vm = proxy_wasm::createDynVm(); #endif } else { ADD_FAILURE() << "compiled without support for the requested \"" << engine << "\" engine"; From 46ea9d68a8df65bab73e720c36a78e2efcdf2ec9 Mon Sep 17 00:00:00 2001 From: Protryon Date: Tue, 10 Sep 2024 14:04:53 -0700 Subject: [PATCH 3/5] include missing files Signed-off-by: Protryon --- include/proxy-wasm/dyn.h | 25 ++++++++++ test/dyn_vm_test.cc | 99 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 include/proxy-wasm/dyn.h create mode 100644 test/dyn_vm_test.cc diff --git a/include/proxy-wasm/dyn.h b/include/proxy-wasm/dyn.h new file mode 100644 index 000000000..c24b9af8c --- /dev/null +++ b/include/proxy-wasm/dyn.h @@ -0,0 +1,25 @@ +// Copyright 2016-2019 Envoy Project Authors +// Copyright 2020 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 + +namespace proxy_wasm { + +class WasmVm; +std::unique_ptr createDynVm(); + +} // namespace proxy_wasm diff --git a/test/dyn_vm_test.cc b/test/dyn_vm_test.cc new file mode 100644 index 000000000..72247de2b --- /dev/null +++ b/test/dyn_vm_test.cc @@ -0,0 +1,99 @@ +// Copyright 2020 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 "gtest/gtest.h" + +#include +#include +#include + +#include "include/proxy-wasm/wasm_vm.h" + +#include "test/utility.h" + +namespace proxy_wasm { +namespace { + +std::vector getDynEngines() { + std::vector engines = { +#if defined(PROXY_WASM_HOST_ENGINE_DYN) + "dyn", +#endif + "" + }; + engines.pop_back(); + return engines; +} + +INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getDynEngines()), + [](const testing::TestParamInfo &info) { + return info.param; + }); + +TEST_P(TestVm, Basic) { + EXPECT_EQ(vm_->getEngineName(), engine_); + EXPECT_EQ(vm_->getEngineName(), "dyn"); + EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::InstantiatedModule); +} + +TEST_P(TestVm, Memory) { + auto source = readTestWasmFile("abi_export.so"); + ASSERT_TRUE(vm_->load(source, {}, {})); + ASSERT_TRUE(vm_->link("")); + + uint64_t raw_word = 0; + + Word word; + ASSERT_TRUE(vm_->setWord(reinterpret_cast(&raw_word), Word(100))); + ASSERT_TRUE(vm_->getWord(reinterpret_cast(&raw_word), &word)); + ASSERT_EQ(100, word.u64_); + ASSERT_EQ(100, raw_word); + + uint32_t raw_data[2] = {0, 0}; + + uint32_t data[2] = {htowasm(static_cast(-1), vm_->usesWasmByteOrder()), + htowasm(200, vm_->usesWasmByteOrder())}; + ASSERT_TRUE(vm_->setMemory(reinterpret_cast(&raw_data[0]), sizeof(int32_t) * 2, + static_cast(data))); + ASSERT_TRUE(vm_->getWord(reinterpret_cast(&raw_data[0]), &word)); + ASSERT_EQ(-1, static_cast(word.u64_)); + ASSERT_TRUE(vm_->getWord(reinterpret_cast(&raw_data[1]), &word)); + ASSERT_EQ(200, static_cast(word.u64_)); +} + +TEST_P(TestVm, ReadWrite) { + auto source = readTestWasmFile("abi_export.so"); + ASSERT_TRUE(vm_->load(source, {}, {})); + ASSERT_TRUE(vm_->link("")); + BufferBase buffer; + buffer.set("test data"); + uint64_t buffer_raw = 0; + uint64_t buffer_len = 0; + auto wasm = TestWasm(std::move(vm_), {}); + ASSERT_TRUE(wasm.initialize()); + ASSERT_EQ(buffer.copyTo(&wasm, 0, buffer.size(), reinterpret_cast(&buffer_raw), + reinterpret_cast(&buffer_len)), + WasmResult::Ok); + + ASSERT_NE(buffer_raw, 0); + ASSERT_NE(buffer_len, 0); + + char *buffer_ptr = reinterpret_cast(buffer_raw); + ASSERT_EQ(buffer_len, buffer.size()); + std::string buffer_str(buffer_ptr, buffer_ptr + buffer_len); + ASSERT_EQ(buffer_str, "test data"); +} + +} // namespace +} // namespace proxy_wasm From ef5850946be83b78980d878b94de9dc50faeeee6 Mon Sep 17 00:00:00 2001 From: Protryon Date: Tue, 10 Sep 2024 14:22:48 -0700 Subject: [PATCH 4/5] remove wasmResultToWord, add limited context comment Signed-off-by: Protryon --- src/dyn/dyn_ffi.cc | 308 +++++++++++++++++++-------------------- src/dyn/dyn_vm_plugin.cc | 9 +- src/exports.cc | 1 + 3 files changed, 157 insertions(+), 161 deletions(-) diff --git a/src/dyn/dyn_ffi.cc b/src/dyn/dyn_ffi.cc index 81110d3f7..364729915 100644 --- a/src/dyn/dyn_ffi.cc +++ b/src/dyn/dyn_ffi.cc @@ -15,243 +15,241 @@ #include "include/proxy-wasm/wasm_vm.h" #include "include/proxy-wasm/wasm_api_impl.h" - -inline uint32_t wasmResultToWord(proxy_wasm::WasmResult result) { - return static_cast(result); -} +#include extern "C" { // Configuration and Status -extern size_t proxy_get_configuration(const char **configuration_ptr, size_t *configuration_size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_get_configuration(configuration_ptr, configuration_size)); +extern proxy_wasm::WasmResult proxy_get_configuration(const char **configuration_ptr, + size_t *configuration_size) { + return proxy_wasm::null_plugin::proxy_get_configuration(configuration_ptr, configuration_size); } -uint32_t proxy_get_status(uint32_t *code_ptr, const char **ptr, size_t *size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_status(code_ptr, ptr, size)); +proxy_wasm::WasmResult proxy_get_status(uint32_t *code_ptr, const char **ptr, size_t *size) { + return proxy_wasm::null_plugin::proxy_get_status(code_ptr, ptr, size); } // Logging -uint32_t proxy_log(proxy_wasm::LogLevel level, const char *logMessage, size_t messageSize) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_log(level, logMessage, messageSize)); +proxy_wasm::WasmResult proxy_log(proxy_wasm::LogLevel level, const char *logMessage, + size_t messageSize) { + return proxy_wasm::null_plugin::proxy_log(level, logMessage, messageSize); } -uint32_t proxy_get_log_level(proxy_wasm::LogLevel *level) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_log_level(level)); +proxy_wasm::WasmResult proxy_get_log_level(proxy_wasm::LogLevel *level) { + return proxy_wasm::null_plugin::proxy_get_log_level(level); } // Timer -uint32_t proxy_set_tick_period_milliseconds(uint64_t millisecond) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_tick_period_milliseconds(millisecond)); +proxy_wasm::WasmResult proxy_set_tick_period_milliseconds(uint64_t millisecond) { + return proxy_wasm::null_plugin::proxy_set_tick_period_milliseconds(millisecond); } -uint32_t proxy_get_current_time_nanoseconds(uint64_t *result) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_current_time_nanoseconds(result)); +proxy_wasm::WasmResult proxy_get_current_time_nanoseconds(uint64_t *result) { + return proxy_wasm::null_plugin::proxy_get_current_time_nanoseconds(result); } // State accessors -uint32_t proxy_get_property(const char *path_ptr, size_t path_size, const char **value_ptr_ptr, - size_t *value_size_ptr) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_property( - path_ptr, path_size, value_ptr_ptr, value_size_ptr)); +proxy_wasm::WasmResult proxy_get_property(const char *path_ptr, size_t path_size, + const char **value_ptr_ptr, size_t *value_size_ptr) { + return proxy_wasm::null_plugin::proxy_get_property(path_ptr, path_size, value_ptr_ptr, + value_size_ptr); } -uint32_t proxy_set_property(const char *key_ptr, size_t key_size, const char *value_ptr, - size_t value_size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_set_property(key_ptr, key_size, value_ptr, value_size)); +proxy_wasm::WasmResult proxy_set_property(const char *key_ptr, size_t key_size, + const char *value_ptr, size_t value_size) { + return proxy_wasm::null_plugin::proxy_set_property(key_ptr, key_size, value_ptr, value_size); } // Continue -uint32_t proxy_continue_request() { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_request()); +proxy_wasm::WasmResult proxy_continue_request() { + return proxy_wasm::null_plugin::proxy_continue_request(); } -uint32_t proxy_continue_response() { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_response()); +proxy_wasm::WasmResult proxy_continue_response() { + return proxy_wasm::null_plugin::proxy_continue_response(); } -uint32_t proxy_continue_stream(proxy_wasm::WasmStreamType stream_type) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_continue_stream(stream_type)); +proxy_wasm::WasmResult proxy_continue_stream(proxy_wasm::WasmStreamType stream_type) { + return proxy_wasm::null_plugin::proxy_continue_stream(stream_type); } -uint32_t proxy_close_stream(proxy_wasm::WasmStreamType stream_type) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_close_stream(stream_type)); +proxy_wasm::WasmResult proxy_close_stream(proxy_wasm::WasmStreamType stream_type) { + return proxy_wasm::null_plugin::proxy_close_stream(stream_type); } -uint32_t proxy_send_local_response(uint32_t response_code, const char *response_code_details_ptr, - size_t response_code_details_size, const char *body_ptr, - size_t body_size, - const char *additional_response_header_pairs_ptr, - size_t additional_response_header_pairs_size, - uint32_t grpc_status) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_send_local_response( +proxy_wasm::WasmResult +proxy_send_local_response(uint32_t response_code, const char *response_code_details_ptr, + size_t response_code_details_size, const char *body_ptr, size_t body_size, + const char *additional_response_header_pairs_ptr, + size_t additional_response_header_pairs_size, uint32_t grpc_status) { + return proxy_wasm::null_plugin::proxy_send_local_response( response_code, response_code_details_ptr, response_code_details_size, body_ptr, body_size, - additional_response_header_pairs_ptr, additional_response_header_pairs_size, grpc_status)); + additional_response_header_pairs_ptr, additional_response_header_pairs_size, grpc_status); } -uint32_t proxy_clear_route_cache() { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_clear_route_cache()); +proxy_wasm::WasmResult proxy_clear_route_cache() { + return proxy_wasm::null_plugin::proxy_clear_route_cache(); } // SharedData -uint32_t proxy_get_shared_data(const char *key_ptr, size_t key_size, const char **value_ptr, - size_t *value_size, uint32_t *cas) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_shared_data( - key_ptr, key_size, value_ptr, value_size, cas)); +proxy_wasm::WasmResult proxy_get_shared_data(const char *key_ptr, size_t key_size, + const char **value_ptr, size_t *value_size, + uint32_t *cas) { + return proxy_wasm::null_plugin::proxy_get_shared_data(key_ptr, key_size, value_ptr, value_size, + cas); } // If cas != 0 and cas != the current cas for 'key' return false, otherwise set the value and // return true. -uint32_t proxy_set_shared_data(const char *key_ptr, size_t key_size, const char *value_ptr, - size_t value_size, uint64_t cas) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_shared_data( - key_ptr, key_size, value_ptr, value_size, cas)); +proxy_wasm::WasmResult proxy_set_shared_data(const char *key_ptr, size_t key_size, + const char *value_ptr, size_t value_size, + uint64_t cas) { + return proxy_wasm::null_plugin::proxy_set_shared_data(key_ptr, key_size, value_ptr, value_size, + cas); } // SharedQueue // Note: Registering the same queue_name will overwrite the old registration while preseving any // pending data. Consequently it should typically be followed by a call to // proxy_dequeue_shared_queue. Returns unique token for the queue. -uint32_t proxy_register_shared_queue(const char *queue_name_ptr, size_t queue_name_size, - uint32_t *token) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_register_shared_queue(queue_name_ptr, queue_name_size, token)); +proxy_wasm::WasmResult proxy_register_shared_queue(const char *queue_name_ptr, + size_t queue_name_size, uint32_t *token) { + return proxy_wasm::null_plugin::proxy_register_shared_queue(queue_name_ptr, queue_name_size, + token); } // Returns unique token for the queue. -uint32_t proxy_resolve_shared_queue(const char *vm_id_ptr, size_t vm_id_size, - const char *queue_name_ptr, size_t queue_name_size, - uint32_t *token) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_resolve_shared_queue( - vm_id_ptr, vm_id_size, queue_name_ptr, queue_name_size, token)); +proxy_wasm::WasmResult proxy_resolve_shared_queue(const char *vm_id_ptr, size_t vm_id_size, + const char *queue_name_ptr, + size_t queue_name_size, uint32_t *token) { + return proxy_wasm::null_plugin::proxy_resolve_shared_queue(vm_id_ptr, vm_id_size, queue_name_ptr, + queue_name_size, token); } // Returns true on end-of-stream (no more data available). -uint32_t proxy_dequeue_shared_queue(uint32_t token, const char **data_ptr, size_t *data_size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_dequeue_shared_queue(token, data_ptr, data_size)); +proxy_wasm::WasmResult proxy_dequeue_shared_queue(uint32_t token, const char **data_ptr, + size_t *data_size) { + return proxy_wasm::null_plugin::proxy_dequeue_shared_queue(token, data_ptr, data_size); } // Returns false if the queue was not found and the data was not enqueued. -uint32_t proxy_enqueue_shared_queue(uint32_t token, const char *data_ptr, size_t data_size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_enqueue_shared_queue(token, data_ptr, data_size)); +proxy_wasm::WasmResult proxy_enqueue_shared_queue(uint32_t token, const char *data_ptr, + size_t data_size) { + return proxy_wasm::null_plugin::proxy_enqueue_shared_queue(token, data_ptr, data_size); } // Buffer -uint32_t proxy_get_buffer_bytes(proxy_wasm::WasmBufferType type, size_t start, size_t length, - const char **ptr, size_t *size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_get_buffer_bytes(type, start, length, ptr, size)); +proxy_wasm::WasmResult proxy_get_buffer_bytes(proxy_wasm::WasmBufferType type, size_t start, + size_t length, const char **ptr, size_t *size) { + return proxy_wasm::null_plugin::proxy_get_buffer_bytes(type, start, length, ptr, size); } -uint32_t proxy_get_buffer_status(proxy_wasm::WasmBufferType type, size_t *length_ptr, - uint32_t *flags_ptr) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_get_buffer_status(type, length_ptr, flags_ptr)); +proxy_wasm::WasmResult proxy_get_buffer_status(proxy_wasm::WasmBufferType type, size_t *length_ptr, + uint32_t *flags_ptr) { + return proxy_wasm::null_plugin::proxy_get_buffer_status(type, length_ptr, flags_ptr); } -uint32_t proxy_set_buffer_bytes(proxy_wasm::WasmBufferType type, uint64_t start, uint64_t length, - const char *data, size_t size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_set_buffer_bytes(type, start, length, data, size)); +proxy_wasm::WasmResult proxy_set_buffer_bytes(proxy_wasm::WasmBufferType type, uint64_t start, + uint64_t length, const char *data, size_t size) { + return proxy_wasm::null_plugin::proxy_set_buffer_bytes(type, start, length, data, size); } // Headers/Trailers/Metadata Maps -uint32_t proxy_add_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, - size_t key_size, const char *value_ptr, size_t value_size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_add_header_map_value( - type, key_ptr, key_size, value_ptr, value_size)); -} -uint32_t proxy_get_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, - size_t key_size, const char **value_ptr, size_t *value_size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_value( - type, key_ptr, key_size, value_ptr, value_size)); -} -uint32_t proxy_get_header_map_pairs(proxy_wasm::WasmHeaderMapType type, const char **ptr, - size_t *size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_pairs(type, ptr, size)); -} -uint32_t proxy_set_header_map_pairs(proxy_wasm::WasmHeaderMapType type, const char *ptr, - size_t size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_header_map_pairs(type, ptr, size)); -} -uint32_t proxy_replace_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, - size_t key_size, const char *value_ptr, size_t value_size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_replace_header_map_value( - type, key_ptr, key_size, value_ptr, value_size)); -} -uint32_t proxy_remove_header_map_value(proxy_wasm::WasmHeaderMapType type, const char *key_ptr, - size_t key_size) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_remove_header_map_value(type, key_ptr, key_size)); -} -uint32_t proxy_get_header_map_size(proxy_wasm::WasmHeaderMapType type, size_t *size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_header_map_size(type, size)); +proxy_wasm::WasmResult proxy_add_header_map_value(proxy_wasm::WasmHeaderMapType type, + const char *key_ptr, size_t key_size, + const char *value_ptr, size_t value_size) { + return proxy_wasm::null_plugin::proxy_add_header_map_value(type, key_ptr, key_size, value_ptr, + value_size); +} +proxy_wasm::WasmResult proxy_get_header_map_value(proxy_wasm::WasmHeaderMapType type, + const char *key_ptr, size_t key_size, + const char **value_ptr, size_t *value_size) { + return proxy_wasm::null_plugin::proxy_get_header_map_value(type, key_ptr, key_size, value_ptr, + value_size); +} +proxy_wasm::WasmResult proxy_get_header_map_pairs(proxy_wasm::WasmHeaderMapType type, + const char **ptr, size_t *size) { + return proxy_wasm::null_plugin::proxy_get_header_map_pairs(type, ptr, size); +} +proxy_wasm::WasmResult proxy_set_header_map_pairs(proxy_wasm::WasmHeaderMapType type, + const char *ptr, size_t size) { + return proxy_wasm::null_plugin::proxy_set_header_map_pairs(type, ptr, size); +} +proxy_wasm::WasmResult proxy_replace_header_map_value(proxy_wasm::WasmHeaderMapType type, + const char *key_ptr, size_t key_size, + const char *value_ptr, size_t value_size) { + return proxy_wasm::null_plugin::proxy_replace_header_map_value(type, key_ptr, key_size, value_ptr, + value_size); +} +proxy_wasm::WasmResult proxy_remove_header_map_value(proxy_wasm::WasmHeaderMapType type, + const char *key_ptr, size_t key_size) { + return proxy_wasm::null_plugin::proxy_remove_header_map_value(type, key_ptr, key_size); +} +proxy_wasm::WasmResult proxy_get_header_map_size(proxy_wasm::WasmHeaderMapType type, size_t *size) { + return proxy_wasm::null_plugin::proxy_get_header_map_size(type, size); } // HTTP // Returns token, used in callback onHttpCallResponse -uint32_t proxy_http_call(const char *uri_ptr, size_t uri_size, void *header_pairs_ptr, - size_t header_pairs_size, const char *body_ptr, size_t body_size, - void *trailer_pairs_ptr, size_t trailer_pairs_size, - uint64_t timeout_milliseconds, uint32_t *token_ptr) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_http_call( +proxy_wasm::WasmResult proxy_http_call(const char *uri_ptr, size_t uri_size, void *header_pairs_ptr, + size_t header_pairs_size, const char *body_ptr, + size_t body_size, void *trailer_pairs_ptr, + size_t trailer_pairs_size, uint64_t timeout_milliseconds, + uint32_t *token_ptr) { + return proxy_wasm::null_plugin::proxy_http_call( uri_ptr, uri_size, header_pairs_ptr, header_pairs_size, body_ptr, body_size, - trailer_pairs_ptr, trailer_pairs_size, timeout_milliseconds, token_ptr)); + trailer_pairs_ptr, trailer_pairs_size, timeout_milliseconds, token_ptr); } // gRPC // Returns token, used in gRPC callbacks (onGrpc...) -uint32_t proxy_grpc_call(const char *service_ptr, size_t service_size, const char *service_name_ptr, - size_t service_name_size, const char *method_name_ptr, - size_t method_name_size, void *initial_metadata_ptr, - size_t initial_metadata_size, const char *request_ptr, size_t request_size, - uint64_t timeout_milliseconds, uint32_t *token_ptr) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_call( +proxy_wasm::WasmResult proxy_grpc_call(const char *service_ptr, size_t service_size, + const char *service_name_ptr, size_t service_name_size, + const char *method_name_ptr, size_t method_name_size, + void *initial_metadata_ptr, size_t initial_metadata_size, + const char *request_ptr, size_t request_size, + uint64_t timeout_milliseconds, uint32_t *token_ptr) { + return proxy_wasm::null_plugin::proxy_grpc_call( service_ptr, service_size, service_name_ptr, service_name_size, method_name_ptr, method_name_size, initial_metadata_ptr, initial_metadata_size, request_ptr, request_size, - timeout_milliseconds, token_ptr)); -} -uint32_t proxy_grpc_stream(const char *service_ptr, size_t service_size, - const char *service_name_ptr, size_t service_name_size, - const char *method_name_ptr, size_t method_name_size, - void *initial_metadata_ptr, size_t initial_metadata_size, - uint32_t *token_ptr) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_stream( + timeout_milliseconds, token_ptr); +} +proxy_wasm::WasmResult proxy_grpc_stream(const char *service_ptr, size_t service_size, + const char *service_name_ptr, size_t service_name_size, + const char *method_name_ptr, size_t method_name_size, + void *initial_metadata_ptr, size_t initial_metadata_size, + uint32_t *token_ptr) { + return proxy_wasm::null_plugin::proxy_grpc_stream( service_ptr, service_size, service_name_ptr, service_name_size, method_name_ptr, - method_name_size, initial_metadata_ptr, initial_metadata_size, token_ptr)); + method_name_size, initial_metadata_ptr, initial_metadata_size, token_ptr); } -uint32_t proxy_grpc_cancel(uint64_t token) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_cancel(token)); +proxy_wasm::WasmResult proxy_grpc_cancel(uint64_t token) { + return proxy_wasm::null_plugin::proxy_grpc_cancel(token); } -uint32_t proxy_grpc_close(uint64_t token) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_grpc_close(token)); +proxy_wasm::WasmResult proxy_grpc_close(uint64_t token) { + return proxy_wasm::null_plugin::proxy_grpc_close(token); } -uint32_t proxy_grpc_send(uint64_t token, const char *message_ptr, size_t message_size, - uint64_t end_stream) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_grpc_send(token, message_ptr, message_size, end_stream)); +proxy_wasm::WasmResult proxy_grpc_send(uint64_t token, const char *message_ptr, size_t message_size, + uint64_t end_stream) { + return proxy_wasm::null_plugin::proxy_grpc_send(token, message_ptr, message_size, end_stream); } // Metrics // Returns a metric_id which can be used to report a metric. On error returns 0. -uint32_t proxy_define_metric(proxy_wasm::MetricType type, const char *name_ptr, size_t name_size, - uint32_t *metric_id) { - return wasmResultToWord( - proxy_wasm::null_plugin::proxy_define_metric(type, name_ptr, name_size, metric_id)); +proxy_wasm::WasmResult proxy_define_metric(proxy_wasm::MetricType type, const char *name_ptr, + size_t name_size, uint32_t *metric_id) { + return proxy_wasm::null_plugin::proxy_define_metric(type, name_ptr, name_size, metric_id); } -uint32_t proxy_increment_metric(uint32_t metric_id, int64_t offset) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_increment_metric(metric_id, offset)); +proxy_wasm::WasmResult proxy_increment_metric(uint32_t metric_id, int64_t offset) { + return proxy_wasm::null_plugin::proxy_increment_metric(metric_id, offset); } -uint32_t proxy_record_metric(uint32_t metric_id, uint64_t value) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_record_metric(metric_id, value)); +proxy_wasm::WasmResult proxy_record_metric(uint32_t metric_id, uint64_t value) { + return proxy_wasm::null_plugin::proxy_record_metric(metric_id, value); } -uint32_t proxy_get_metric(uint32_t metric_id, uint64_t *value) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_get_metric(metric_id, value)); +proxy_wasm::WasmResult proxy_get_metric(uint32_t metric_id, uint64_t *value) { + return proxy_wasm::null_plugin::proxy_get_metric(metric_id, value); } // System -uint32_t proxy_set_effective_context(uint64_t context_id) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_set_effective_context(context_id)); +proxy_wasm::WasmResult proxy_set_effective_context(uint64_t context_id) { + return proxy_wasm::null_plugin::proxy_set_effective_context(context_id); } -uint32_t proxy_done() { return wasmResultToWord(proxy_wasm::null_plugin::proxy_done()); } +proxy_wasm::WasmResult proxy_done() { return proxy_wasm::null_plugin::proxy_done(); } -uint32_t proxy_call_foreign_function(const char *function_name, size_t function_name_size, - const char *arguments, size_t arguments_size, char **results, - size_t *results_size) { - return wasmResultToWord(proxy_wasm::null_plugin::proxy_call_foreign_function( - function_name, function_name_size, arguments, arguments_size, results, results_size)); +proxy_wasm::WasmResult proxy_call_foreign_function(const char *function_name, + size_t function_name_size, const char *arguments, + size_t arguments_size, char **results, + size_t *results_size) { + return proxy_wasm::null_plugin::proxy_call_foreign_function( + function_name, function_name_size, arguments, arguments_size, results, results_size); } // following functions only exposed in dyn native contexts diff --git a/src/dyn/dyn_vm_plugin.cc b/src/dyn/dyn_vm_plugin.cc index 84e016565..c252764d4 100644 --- a/src/dyn/dyn_vm_plugin.cc +++ b/src/dyn/dyn_vm_plugin.cc @@ -125,8 +125,7 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa *f = nullptr; return; } - auto target_func = - reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2, proxy_wasm::Word w3) { proxy_wasm::SaveRestoreContext saved_context(context); @@ -184,8 +183,7 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa *f = nullptr; return; } - auto target_func = - reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2) { proxy_wasm::SaveRestoreContext saved_context(context); @@ -204,8 +202,7 @@ void DynVmPlugin::getFunction(std::string_view function_name, proxy_wasm::WasmCa *f = nullptr; return; } - auto target_func = - reinterpret_cast(target); + auto target_func = reinterpret_cast(target); *f = [this, target_func, function_name](proxy_wasm::ContextBase *context, proxy_wasm::Word w1, proxy_wasm::Word w2, proxy_wasm::Word w3) { proxy_wasm::SaveRestoreContext saved_context(context); diff --git a/src/exports.cc b/src/exports.cc index 7d9ec65ad..43f2a26a5 100644 --- a/src/exports.cc +++ b/src/exports.cc @@ -48,6 +48,7 @@ ContextBase *contextOrEffectiveContextRoot() { return nullptr; }; +// Gets any currently executing Wasm call context, including a thread-sharable limited context. ContextBase *getLimitedContext() { if (limited_context_ != nullptr) { return limited_context_; From be8f9dc37a957fad1638de566d3e66c521510c68 Mon Sep 17 00:00:00 2001 From: Protryon Date: Tue, 10 Sep 2024 14:24:06 -0700 Subject: [PATCH 5/5] update test file Signed-off-by: Protryon --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c9cbfa66..46a34cb03 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -115,7 +115,7 @@ jobs: flags: --config=gcc - name: 'DynVM on Linux/x86_64' engine: 'dyn' - os: ubuntu-20.04 + os: ubuntu-22.04 arch: x86_64 action: test flags: --config=gcc