From 7021484a30674c70a275e314da3008908864379e Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 6 Dec 2021 14:34:09 -0500 Subject: [PATCH 01/33] add code coverage host functions --- libraries/chain/CMakeLists.txt | 1 + libraries/chain/genesis_intrinsics.cpp | 5 +- .../eos-vm-oc/intrinsic_mapping.hpp | 5 +- .../eosio/chain/webassembly/interface.hpp | 5 ++ libraries/chain/webassembly/coverage.cpp | 61 +++++++++++++++++++ .../chain/webassembly/runtimes/eos-vm.cpp | 5 ++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 libraries/chain/webassembly/coverage.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 825253a2526..c457f63a921 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -62,6 +62,7 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/compiler_builtins.cpp webassembly/context_free.cpp webassembly/console.cpp + webassembly/coverage.cpp webassembly/crypto.cpp webassembly/database.cpp webassembly/kv_database.cpp diff --git a/libraries/chain/genesis_intrinsics.cpp b/libraries/chain/genesis_intrinsics.cpp index 8a0c13ec165..641dc4e4730 100644 --- a/libraries/chain/genesis_intrinsics.cpp +++ b/libraries/chain/genesis_intrinsics.cpp @@ -170,7 +170,10 @@ const std::vector genesis_intrinsics = { "memcpy", "memmove", "memcmp", - "memset" + "memset", + "coverage_inc_fun_cnt", + "coverage_inc_line_cnt", + "coverage_dump" }; } } // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index be288c20942..651d22a12e0 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -276,7 +276,10 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.push_data"_s, "env.print_time_us"_s, "env.get_input_data"_s, - "env.set_output_data"_s + "env.set_output_data"_s, + "env.coverage_inc_fun_cnt"_s, + "env.coverage_inc_line_cnt"_s, + "env.coverage_dump"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index c6dc44c2976..c0ec0417638 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1897,6 +1897,11 @@ namespace eosio { namespace chain { namespace webassembly { int32_t __lttf2(uint64_t, uint64_t, uint64_t, uint64_t) const; int32_t __unordtf2(uint64_t, uint64_t, uint64_t, uint64_t) const; + // code coverage support functions + void coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); + void coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); + void coverage_dump(); + private: apply_context& context; }; diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp new file mode 100644 index 00000000000..6d251b78df2 --- /dev/null +++ b/libraries/chain/webassembly/coverage.cpp @@ -0,0 +1,61 @@ +#include + +#include +#include + +namespace eosio { namespace chain { namespace webassembly { + static std::unordered_map > > funcnt_map; + static std::unordered_map > > linecnt_map; + + void interface::coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num) { + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + funcnt[func_num]++; + } + + void interface::coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num) { + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + linecnt[line_num]++; + } + + void interface::coverage_dump() { + auto fName = std::string("call-counts.json"); + std::ofstream out_json_file; + out_json_file.open(fName); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for (auto code_map : funcnt_map) { + auto code_str = code_map.first.to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + for (auto funcnt : code_map.second) { + auto file_num = funcnt.first; + for (auto func : funcnt.second) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for (auto code_map : linecnt_map) { + auto code_str = code_map.first.to_string(); + out_json_file << "{ \"" << code_str <<"\""; + + for (auto linecnt : code_map.second) { + for (auto line : linecnt.second) { + + } + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file.close(); + } +}}} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 16b10c437cf..748c8d4a3dc 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -574,6 +574,11 @@ REGISTER_CF_HOST_FUNCTION(__letf2); REGISTER_CF_HOST_FUNCTION(__lttf2); REGISTER_CF_HOST_FUNCTION(__unordtf2); +// code coverage API +REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) +REGISTER_HOST_FUNCTION(coverage_dump) + } // namespace webassembly } // namespace chain } // namespace eosio From 9cbe513a08e2507d3743b29e965ae6731beb2f02 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 6 Dec 2021 21:56:14 -0500 Subject: [PATCH 02/33] code coverage now protocol feature instead of genesis --- libraries/chain/controller.cpp | 11 +++++++++++ libraries/chain/genesis_intrinsics.cpp | 5 +---- .../include/eosio/chain/protocol_feature_manager.hpp | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index be9526f3f2d..8086119a9a2 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -277,6 +277,7 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); set_activation_handler(); + set_activation_handler(); self.irreversible_block.connect([this](const block_state_ptr& bsp) { wasmif.current_lib(bsp->block_num); @@ -3456,6 +3457,16 @@ void controller_impl::on_activation +void controller_impl::on_activation() { + db.modify( db.get(), [&]( auto& ps ) { + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + } ); +} + + /// End of protocol feature activation handlers } } /// eosio::chain diff --git a/libraries/chain/genesis_intrinsics.cpp b/libraries/chain/genesis_intrinsics.cpp index 641dc4e4730..8a0c13ec165 100644 --- a/libraries/chain/genesis_intrinsics.cpp +++ b/libraries/chain/genesis_intrinsics.cpp @@ -170,10 +170,7 @@ const std::vector genesis_intrinsics = { "memcpy", "memmove", "memcmp", - "memset", - "coverage_inc_fun_cnt", - "coverage_inc_line_cnt", - "coverage_dump" + "memset" }; } } // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp index 22b0df48905..4934ad3153e 100644 --- a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp +++ b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp @@ -26,7 +26,8 @@ enum class builtin_protocol_feature_t : uint32_t { action_return_value, kv_database, configurable_wasm_limits, - blockchain_parameters + blockchain_parameters, + wasm_code_coverage }; struct protocol_feature_subjective_restrictions { From 1c67d03ad46b8029c2846a77dfad95a92274f0fe Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Tue, 7 Dec 2021 13:48:58 -0500 Subject: [PATCH 03/33] add coverage_get_XXX() and coverage_reset() host functions --- libraries/chain/controller.cpp | 3 ++ .../eos-vm-oc/intrinsic_mapping.hpp | 5 ++- .../eosio/chain/webassembly/interface.hpp | 3 ++ libraries/chain/webassembly/coverage.cpp | 33 +++++++++++++++++++ .../chain/webassembly/runtimes/eos-vm.cpp | 3 ++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 8086119a9a2..3d1f306571f 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -3462,7 +3462,10 @@ void controller_impl::on_activation(), [&]( auto& ps ) { add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); } ); } diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 651d22a12e0..848314eafb1 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -279,7 +279,10 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.set_output_data"_s, "env.coverage_inc_fun_cnt"_s, "env.coverage_inc_line_cnt"_s, - "env.coverage_dump"_s + "env.coverage_get_fun_cnt"_s, + "env.coverage_inc_line_cnt"_s, + "env.coverage_dump"_s, + "env.coverage_reset"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index c0ec0417638..1e5b7bb2007 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1900,7 +1900,10 @@ namespace eosio { namespace chain { namespace webassembly { // code coverage support functions void coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); void coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); + uint32_t coverage_get_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); + uint32_t coverage_get_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); void coverage_dump(); + void coverage_reset(); private: apply_context& context; diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp index 6d251b78df2..30d427969c8 100644 --- a/libraries/chain/webassembly/coverage.cpp +++ b/libraries/chain/webassembly/coverage.cpp @@ -19,6 +19,34 @@ namespace eosio { namespace chain { namespace webassembly { linecnt[line_num]++; } + uint32_t interface::coverage_get_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num) { + uint32_t ret_val = 0; + if (funcnt_map.count(code) > 0) { + auto &code_map = funcnt_map[code]; + if (code_map.count(file_num) > 0) { + auto &funcnt = code_map[file_num]; + if (funcnt.count(func_num) > 0) { + ret_val = funcnt[func_num]; + } + } + } + return ret_val; + } + + uint32_t interface::coverage_get_line_cnt(account_name code, uint32_t file_num, uint32_t line_num) { + uint32_t ret_val = 0; + if (linecnt_map.count(code) > 0) { + auto &code_map = linecnt_map[code]; + if (code_map.count(file_num) > 0) { + auto &linecnt = code_map[file_num]; + if (linecnt.count(line_num) > 0) { + ret_val = linecnt[line_num]; + } + } + } + return ret_val; + } + void interface::coverage_dump() { auto fName = std::string("call-counts.json"); std::ofstream out_json_file; @@ -58,4 +86,9 @@ namespace eosio { namespace chain { namespace webassembly { out_json_file << "\t}\n"; out_json_file.close(); } + + void interface::coverage_reset() { + funcnt_map.clear(); + linecnt_map.clear(); + } }}} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 748c8d4a3dc..080352dc60d 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -577,7 +577,10 @@ REGISTER_CF_HOST_FUNCTION(__unordtf2); // code coverage API REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) +REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_get_line_cnt) REGISTER_HOST_FUNCTION(coverage_dump) +REGISTER_HOST_FUNCTION(coverage_reset) } // namespace webassembly } // namespace chain From f7d3423bd478e4469fcddd5d914cbfb965436c88 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Tue, 7 Dec 2021 14:49:05 -0500 Subject: [PATCH 04/33] correct intrinsic name --- .../eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 848314eafb1..a3823c92e08 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -280,7 +280,7 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.coverage_inc_fun_cnt"_s, "env.coverage_inc_line_cnt"_s, "env.coverage_get_fun_cnt"_s, - "env.coverage_inc_line_cnt"_s, + "env.coverage_get_line_cnt"_s, "env.coverage_dump"_s, "env.coverage_reset"_s ); From 2de30682d84e57a7105b513e8fbe4ad27250c62e Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 11:11:02 -0500 Subject: [PATCH 05/33] Revert "correct intrinsic name" This reverts commit f7d3423bd478e4469fcddd5d914cbfb965436c88. --- .../eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index a3823c92e08..848314eafb1 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -280,7 +280,7 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.coverage_inc_fun_cnt"_s, "env.coverage_inc_line_cnt"_s, "env.coverage_get_fun_cnt"_s, - "env.coverage_get_line_cnt"_s, + "env.coverage_inc_line_cnt"_s, "env.coverage_dump"_s, "env.coverage_reset"_s ); From 4b5a68decc80090b8d56fa0ad74153afe22a7eff Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 11:11:08 -0500 Subject: [PATCH 06/33] Revert "add coverage_get_XXX() and coverage_reset() host functions" This reverts commit 1c67d03ad46b8029c2846a77dfad95a92274f0fe. --- libraries/chain/controller.cpp | 3 -- .../eos-vm-oc/intrinsic_mapping.hpp | 5 +-- .../eosio/chain/webassembly/interface.hpp | 3 -- libraries/chain/webassembly/coverage.cpp | 33 ------------------- .../chain/webassembly/runtimes/eos-vm.cpp | 3 -- 5 files changed, 1 insertion(+), 46 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 3d1f306571f..8086119a9a2 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -3462,10 +3462,7 @@ void controller_impl::on_activation(), [&]( auto& ps ) { add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); } ); } diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 848314eafb1..651d22a12e0 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -279,10 +279,7 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.set_output_data"_s, "env.coverage_inc_fun_cnt"_s, "env.coverage_inc_line_cnt"_s, - "env.coverage_get_fun_cnt"_s, - "env.coverage_inc_line_cnt"_s, - "env.coverage_dump"_s, - "env.coverage_reset"_s + "env.coverage_dump"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index 1e5b7bb2007..c0ec0417638 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1900,10 +1900,7 @@ namespace eosio { namespace chain { namespace webassembly { // code coverage support functions void coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); void coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); - uint32_t coverage_get_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); - uint32_t coverage_get_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); void coverage_dump(); - void coverage_reset(); private: apply_context& context; diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp index 30d427969c8..6d251b78df2 100644 --- a/libraries/chain/webassembly/coverage.cpp +++ b/libraries/chain/webassembly/coverage.cpp @@ -19,34 +19,6 @@ namespace eosio { namespace chain { namespace webassembly { linecnt[line_num]++; } - uint32_t interface::coverage_get_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num) { - uint32_t ret_val = 0; - if (funcnt_map.count(code) > 0) { - auto &code_map = funcnt_map[code]; - if (code_map.count(file_num) > 0) { - auto &funcnt = code_map[file_num]; - if (funcnt.count(func_num) > 0) { - ret_val = funcnt[func_num]; - } - } - } - return ret_val; - } - - uint32_t interface::coverage_get_line_cnt(account_name code, uint32_t file_num, uint32_t line_num) { - uint32_t ret_val = 0; - if (linecnt_map.count(code) > 0) { - auto &code_map = linecnt_map[code]; - if (code_map.count(file_num) > 0) { - auto &linecnt = code_map[file_num]; - if (linecnt.count(line_num) > 0) { - ret_val = linecnt[line_num]; - } - } - } - return ret_val; - } - void interface::coverage_dump() { auto fName = std::string("call-counts.json"); std::ofstream out_json_file; @@ -86,9 +58,4 @@ namespace eosio { namespace chain { namespace webassembly { out_json_file << "\t}\n"; out_json_file.close(); } - - void interface::coverage_reset() { - funcnt_map.clear(); - linecnt_map.clear(); - } }}} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 080352dc60d..748c8d4a3dc 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -577,10 +577,7 @@ REGISTER_CF_HOST_FUNCTION(__unordtf2); // code coverage API REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) -REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_get_line_cnt) REGISTER_HOST_FUNCTION(coverage_dump) -REGISTER_HOST_FUNCTION(coverage_reset) } // namespace webassembly } // namespace chain From 57ca0e96d320603e7b22db390ef639269bc15726 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 11:11:11 -0500 Subject: [PATCH 07/33] Revert "code coverage now protocol feature instead of genesis" This reverts commit 9cbe513a08e2507d3743b29e965ae6731beb2f02. --- libraries/chain/controller.cpp | 11 ----------- libraries/chain/genesis_intrinsics.cpp | 5 ++++- .../include/eosio/chain/protocol_feature_manager.hpp | 3 +-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 8086119a9a2..be9526f3f2d 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -277,7 +277,6 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); set_activation_handler(); - set_activation_handler(); self.irreversible_block.connect([this](const block_state_ptr& bsp) { wasmif.current_lib(bsp->block_num); @@ -3457,16 +3456,6 @@ void controller_impl::on_activation -void controller_impl::on_activation() { - db.modify( db.get(), [&]( auto& ps ) { - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); - } ); -} - - /// End of protocol feature activation handlers } } /// eosio::chain diff --git a/libraries/chain/genesis_intrinsics.cpp b/libraries/chain/genesis_intrinsics.cpp index 8a0c13ec165..641dc4e4730 100644 --- a/libraries/chain/genesis_intrinsics.cpp +++ b/libraries/chain/genesis_intrinsics.cpp @@ -170,7 +170,10 @@ const std::vector genesis_intrinsics = { "memcpy", "memmove", "memcmp", - "memset" + "memset", + "coverage_inc_fun_cnt", + "coverage_inc_line_cnt", + "coverage_dump" }; } } // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp index 4934ad3153e..22b0df48905 100644 --- a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp +++ b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp @@ -26,8 +26,7 @@ enum class builtin_protocol_feature_t : uint32_t { action_return_value, kv_database, configurable_wasm_limits, - blockchain_parameters, - wasm_code_coverage + blockchain_parameters }; struct protocol_feature_subjective_restrictions { From 73acc24be6703471393c9e255a9d526608343cd2 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 11:11:14 -0500 Subject: [PATCH 08/33] Revert "add code coverage host functions" This reverts commit 7021484a30674c70a275e314da3008908864379e. --- libraries/chain/CMakeLists.txt | 1 - libraries/chain/genesis_intrinsics.cpp | 5 +- .../eos-vm-oc/intrinsic_mapping.hpp | 5 +- .../eosio/chain/webassembly/interface.hpp | 5 -- libraries/chain/webassembly/coverage.cpp | 61 ------------------- .../chain/webassembly/runtimes/eos-vm.cpp | 5 -- 6 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 libraries/chain/webassembly/coverage.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c457f63a921..825253a2526 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -62,7 +62,6 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/compiler_builtins.cpp webassembly/context_free.cpp webassembly/console.cpp - webassembly/coverage.cpp webassembly/crypto.cpp webassembly/database.cpp webassembly/kv_database.cpp diff --git a/libraries/chain/genesis_intrinsics.cpp b/libraries/chain/genesis_intrinsics.cpp index 641dc4e4730..8a0c13ec165 100644 --- a/libraries/chain/genesis_intrinsics.cpp +++ b/libraries/chain/genesis_intrinsics.cpp @@ -170,10 +170,7 @@ const std::vector genesis_intrinsics = { "memcpy", "memmove", "memcmp", - "memset", - "coverage_inc_fun_cnt", - "coverage_inc_line_cnt", - "coverage_dump" + "memset" }; } } // namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 651d22a12e0..be288c20942 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -276,10 +276,7 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.push_data"_s, "env.print_time_us"_s, "env.get_input_data"_s, - "env.set_output_data"_s, - "env.coverage_inc_fun_cnt"_s, - "env.coverage_inc_line_cnt"_s, - "env.coverage_dump"_s + "env.set_output_data"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index c0ec0417638..c6dc44c2976 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1897,11 +1897,6 @@ namespace eosio { namespace chain { namespace webassembly { int32_t __lttf2(uint64_t, uint64_t, uint64_t, uint64_t) const; int32_t __unordtf2(uint64_t, uint64_t, uint64_t, uint64_t) const; - // code coverage support functions - void coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num); - void coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num); - void coverage_dump(); - private: apply_context& context; }; diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp deleted file mode 100644 index 6d251b78df2..00000000000 --- a/libraries/chain/webassembly/coverage.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include - -#include -#include - -namespace eosio { namespace chain { namespace webassembly { - static std::unordered_map > > funcnt_map; - static std::unordered_map > > linecnt_map; - - void interface::coverage_inc_fun_cnt(account_name code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - funcnt[func_num]++; - } - - void interface::coverage_inc_line_cnt(account_name code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - linecnt[line_num]++; - } - - void interface::coverage_dump() { - auto fName = std::string("call-counts.json"); - std::ofstream out_json_file; - out_json_file.open(fName); - - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for (auto code_map : funcnt_map) { - auto code_str = code_map.first.to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - for (auto funcnt : code_map.second) { - auto file_num = funcnt.first; - for (auto func : funcnt.second) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; - } - } - out_json_file << "\t\t]\n"; - } - out_json_file << "\t}\n"; - - out_json_file << "\t\"lines\": {"; - for (auto code_map : linecnt_map) { - auto code_str = code_map.first.to_string(); - out_json_file << "{ \"" << code_str <<"\""; - - for (auto linecnt : code_map.second) { - for (auto line : linecnt.second) { - - } - } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file.close(); - } -}}} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 748c8d4a3dc..16b10c437cf 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -574,11 +574,6 @@ REGISTER_CF_HOST_FUNCTION(__letf2); REGISTER_CF_HOST_FUNCTION(__lttf2); REGISTER_CF_HOST_FUNCTION(__unordtf2); -// code coverage API -REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) -REGISTER_HOST_FUNCTION(coverage_dump) - } // namespace webassembly } // namespace chain } // namespace eosio From 74afa6f8cc742bbf5135f7c27de0856d05607f34 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 12:59:06 -0500 Subject: [PATCH 09/33] add coverage intrinsics to eosio-tester --- programs/eosio-tester/main.cpp | 87 ++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index a3a241f4a7d..1d490da6580 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -182,6 +182,9 @@ struct test_chain { std::unique_ptr intr_ctx; std::set refs; + std::unordered_map > > funcnt_map; + std::unordered_map > > linecnt_map; + test_chain(const char* snapshot) { eosio::chain::genesis_state genesis; genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); @@ -1123,6 +1126,83 @@ struct callbacks { } } + void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + auto &code_map = sel_chain.funcnt_map[code]; + auto &funcnt = code_map[file_num]; + funcnt[func_num]++; + } + + void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + auto &code_map = sel_chain.linecnt_map[code]; + auto &linecnt = code_map[file_num]; + linecnt[line_num]++; + } + + uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + auto &code_map = sel_chain.funcnt_map[code]; + auto &funcnt = code_map[file_num]; + return funcnt[func_num]; + } + + uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + auto &code_map = sel_chain.linecnt_map[code]; + auto &linecnt = code_map[file_num]; + return linecnt[line_num]; + } + + void coverage_dump() { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + auto fName = std::string("call-counts.json"); + std::ofstream out_json_file; + out_json_file.open(fName); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for (auto code_map : sel_chain.funcnt_map) { + auto code_str = eosio::chain::name{code_map.first}.to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + for (auto funcnt : code_map.second) { + auto file_num = funcnt.first; + for (auto func : funcnt.second) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for (auto code_map : sel_chain.linecnt_map) { + auto code_str = eosio::chain::name{code_map.first}.to_string(); + out_json_file << "{ \"" << code_str <<"\""; + + for (auto linecnt : code_map.second) { + auto file_num = linecnt.first; + for (auto line : linecnt.second) { + auto line_num = line.first; + auto cnt = line.second; + out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; + } + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file.close(); + } + + void coverage_reset() { + auto &sel_chain = *state.chains[*state.selected_chain_index]; + sel_chain.funcnt_map.clear(); + sel_chain.linecnt_map.clear(); + } }; // callbacks @@ -1211,6 +1291,13 @@ void register_callbacks() { rhf_t::add<&callbacks::sha512>("env", "sha512"); rhf_t::add<&callbacks::ripemd160>("env", "ripemd160"); rhf_t::add<&callbacks::recover_key>("env", "recover_key"); + + rhf_t::add<&callbacks::recover_key>("env", "coverage_inc_fun_cnt"); + rhf_t::add<&callbacks::recover_key>("env", "coverage_inc_line_cnt"); + rhf_t::add<&callbacks::recover_key>("env", "coverage_get_fun_cnt"); + rhf_t::add<&callbacks::recover_key>("env", "coverage_get_line_cnt"); + rhf_t::add<&callbacks::recover_key>("env", "coverage_dump"); + rhf_t::add<&callbacks::recover_key>("env", "coverage_reset"); } static int run(const char* wasm, const std::vector& args) { From 9a05ec30319db58ca5be578272d1cfccd703eb5a Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 8 Dec 2021 15:49:20 -0500 Subject: [PATCH 10/33] fix validation-reflect test failures, add param to covergae dump --- programs/eosio-tester/main.cpp | 128 ++++++++++++++++----------------- 1 file changed, 62 insertions(+), 66 deletions(-) diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 1d490da6580..c7239f7c1f7 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -182,9 +182,6 @@ struct test_chain { std::unique_ptr intr_ctx; std::set refs; - std::unordered_map > > funcnt_map; - std::unordered_map > > linecnt_map; - test_chain(const char* snapshot) { eosio::chain::genesis_state genesis; genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); @@ -503,6 +500,7 @@ FC_REFLECT(push_trx_args, (transaction)(context_free_data)(signatures)(keys)) return selected().IDX.previous_secondary(iterator, primary); \ } + struct callbacks { ::state& state; @@ -1126,82 +1124,80 @@ struct callbacks { } } + std::unordered_map > > funcnt_map; + std::unordered_map > > linecnt_map; + void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - auto &code_map = sel_chain.funcnt_map[code]; + auto &code_map = funcnt_map[code]; auto &funcnt = code_map[file_num]; funcnt[func_num]++; } void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - auto &code_map = sel_chain.linecnt_map[code]; + auto &code_map = linecnt_map[code]; auto &linecnt = code_map[file_num]; linecnt[line_num]++; } uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - auto &code_map = sel_chain.funcnt_map[code]; - auto &funcnt = code_map[file_num]; - return funcnt[func_num]; + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + return funcnt[func_num]; } uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - auto &code_map = sel_chain.linecnt_map[code]; - auto &linecnt = code_map[file_num]; - return linecnt[line_num]; - } - - void coverage_dump() { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - auto fName = std::string("call-counts.json"); - std::ofstream out_json_file; - out_json_file.open(fName); - - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for (auto code_map : sel_chain.funcnt_map) { - auto code_str = eosio::chain::name{code_map.first}.to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - for (auto funcnt : code_map.second) { - auto file_num = funcnt.first; - for (auto func : funcnt.second) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; - } + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + return linecnt[line_num]; + } + + void coverage_dump(uint32_t n) { + auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); + std::ofstream out_json_file; + out_json_file.open(fName); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for (auto code_map : funcnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + for (auto funcnt : code_map.second) { + auto file_num = funcnt.first; + for (auto func : funcnt.second) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; } - out_json_file << "\t\t]\n"; - } - out_json_file << "\t}\n"; - - out_json_file << "\t\"lines\": {"; - for (auto code_map : sel_chain.linecnt_map) { - auto code_str = eosio::chain::name{code_map.first}.to_string(); - out_json_file << "{ \"" << code_str <<"\""; - - for (auto linecnt : code_map.second) { - auto file_num = linecnt.first; - for (auto line : linecnt.second) { - auto line_num = line.first; - auto cnt = line.second; - out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; - } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for (auto code_map : linecnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + + for (auto linecnt : code_map.second) { + auto file_num = linecnt.first; + for (auto line : linecnt.second) { + auto line_num = line.first; + auto cnt = line.second; + out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file.close(); + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file << "}\n"; + out_json_file.close(); } void coverage_reset() { - auto &sel_chain = *state.chains[*state.selected_chain_index]; - sel_chain.funcnt_map.clear(); - sel_chain.linecnt_map.clear(); + funcnt_map.clear(); + linecnt_map.clear(); } }; // callbacks @@ -1292,12 +1288,12 @@ void register_callbacks() { rhf_t::add<&callbacks::ripemd160>("env", "ripemd160"); rhf_t::add<&callbacks::recover_key>("env", "recover_key"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_inc_fun_cnt"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_inc_line_cnt"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_get_fun_cnt"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_get_line_cnt"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_dump"); - rhf_t::add<&callbacks::recover_key>("env", "coverage_reset"); + rhf_t::add<&callbacks::coverage_inc_fun_cnt>("env", "coverage_inc_fun_cnt"); + rhf_t::add<&callbacks::coverage_inc_line_cnt>("env", "coverage_inc_line_cnt"); + rhf_t::add<&callbacks::coverage_get_fun_cnt>("env", "coverage_get_fun_cnt"); + rhf_t::add<&callbacks::coverage_get_line_cnt>("env", "coverage_get_line_cnt"); + rhf_t::add<&callbacks::coverage_dump>("env", "coverage_dump"); + rhf_t::add<&callbacks::coverage_reset>("env", "coverage_reset"); } static int run(const char* wasm, const std::vector& args) { From 4a31d3b469f8e090404398823405723762e34a49 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Thu, 9 Dec 2021 07:34:53 -0500 Subject: [PATCH 11/33] rodeos coverage callbacks --- .../include/b1/rodeos/callbacks/coverage.hpp | 114 ++++++++++++++++++ libraries/rodeos/include/b1/rodeos/filter.hpp | 12 +- libraries/rodeos/rodeos.cpp | 3 +- libraries/rodeos/wasm_ql.cpp | 15 ++- 4 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp new file mode 100644 index 00000000000..10b8aad912a --- /dev/null +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include +#include + +namespace b1::rodeos { + +struct coverage_state { + std::unordered_map > > funcnt_map; + std::unordered_map > > linecnt_map; + // std::map > > funcnt_map; + // std::map > > linecnt_map; +}; + +template +struct coverage_callbacks { + Derived& derived() { return static_cast(*this); } + + void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &funcnt_map = derived().get_coverage_state().funcnt_map; + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + funcnt[func_num]++; + } + + void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &linecnt_map = derived().get_coverage_state().linecnt_map; + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + linecnt[line_num]++; + } + + uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &funcnt_map = derived().get_coverage_state().funcnt_map; + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + return funcnt[func_num]; + } + + uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &linecnt_map = derived().get_coverage_state().linecnt_map; + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + return linecnt[line_num]; + } + + void coverage_dump(uint32_t n) { + auto &funcnt_map = derived().get_coverage_state().funcnt_map; + auto &linecnt_map = derived().get_coverage_state().linecnt_map; + + auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); + std::ofstream out_json_file; + out_json_file.open(fName); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for (auto code_map : funcnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + for (auto funcnt : code_map.second) { + auto file_num = funcnt.first; + for (auto func : funcnt.second) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for (auto code_map : linecnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + + for (auto linecnt : code_map.second) { + auto file_num = linecnt.first; + for (auto line : linecnt.second) { + auto line_num = line.first; + auto cnt = line.second; + out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; + } + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file << "}\n"; + out_json_file.close(); + } + + void coverage_reset() { + auto &funcnt_map = derived().get_coverage_state().funcnt_map; + auto &linecnt_map = derived().get_coverage_state().linecnt_map; + + funcnt_map.clear(); + linecnt_map.clear(); + } + + template + static void register_callbacks() { + // todo: preconditions + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_inc_fun_cnt); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_inc_line_cnt); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_fun_cnt); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_line_cnt); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_dump); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_reset); + } +}; // coverage_callbacks + +} // namespace b1::rodeos \ No newline at end of file diff --git a/libraries/rodeos/include/b1/rodeos/filter.hpp b/libraries/rodeos/include/b1/rodeos/filter.hpp index b139ac7ee2f..2374704257f 100644 --- a/libraries/rodeos/include/b1/rodeos/filter.hpp +++ b/libraries/rodeos/include/b1/rodeos/filter.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED # include # include @@ -65,19 +66,23 @@ struct callbacks : b1::rodeos::chaindb_callbacks, b1::rodeos::filter_callbacks, b1::rodeos::memory_callbacks, b1::rodeos::unimplemented_callbacks, - b1::rodeos::system_callbacks { + b1::rodeos::system_callbacks, + b1::rodeos::coverage_callbacks { filter::filter_state& filter_state; b1::rodeos::chaindb_state& chaindb_state; b1::rodeos::db_view_state& db_view_state; + b1::rodeos::coverage_state& coverage_state; callbacks(filter::filter_state& filter_state, b1::rodeos::chaindb_state& chaindb_state, - b1::rodeos::db_view_state& db_view_state) - : filter_state{ filter_state }, chaindb_state{ chaindb_state }, db_view_state{ db_view_state } {} + b1::rodeos::db_view_state& db_view_state, b1::rodeos::coverage_state& coverage_state) + : filter_state{ filter_state }, chaindb_state{ chaindb_state }, db_view_state{ db_view_state } + , coverage_state{ coverage_state } {} auto& get_state() { return filter_state; } auto& get_filter_callback_state() { return filter_state; } auto& get_chaindb_state() { return chaindb_state; } auto& get_db_view_state() { return db_view_state; } + auto& get_coverage_state() { return coverage_state; } }; inline void register_callbacks() { @@ -92,6 +97,7 @@ inline void register_callbacks() { b1::rodeos::memory_callbacks::register_callbacks(); b1::rodeos::system_callbacks::register_callbacks(); b1::rodeos::unimplemented_callbacks::register_callbacks(); + b1::rodeos::coverage_callbacks::register_callbacks(); } } // namespace b1::rodeos::filter diff --git a/libraries/rodeos/rodeos.cpp b/libraries/rodeos/rodeos.cpp index 1d91f56c0fa..6b51436e978 100644 --- a/libraries/rodeos/rodeos.cpp +++ b/libraries/rodeos/rodeos.cpp @@ -347,8 +347,9 @@ void rodeos_filter::process(rodeos_db_snapshot& snapshot, const ship_protocol::g snapshot.check_write(result); chaindb_state chaindb_state; db_view_state view_state{ name, *snapshot.db, *snapshot.write_session, snapshot.partition->contract_kv_prefix }; + coverage_state coverage_state; view_state.kv_state.enable_write = true; - filter::callbacks cb{ *filter_state, chaindb_state, view_state }; + filter::callbacks cb{ *filter_state, chaindb_state, view_state, coverage_state }; filter_state->max_console_size = 10000; filter_state->console.clear(); filter_state->input_data = bin; diff --git a/libraries/rodeos/wasm_ql.cpp b/libraries/rodeos/wasm_ql.cpp index d3ba0853f1c..bab436c6d20 100644 --- a/libraries/rodeos/wasm_ql.cpp +++ b/libraries/rodeos/wasm_ql.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -72,18 +73,22 @@ struct callbacks : action_callbacks, db_callbacks, memory_callbacks, query_callbacks, - unimplemented_callbacks { + unimplemented_callbacks, + coverage_callbacks { wasm_ql::thread_state& thread_state; rodeos::chaindb_state& chaindb_state; rodeos::db_view_state& db_view_state; + rodeos::coverage_state& coverage_state; callbacks(wasm_ql::thread_state& thread_state, rodeos::chaindb_state& chaindb_state, - rodeos::db_view_state& db_view_state) - : thread_state{ thread_state }, chaindb_state{ chaindb_state }, db_view_state{ db_view_state } {} + rodeos::db_view_state& db_view_state, rodeos::coverage_state& coverage_state) + : thread_state{ thread_state }, chaindb_state{ chaindb_state }, db_view_state{ db_view_state } + , coverage_state{ coverage_state } {} auto& get_state() { return thread_state; } auto& get_chaindb_state() { return chaindb_state; } auto& get_db_view_state() { return db_view_state; } + auto& get_coverage_state() { return coverage_state; } }; std::once_flag registered_callbacks; @@ -99,6 +104,7 @@ void register_callbacks() { memory_callbacks::register_callbacks(); query_callbacks::register_callbacks(); unimplemented_callbacks::register_callbacks(); + coverage_callbacks::register_callbacks(); } struct backend_entry { @@ -273,7 +279,8 @@ void run_action(wasm_ql::thread_state& thread_state, const std::vector& co thread_state.block_info.reset(); chaindb_state chaindb_state; - callbacks cb{ thread_state, chaindb_state, db_view_state }; + coverage_state coverage_state; + callbacks cb{ thread_state, chaindb_state, db_view_state, coverage_state }; entry->backend->set_wasm_allocator(&thread_state.wa); try { From 56e9f2f2f6b0d2780539679ecbe4ca0881a79a35 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Thu, 9 Dec 2021 11:28:58 -0500 Subject: [PATCH 12/33] add coverage intrinisic to eos-vm-oc --- .../chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index be288c20942..a3823c92e08 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -276,7 +276,13 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.push_data"_s, "env.print_time_us"_s, "env.get_input_data"_s, - "env.set_output_data"_s + "env.set_output_data"_s, + "env.coverage_inc_fun_cnt"_s, + "env.coverage_inc_line_cnt"_s, + "env.coverage_get_fun_cnt"_s, + "env.coverage_get_line_cnt"_s, + "env.coverage_dump"_s, + "env.coverage_reset"_s ); }}} \ No newline at end of file From ad65b381e7e7cec7add79f0bae6d75e03038ea4d Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Fri, 10 Dec 2021 15:32:48 -0500 Subject: [PATCH 13/33] whitelist tester intrinsics --- libraries/chain/include/eosio/chain/controller.hpp | 4 ++-- programs/eosio-tester/main.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index a411b8bf1e5..6228ec2be9b 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -404,9 +404,9 @@ namespace eosio { namespace chain { friend class apply_context; friend class transaction_context; - chainbase::database& mutable_db()const; - std::unique_ptr my; + public: + chainbase::database& mutable_db()const; }; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index c7239f7c1f7..cb955155aa0 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -220,6 +220,17 @@ struct test_chain { accepted_block_connection.emplace( control->accepted_block.connect([&](const block_state_ptr& p) { on_accepted_block(p); })); + auto &db = control->mutable_db(); + + db.modify( db.get(), [&]( auto& ps ) { + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); + } ); + if (snapshot_reader) { control->startup([] {}, [] { return false; }, snapshot_reader); } else { From 7e6b8094814ea3de81a78e7078a54fd34908b8b5 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Sat, 11 Dec 2021 17:31:00 -0500 Subject: [PATCH 14/33] back to host function (verified working, generate coverage report) --- libraries/chain/CMakeLists.txt | 1 + libraries/chain/controller.cpp | 14 ++++ .../eosio/chain/protocol_feature_manager.hpp | 3 +- .../eosio/chain/webassembly/interface.hpp | 8 ++ libraries/chain/webassembly/coverage.cpp | 82 +++++++++++++++++++ .../chain/webassembly/runtimes/eos-vm.cpp | 8 ++ programs/eosio-tester/main.cpp | 23 +++--- 7 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 libraries/chain/webassembly/coverage.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 825253a2526..c457f63a921 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -62,6 +62,7 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/compiler_builtins.cpp webassembly/context_free.cpp webassembly/console.cpp + webassembly/coverage.cpp webassembly/crypto.cpp webassembly/database.cpp webassembly/kv_database.cpp diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index be9526f3f2d..3d1f306571f 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -277,6 +277,7 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); set_activation_handler(); + set_activation_handler(); self.irreversible_block.connect([this](const block_state_ptr& bsp) { wasmif.current_lib(bsp->block_num); @@ -3456,6 +3457,19 @@ void controller_impl::on_activation +void controller_impl::on_activation() { + db.modify( db.get(), [&]( auto& ps ) { + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); + } ); +} + + /// End of protocol feature activation handlers } } /// eosio::chain diff --git a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp index 22b0df48905..4934ad3153e 100644 --- a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp +++ b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp @@ -26,7 +26,8 @@ enum class builtin_protocol_feature_t : uint32_t { action_return_value, kv_database, configurable_wasm_limits, - blockchain_parameters + blockchain_parameters, + wasm_code_coverage }; struct protocol_feature_subjective_restrictions { diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index c6dc44c2976..1411bba5bef 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1897,6 +1897,14 @@ namespace eosio { namespace chain { namespace webassembly { int32_t __lttf2(uint64_t, uint64_t, uint64_t, uint64_t) const; int32_t __unordtf2(uint64_t, uint64_t, uint64_t, uint64_t) const; + // code coverage support functions + void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num); + void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); + uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num); + uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); + void coverage_dump(uint32_t); + void coverage_reset(); + private: apply_context& context; }; diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp new file mode 100644 index 00000000000..a0d7586c40d --- /dev/null +++ b/libraries/chain/webassembly/coverage.cpp @@ -0,0 +1,82 @@ +#include + +#include +#include + +namespace eosio { namespace chain { namespace webassembly { + std::unordered_map > > funcnt_map; + std::unordered_map > > linecnt_map; + + void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + funcnt[func_num]++; + } + + void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + linecnt[line_num]++; + } + + uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + auto &code_map = funcnt_map[code]; + auto &funcnt = code_map[file_num]; + return funcnt[func_num]; + } + + uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + auto &code_map = linecnt_map[code]; + auto &linecnt = code_map[file_num]; + return linecnt[line_num]; + } + + void interface::coverage_dump(uint32_t n) { + auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); + std::ofstream out_json_file; + out_json_file.open(fName); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for (auto code_map : funcnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + for (auto funcnt : code_map.second) { + auto file_num = funcnt.first; + for (auto func : funcnt.second) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for (auto code_map : linecnt_map) { + auto code_str = eosio::chain::name(code_map.first).to_string(); + out_json_file << "\t\t\"" << code_str <<"\": [\n"; + + for (auto linecnt : code_map.second) { + auto file_num = linecnt.first; + for (auto line : linecnt.second) { + auto line_num = line.first; + auto cnt = line.second; + out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; + } + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file << "}\n"; + out_json_file.close(); + } + + void interface::coverage_reset() { + funcnt_map.clear(); + linecnt_map.clear(); + } +}}} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 16b10c437cf..080352dc60d 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -574,6 +574,14 @@ REGISTER_CF_HOST_FUNCTION(__letf2); REGISTER_CF_HOST_FUNCTION(__lttf2); REGISTER_CF_HOST_FUNCTION(__unordtf2); +// code coverage API +REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) +REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_get_line_cnt) +REGISTER_HOST_FUNCTION(coverage_dump) +REGISTER_HOST_FUNCTION(coverage_reset) + } // namespace webassembly } // namespace chain } // namespace eosio diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index cb955155aa0..117a4cae0db 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -220,17 +220,6 @@ struct test_chain { accepted_block_connection.emplace( control->accepted_block.connect([&](const block_state_ptr& p) { on_accepted_block(p); })); - auto &db = control->mutable_db(); - - db.modify( db.get(), [&]( auto& ps ) { - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); - } ); - if (snapshot_reader) { control->startup([] {}, [] { return false; }, snapshot_reader); } else { @@ -238,7 +227,17 @@ struct test_chain { control, [] {}, [] { return false; }, genesis); control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, { *control->get_protocol_feature_manager().get_builtin_digest( - eosio::chain::builtin_protocol_feature_t::preactivate_feature) }); + eosio::chain::builtin_protocol_feature_t::preactivate_feature) + }); + auto& pfm = control->get_protocol_feature_manager(); + auto feat = eosio::chain::builtin_protocol_feature_t::wasm_code_coverage; + auto wasm_code_coverage_digest = *pfm.get_builtin_digest(feat); + uint32_t action_id = 0; + control->preactivate_feature(action_id, wasm_code_coverage_digest); + finish_block(); + + control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, + { wasm_code_coverage_digest }); } } From 24ba301f486254b1af2e7b0a2f51f4cca7f341ee Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Tue, 14 Dec 2021 17:06:07 -0500 Subject: [PATCH 15/33] missed changes from prior checkin --- libraries/chain/protocol_feature_manager.cpp | 11 +++ programs/eosio-tester/main.cpp | 83 -------------------- 2 files changed, 11 insertions(+), 83 deletions(-) diff --git a/libraries/chain/protocol_feature_manager.cpp b/libraries/chain/protocol_feature_manager.cpp index 82da9deb542..dfdd48922ed 100644 --- a/libraries/chain/protocol_feature_manager.cpp +++ b/libraries/chain/protocol_feature_manager.cpp @@ -229,6 +229,17 @@ Allows privileged contracts to set the constraints on WebAssembly code. Builtin protocol feature: BLOCKCHAIN_PARAMETERS Allows privileged contracts to get and set subsets of blockchain parameters. +*/ + ( builtin_protocol_feature_t::wasm_code_coverage, builtin_protocol_feature_spec{ + "WASM_CODE_COVERAGE", + fc::variant("57f673c34b311a0bd9060c3c47ce596e0d9ae827a79b80b629a3f0667b21ccc9").as(), + {} + } ) + // SHA256 hash of the raw message below within the comment delimiters (do not modify message below). +/* +Builtin protocol feature: WASM_CODE_COVERAGE + +Adds coverage_XXX functions to support code coverage. */ ; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 117a4cae0db..e26e64359e9 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -1134,82 +1134,6 @@ struct callbacks { } } - std::unordered_map > > funcnt_map; - std::unordered_map > > linecnt_map; - - void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - funcnt[func_num]++; - } - - void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - linecnt[line_num]++; - } - - uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - return funcnt[func_num]; - } - - uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - return linecnt[line_num]; - } - - void coverage_dump(uint32_t n) { - auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); - std::ofstream out_json_file; - out_json_file.open(fName); - - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for (auto code_map : funcnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - for (auto funcnt : code_map.second) { - auto file_num = funcnt.first; - for (auto func : funcnt.second) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; - } - } - out_json_file << "\t\t]\n"; - } - out_json_file << "\t}\n"; - - out_json_file << "\t\"lines\": {"; - for (auto code_map : linecnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - - for (auto linecnt : code_map.second) { - auto file_num = linecnt.first; - for (auto line : linecnt.second) { - auto line_num = line.first; - auto cnt = line.second; - out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; - } - } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file << "}\n"; - out_json_file.close(); - } - - void coverage_reset() { - funcnt_map.clear(); - linecnt_map.clear(); - } - }; // callbacks #define DB_REGISTER_SECONDARY(IDX) \ @@ -1297,13 +1221,6 @@ void register_callbacks() { rhf_t::add<&callbacks::sha512>("env", "sha512"); rhf_t::add<&callbacks::ripemd160>("env", "ripemd160"); rhf_t::add<&callbacks::recover_key>("env", "recover_key"); - - rhf_t::add<&callbacks::coverage_inc_fun_cnt>("env", "coverage_inc_fun_cnt"); - rhf_t::add<&callbacks::coverage_inc_line_cnt>("env", "coverage_inc_line_cnt"); - rhf_t::add<&callbacks::coverage_get_fun_cnt>("env", "coverage_get_fun_cnt"); - rhf_t::add<&callbacks::coverage_get_line_cnt>("env", "coverage_get_line_cnt"); - rhf_t::add<&callbacks::coverage_dump>("env", "coverage_dump"); - rhf_t::add<&callbacks::coverage_reset>("env", "coverage_reset"); } static int run(const char* wasm, const std::vector& args) { From c078facd9755cade8d45e7e060d07963ef6cb5cd Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 3 Jan 2022 20:19:24 -0500 Subject: [PATCH 16/33] move rodoes coverage state to global --- .../include/b1/rodeos/callbacks/coverage.hpp | 17 +++-------------- libraries/rodeos/rodeos.cpp | 3 +++ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 10b8aad912a..20de7296a98 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -5,11 +5,10 @@ namespace b1::rodeos { +extern std::unordered_map > > funcnt_map; +extern std::unordered_map > > linecnt_map; + struct coverage_state { - std::unordered_map > > funcnt_map; - std::unordered_map > > linecnt_map; - // std::map > > funcnt_map; - // std::map > > linecnt_map; }; template @@ -17,37 +16,30 @@ struct coverage_callbacks { Derived& derived() { return static_cast(*this); } void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &funcnt_map = derived().get_coverage_state().funcnt_map; auto &code_map = funcnt_map[code]; auto &funcnt = code_map[file_num]; funcnt[func_num]++; } void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &linecnt_map = derived().get_coverage_state().linecnt_map; auto &code_map = linecnt_map[code]; auto &linecnt = code_map[file_num]; linecnt[line_num]++; } uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &funcnt_map = derived().get_coverage_state().funcnt_map; auto &code_map = funcnt_map[code]; auto &funcnt = code_map[file_num]; return funcnt[func_num]; } uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &linecnt_map = derived().get_coverage_state().linecnt_map; auto &code_map = linecnt_map[code]; auto &linecnt = code_map[file_num]; return linecnt[line_num]; } void coverage_dump(uint32_t n) { - auto &funcnt_map = derived().get_coverage_state().funcnt_map; - auto &linecnt_map = derived().get_coverage_state().linecnt_map; - auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); std::ofstream out_json_file; out_json_file.open(fName); @@ -92,9 +84,6 @@ struct coverage_callbacks { } void coverage_reset() { - auto &funcnt_map = derived().get_coverage_state().funcnt_map; - auto &linecnt_map = derived().get_coverage_state().linecnt_map; - funcnt_map.clear(); linecnt_map.clear(); } diff --git a/libraries/rodeos/rodeos.cpp b/libraries/rodeos/rodeos.cpp index 6b51436e978..c866de756aa 100644 --- a/libraries/rodeos/rodeos.cpp +++ b/libraries/rodeos/rodeos.cpp @@ -8,6 +8,9 @@ namespace b1::rodeos { +std::unordered_map > > funcnt_map; +std::unordered_map > > linecnt_map; + namespace ship_protocol = eosio::ship_protocol; using ship_protocol::get_blocks_result_base; From 033d0df7ab76bb42f5d2a351ed6f9c8699ff982a Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Tue, 11 Jan 2022 14:11:01 -0500 Subject: [PATCH 17/33] update programs/eosio-tester/main.cpp --- programs/eosio-tester/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index e26e64359e9..efc22cd3686 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -184,6 +184,12 @@ struct test_chain { test_chain(const char* snapshot) { eosio::chain::genesis_state genesis; + // increase default limits to allow for code coverage + genesis.initial_configuration.max_transaction_net_usage *= 2; + genesis.initial_configuration.max_block_net_usage *= 2; + genesis.initial_configuration.max_block_cpu_usage *= 2; + genesis.initial_configuration.max_transaction_cpu_usage *= 2; + genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); cfg = std::make_unique(); cfg->blog.log_dir = dir.path() / "blocks"; From 25c6b14d6cee6d5a3180a6ef50fb4c228d602f86 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 17 Jan 2022 14:02:10 -0600 Subject: [PATCH 18/33] Refactor code coverage host functions to remove need for protocol feature --- libraries/chain/CMakeLists.txt | 1 - libraries/chain/controller.cpp | 14 --- .../eosio/chain/protocol_feature_manager.hpp | 3 +- .../eosio/chain/webassembly/preconditions.hpp | 12 +++ libraries/chain/protocol_feature_manager.cpp | 11 -- .../chain/webassembly/runtimes/eos-vm.cpp | 21 ---- .../include/b1/rodeos/callbacks/coverage.hpp | 66 ++---------- libraries/rodeos/include/eosio/coverage.hpp | 101 ++++++++++++++++++ programs/eosio-tester/main.cpp | 72 ++++++++++--- 9 files changed, 181 insertions(+), 120 deletions(-) create mode 100644 libraries/rodeos/include/eosio/coverage.hpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c457f63a921..825253a2526 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -62,7 +62,6 @@ set(CHAIN_WEBASSEMBLY_SOURCES webassembly/compiler_builtins.cpp webassembly/context_free.cpp webassembly/console.cpp - webassembly/coverage.cpp webassembly/crypto.cpp webassembly/database.cpp webassembly/kv_database.cpp diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 3d1f306571f..be9526f3f2d 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -277,7 +277,6 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); set_activation_handler(); - set_activation_handler(); self.irreversible_block.connect([this](const block_state_ptr& bsp) { wasmif.current_lib(bsp->block_num); @@ -3457,19 +3456,6 @@ void controller_impl::on_activation -void controller_impl::on_activation() { - db.modify( db.get(), [&]( auto& ps ) { - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); - add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); - } ); -} - - /// End of protocol feature activation handlers } } /// eosio::chain diff --git a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp index 4934ad3153e..22b0df48905 100644 --- a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp +++ b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp @@ -26,8 +26,7 @@ enum class builtin_protocol_feature_t : uint32_t { action_return_value, kv_database, configurable_wasm_limits, - blockchain_parameters, - wasm_code_coverage + blockchain_parameters }; struct protocol_feature_subjective_restrictions { diff --git a/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp b/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp index 3416557904b..517ca839ed3 100644 --- a/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp @@ -167,4 +167,16 @@ namespace eosio { namespace chain { namespace webassembly { static_assert( are_whitelisted_legacy_types_v...>, "legacy whitelisted type violation"); })); + template + struct host_function_registrator { + template + constexpr host_function_registrator(Mod mod_name, Name fn_name) { + using rhf_t = eos_vm_host_functions_t; + rhf_t::add(mod_name.c_str(), fn_name.c_str()); + #ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED + eosvmoc::register_eosvm_oc>(mod_name + BOOST_HANA_STRING(".") + fn_name); + #endif + } + }; + }}} // ns eosio::chain::webassembly diff --git a/libraries/chain/protocol_feature_manager.cpp b/libraries/chain/protocol_feature_manager.cpp index dfdd48922ed..82da9deb542 100644 --- a/libraries/chain/protocol_feature_manager.cpp +++ b/libraries/chain/protocol_feature_manager.cpp @@ -229,17 +229,6 @@ Allows privileged contracts to set the constraints on WebAssembly code. Builtin protocol feature: BLOCKCHAIN_PARAMETERS Allows privileged contracts to get and set subsets of blockchain parameters. -*/ - ( builtin_protocol_feature_t::wasm_code_coverage, builtin_protocol_feature_spec{ - "WASM_CODE_COVERAGE", - fc::variant("57f673c34b311a0bd9060c3c47ce596e0d9ae827a79b80b629a3f0667b21ccc9").as(), - {} - } ) - // SHA256 hash of the raw message below within the comment delimiters (do not modify message below). -/* -Builtin protocol feature: WASM_CODE_COVERAGE - -Adds coverage_XXX functions to support code coverage. */ ; diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 080352dc60d..a60e9381816 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -11,7 +11,6 @@ #include #endif #include -#include namespace eosio { namespace chain { namespace webassembly { namespace eos_vm_runtime { @@ -289,18 +288,6 @@ std::unique_ptr eos_vm_profile_runtime::inst } -template -struct host_function_registrator { - template - constexpr host_function_registrator(Mod mod_name, Name fn_name) { - using rhf_t = eos_vm_host_functions_t; - rhf_t::add(mod_name.c_str(), fn_name.c_str()); -#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED - eosvmoc::register_eosvm_oc>(mod_name + BOOST_HANA_STRING(".") + fn_name); -#endif - } -}; - #define REGISTER_HOST_FUNCTION(NAME, ...) \ static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \ NAME##_registrator_impl() { \ @@ -574,14 +561,6 @@ REGISTER_CF_HOST_FUNCTION(__letf2); REGISTER_CF_HOST_FUNCTION(__lttf2); REGISTER_CF_HOST_FUNCTION(__unordtf2); -// code coverage API -REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) -REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_get_line_cnt) -REGISTER_HOST_FUNCTION(coverage_dump) -REGISTER_HOST_FUNCTION(coverage_reset) - } // namespace webassembly } // namespace chain } // namespace eosio diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 20de7296a98..101434d4aff 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -1,13 +1,10 @@ #pragma once #include -#include +#include namespace b1::rodeos { -extern std::unordered_map > > funcnt_map; -extern std::unordered_map > > linecnt_map; - struct coverage_state { }; @@ -16,76 +13,27 @@ struct coverage_callbacks { Derived& derived() { return static_cast(*this); } void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - funcnt[func_num]++; + eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num); } void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - linecnt[line_num]++; + eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num); } uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - return funcnt[func_num]; + eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); } uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - return linecnt[line_num]; + eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); } void coverage_dump(uint32_t n) { - auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); - std::ofstream out_json_file; - out_json_file.open(fName); - - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for (auto code_map : funcnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - for (auto funcnt : code_map.second) { - auto file_num = funcnt.first; - for (auto func : funcnt.second) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; - } - } - out_json_file << "\t\t]\n"; - } - out_json_file << "\t}\n"; - - out_json_file << "\t\"lines\": {"; - for (auto code_map : linecnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - - for (auto linecnt : code_map.second) { - auto file_num = linecnt.first; - for (auto line : linecnt.second) { - auto line_num = line.first; - auto cnt = line.second; - out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; - } - } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file << "}\n"; - out_json_file.close(); + eosio::coverage::coverage_dump(n); } void coverage_reset() { - funcnt_map.clear(); - linecnt_map.clear(); + eosio::coverage::coverage_reset(); } template diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp new file mode 100644 index 00000000000..662418f710f --- /dev/null +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include +#include +#include +#include + +// rodeos lib is not the ideal location for this as it is also used by eosio-tester but rodeos lib keeps it out of nodeos +namespace eosio { +namespace coverage { + +class coverage_maps { +public: + static coverage_maps& instance() { + static coverage_maps instance; + return instance; + } + coverage_maps(const coverage_maps&) = delete; + void operator=(const coverage_maps&) = delete; + + std::unordered_map > > funcnt_map; + std::unordered_map > > linecnt_map; +private: + coverage_maps() = default; +}; + +inline void coverage_inc_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num ) { + auto& code_map = coverage_maps::instance().funcnt_map[code]; + auto& funcnt = code_map[file_num]; + funcnt[func_num]++; +} + +inline void coverage_inc_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num ) { + auto& code_map = coverage_maps::instance().linecnt_map[code]; + auto& linecnt = code_map[file_num]; + linecnt[line_num]++; +} + +inline uint32_t coverage_get_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num ) { + auto& code_map = coverage_maps::instance().funcnt_map[code]; + auto& funcnt = code_map[file_num]; + return funcnt[func_num]; +} + +inline uint32_t coverage_get_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num ) { + auto& code_map = coverage_maps::instance().linecnt_map[code]; + auto& linecnt = code_map[file_num]; + return linecnt[line_num]; +} + +inline void coverage_dump( uint32_t n ) { + auto fName = std::string( "call-counts" ) + std::to_string( n ) + std::string( ".json" ); + std::ofstream out_json_file; + out_json_file.open( fName ); + + // dont use auto JSON serialization because + // we want to convert maps to arrays + out_json_file << "{\n"; + out_json_file << "\t\"functions\": {"; + for( const auto& code_map: coverage_maps::instance().funcnt_map ) { + auto code_str = eosio::chain::name( code_map.first ).to_string(); + out_json_file << "\t\t\"" << code_str << "\": [\n"; + for( const auto& funcnt: code_map.second ) { + auto file_num = funcnt.first; + for( const auto& func: funcnt.second ) { + auto func_num = func.first; + auto calls = func.second; + out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + } + } + out_json_file << "\t\t]\n"; + } + out_json_file << "\t}\n"; + + out_json_file << "\t\"lines\": {"; + for( const auto& code_map: coverage_maps::instance().linecnt_map ) { + auto code_str = eosio::chain::name( code_map.first ).to_string(); + out_json_file << "\t\t\"" << code_str << "\": [\n"; + + for( const auto& linecnt: code_map.second ) { + auto file_num = linecnt.first; + for( const auto& line: linecnt.second ) { + auto line_num = line.first; + auto cnt = line.second; + out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; + } + } + out_json_file << "]\n"; + } + out_json_file << "\t}\n"; + out_json_file << "}\n"; + out_json_file.close(); +} + +inline void coverage_reset() { + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); +} + +} // namespace coverage +} // namespace eosio \ No newline at end of file diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index efc22cd3686..c5e9ab45007 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -1,6 +1,11 @@ +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -10,6 +15,7 @@ #include #include #include +#include #undef N @@ -102,6 +108,51 @@ struct transaction_checktime_factory { }; }; // namespace +// Defined here to keep it out of nodeos +namespace eosio::chain::webassembly { + +#define REGISTER_HOST_FUNCTION(NAME, ...) \ + static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \ + NAME##_registrator_impl() { \ + return {BOOST_HANA_STRING("env"), BOOST_HANA_STRING(#NAME)}; \ + } \ + inline static auto NAME##_registrator = NAME##_registrator_impl(); + +// code coverage API +REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) +REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) +REGISTER_HOST_FUNCTION(coverage_get_line_cnt) +REGISTER_HOST_FUNCTION(coverage_dump) +REGISTER_HOST_FUNCTION(coverage_reset) + +void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num); +} + +void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num); +} + +uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { + eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); +} + +uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { + eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); +} + +void interface::coverage_dump(uint32_t n) { + eosio::coverage::coverage_dump(n); +} + +void interface::coverage_reset() { + eosio::coverage::coverage_reset(); +} + +} // namespace eosio::chain::webassembly + + struct intrinsic_context { eosio::chain::controller& control; eosio::chain::packed_transaction trx; @@ -233,17 +284,15 @@ struct test_chain { control, [] {}, [] { return false; }, genesis); control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, { *control->get_protocol_feature_manager().get_builtin_digest( - eosio::chain::builtin_protocol_feature_t::preactivate_feature) - }); - auto& pfm = control->get_protocol_feature_manager(); - auto feat = eosio::chain::builtin_protocol_feature_t::wasm_code_coverage; - auto wasm_code_coverage_digest = *pfm.get_builtin_digest(feat); - uint32_t action_id = 0; - control->preactivate_feature(action_id, wasm_code_coverage_digest); - finish_block(); - - control->start_block(control->head_block_time() + fc::microseconds(block_interval_us), 0, - { wasm_code_coverage_digest }); + eosio::chain::builtin_protocol_feature_t::preactivate_feature) }); + control->mutable_db().modify( control->mutable_db().get(), [&]( auto& ps ) { + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); + } ); } } @@ -516,7 +565,6 @@ FC_REFLECT(push_trx_args, (transaction)(context_free_data)(signatures)(keys)) return selected().IDX.previous_secondary(iterator, primary); \ } - struct callbacks { ::state& state; From 931775a23ce08b161e31af78d62f2838d43836a4 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 17 Jan 2022 14:52:56 -0600 Subject: [PATCH 19/33] rm unused file --- libraries/chain/webassembly/coverage.cpp | 82 ------------------------ 1 file changed, 82 deletions(-) delete mode 100644 libraries/chain/webassembly/coverage.cpp diff --git a/libraries/chain/webassembly/coverage.cpp b/libraries/chain/webassembly/coverage.cpp deleted file mode 100644 index a0d7586c40d..00000000000 --- a/libraries/chain/webassembly/coverage.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include - -#include -#include - -namespace eosio { namespace chain { namespace webassembly { - std::unordered_map > > funcnt_map; - std::unordered_map > > linecnt_map; - - void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - funcnt[func_num]++; - } - - void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - linecnt[line_num]++; - } - - uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - auto &code_map = funcnt_map[code]; - auto &funcnt = code_map[file_num]; - return funcnt[func_num]; - } - - uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - auto &code_map = linecnt_map[code]; - auto &linecnt = code_map[file_num]; - return linecnt[line_num]; - } - - void interface::coverage_dump(uint32_t n) { - auto fName = std::string("call-counts") + std::to_string(n) + std::string(".json"); - std::ofstream out_json_file; - out_json_file.open(fName); - - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for (auto code_map : funcnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - for (auto funcnt : code_map.second) { - auto file_num = funcnt.first; - for (auto func : funcnt.second) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; - } - } - out_json_file << "\t\t]\n"; - } - out_json_file << "\t}\n"; - - out_json_file << "\t\"lines\": {"; - for (auto code_map : linecnt_map) { - auto code_str = eosio::chain::name(code_map.first).to_string(); - out_json_file << "\t\t\"" << code_str <<"\": [\n"; - - for (auto linecnt : code_map.second) { - auto file_num = linecnt.first; - for (auto line : linecnt.second) { - auto line_num = line.first; - auto cnt = line.second; - out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; - } - } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file << "}\n"; - out_json_file.close(); - } - - void interface::coverage_reset() { - funcnt_map.clear(); - linecnt_map.clear(); - } -}}} From e7ce00d91aca0f950fb435847c7c2050e265efb2 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 17 Jan 2022 15:21:16 -0600 Subject: [PATCH 20/33] Additional cleanup --- libraries/chain/include/eosio/chain/controller.hpp | 6 +++++- libraries/rodeos/rodeos.cpp | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 6228ec2be9b..8034ce91638 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -12,6 +12,7 @@ #include #include +struct test_chain; namespace chainbase { class database; } @@ -403,10 +404,13 @@ namespace eosio { namespace chain { private: friend class apply_context; friend class transaction_context; + friend struct ::test_chain; + + chainbase::database& mutable_db()const; std::unique_ptr my; public: - chainbase::database& mutable_db()const; + }; diff --git a/libraries/rodeos/rodeos.cpp b/libraries/rodeos/rodeos.cpp index c866de756aa..6b51436e978 100644 --- a/libraries/rodeos/rodeos.cpp +++ b/libraries/rodeos/rodeos.cpp @@ -8,9 +8,6 @@ namespace b1::rodeos { -std::unordered_map > > funcnt_map; -std::unordered_map > > linecnt_map; - namespace ship_protocol = eosio::ship_protocol; using ship_protocol::get_blocks_result_base; From 1190d853032a0882522be0146d383233fc4ed56d Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 17 Jan 2022 15:25:59 -0600 Subject: [PATCH 21/33] whitespace cleanup --- libraries/chain/include/eosio/chain/controller.hpp | 2 -- libraries/rodeos/include/eosio/coverage.hpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 8034ce91638..d70f4a7a7b5 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -409,8 +409,6 @@ namespace eosio { namespace chain { chainbase::database& mutable_db()const; std::unique_ptr my; - public: - }; diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index 662418f710f..bb6a4f09c72 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -98,4 +98,4 @@ inline void coverage_reset() { } } // namespace coverage -} // namespace eosio \ No newline at end of file +} // namespace eosio From 7d143dafb2452a4f8d50767dcc6523b4234f1dd1 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 18 Jan 2022 09:45:33 -0600 Subject: [PATCH 22/33] Fix oc build --- .../chain/include/eosio/chain/webassembly/preconditions.hpp | 3 +++ libraries/chain/webassembly/runtimes/eos-vm.cpp | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp b/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp index 517ca839ed3..70f52ca3c10 100644 --- a/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/preconditions.hpp @@ -3,6 +3,9 @@ #include #include #include +#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED +#include +#endif #include #include diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index a60e9381816..4c28b6791a3 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -7,9 +7,6 @@ //eos-vm includes #include #include -#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED -#include -#endif #include namespace eosio { namespace chain { namespace webassembly { namespace eos_vm_runtime { From 52fe79e81dc01755bf16f295bafbbcb9c3d970ad Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 21 Jan 2022 13:26:05 -0600 Subject: [PATCH 23/33] Add missing returns --- programs/eosio-tester/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index c5e9ab45007..b56d7ba622c 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -135,11 +135,11 @@ void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t } uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); + return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); } uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); + return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); } void interface::coverage_dump(uint32_t n) { From 475bc5a85da54ddf758070b3616a7f70496484d0 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 25 Jan 2022 12:03:42 -0600 Subject: [PATCH 24/33] Add missing returns --- libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 101434d4aff..27a269c98ac 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -21,11 +21,11 @@ struct coverage_callbacks { } uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); + return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); } uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); + return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); } void coverage_dump(uint32_t n) { From 443b964f1299c949fa6e701da027cc3a574f9cff Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Wed, 2 Feb 2022 16:51:54 -0500 Subject: [PATCH 25/33] new function coverage_dump_funcnt replaces coverage_dump --- .../eos-vm-oc/intrinsic_mapping.hpp | 2 +- .../eosio/chain/webassembly/interface.hpp | 2 +- .../include/b1/rodeos/callbacks/coverage.hpp | 6 +- libraries/rodeos/include/eosio/coverage.hpp | 87 +++++++++++-------- programs/eosio-tester/main.cpp | 8 +- 5 files changed, 60 insertions(+), 45 deletions(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index a3823c92e08..194a251e7d1 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -281,7 +281,7 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.coverage_inc_line_cnt"_s, "env.coverage_get_fun_cnt"_s, "env.coverage_get_line_cnt"_s, - "env.coverage_dump"_s, + "env.coverage_dump_funcnt"_s, "env.coverage_reset"_s ); diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index 1411bba5bef..d58ca90d02a 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1902,7 +1902,7 @@ namespace eosio { namespace chain { namespace webassembly { void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num); uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); - void coverage_dump(uint32_t); + uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, span file_name, uint32_t max, bool append); void coverage_reset(); private: diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 27a269c98ac..07a1b20bb11 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -28,8 +28,8 @@ struct coverage_callbacks { return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); } - void coverage_dump(uint32_t n) { - eosio::coverage::coverage_dump(n); + uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { + return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append); } void coverage_reset() { @@ -43,7 +43,7 @@ struct coverage_callbacks { RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_inc_line_cnt); RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_fun_cnt); RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_line_cnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_dump); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_dump_funcnt); RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_reset); } }; // coverage_callbacks diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index bb6a4f09c72..411890dcfb0 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -48,48 +48,63 @@ inline uint32_t coverage_get_line_cnt( uint64_t code, uint32_t file_num, uint32_ return linecnt[line_num]; } -inline void coverage_dump( uint32_t n ) { - auto fName = std::string( "call-counts" ) + std::to_string( n ) + std::string( ".json" ); - std::ofstream out_json_file; - out_json_file.open( fName ); +// dump coverage output to file +// if code == 0, dump all coverage for all codes, constrained by max argument +// max is only checked for every code, so it is possible to exceed the number +// if code > 0, then only dump coverage for specific code and specific file_num +// in this mode, max is effectively ignored +// returns the next code, or 0 if at end +inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const char* file_name, uint32_t file_name_size, uint32_t max, bool append ) { + std::ofstream out_bin_file; + auto flags = std::ofstream::out | std::ofstream::binary; + if (append) + flags = flags | std::ofstream::app; + else + flags = flags | std::ofstream::trunc; - // dont use auto JSON serialization because - // we want to convert maps to arrays - out_json_file << "{\n"; - out_json_file << "\t\"functions\": {"; - for( const auto& code_map: coverage_maps::instance().funcnt_map ) { - auto code_str = eosio::chain::name( code_map.first ).to_string(); - out_json_file << "\t\t\"" << code_str << "\": [\n"; - for( const auto& funcnt: code_map.second ) { - auto file_num = funcnt.first; - for( const auto& func: funcnt.second ) { - auto func_num = func.first; - auto calls = func.second; - out_json_file << "\t\t\t[" << file_num << ", " << func_num << ", " << calls << "]\n"; + ilog("coverage_dump_funcnt: file_name= ${f} max= ${max} ${app}", ("f", file_name)("nax", max)("app", append)); + out_bin_file.open(file_name, flags ); + uint32_t i = 0; + auto funcnt_map = coverage_maps::instance().funcnt_map; + auto code_itr = funcnt_map.begin(); + if (code > 0) { + code_itr = funcnt_map.find(code); + } + while (code_itr != funcnt_map.end() && i < max) { + auto codenum = code_itr->first; + auto filenum_map = code_itr->second; + auto filenum_itr = filenum_map.begin(); + if (code > 0) { + filenum_itr = filenum_map.find(file_num); + } + while (filenum_itr != filenum_map.end()) { + auto filenum = filenum_itr->first; + auto funcnum_map = filenum_itr->second; + for (const auto& funcnum_itr : funcnum_map) { + auto funcnum = funcnum_itr.first; + auto calls = funcnum_itr.second; + out_bin_file.write(reinterpret_cast(&codenum), sizeof(code)); + out_bin_file.write(reinterpret_cast(&filenum), sizeof(filenum)); + out_bin_file.write(reinterpret_cast(&funcnum), sizeof(funcnum)); + out_bin_file.write(reinterpret_cast(&calls), sizeof(calls)); + ++i; } + ++filenum_itr; + if (code > 0) + break; } - out_json_file << "\t\t]\n"; + ++code_itr; + if (code > 0); + break; } - out_json_file << "\t}\n"; - out_json_file << "\t\"lines\": {"; - for( const auto& code_map: coverage_maps::instance().linecnt_map ) { - auto code_str = eosio::chain::name( code_map.first ).to_string(); - out_json_file << "\t\t\"" << code_str << "\": [\n"; + out_bin_file.flush(); + out_bin_file.close(); - for( const auto& linecnt: code_map.second ) { - auto file_num = linecnt.first; - for( const auto& line: linecnt.second ) { - auto line_num = line.first; - auto cnt = line.second; - out_json_file << "\t\t\t[" << file_num << ", " << line_num << ", " << cnt << "]\n"; - } - } - out_json_file << "]\n"; - } - out_json_file << "\t}\n"; - out_json_file << "}\n"; - out_json_file.close(); + uint64_t r = 0; + if(code_itr != funcnt_map.end()) + r = code_itr->first; + return r; } inline void coverage_reset() { diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index b56d7ba622c..59948335276 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -123,7 +123,7 @@ REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) REGISTER_HOST_FUNCTION(coverage_get_line_cnt) -REGISTER_HOST_FUNCTION(coverage_dump) +REGISTER_HOST_FUNCTION(coverage_dump_funcnt) REGISTER_HOST_FUNCTION(coverage_reset) void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { @@ -142,8 +142,8 @@ uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); } -void interface::coverage_dump(uint32_t n) { - eosio::coverage::coverage_dump(n); +uint64_t interface::coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { + return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append); } void interface::coverage_reset() { @@ -290,7 +290,7 @@ struct test_chain { eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump_funcnt" ); eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); } ); } From 9b75c43e6ca82abedc9a2ec03e1d3c9ee2d006a4 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Thu, 3 Feb 2022 08:31:11 -0500 Subject: [PATCH 26/33] separate coverage maps for chain/rodeos --- .../include/b1/rodeos/callbacks/coverage.hpp | 28 +++++++++--- libraries/rodeos/include/eosio/coverage.hpp | 43 ++++++------------- programs/eosio-tester/main.cpp | 29 ++++++++++--- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 07a1b20bb11..03f04513926 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -5,6 +5,21 @@ namespace b1::rodeos { +class coverage_maps { + public: + static coverage_maps& instance() { + static coverage_maps instance; + return instance; + } + coverage_maps(const coverage_maps&) = delete; + void operator=(const coverage_maps&) = delete; + + cov_map_t funcnt_map; + cov_map_t linecnt_map; + private: + coverage_maps() = default; +}; + struct coverage_state { }; @@ -13,27 +28,28 @@ struct coverage_callbacks { Derived& derived() { return static_cast(*this); } void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num); + eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); } void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num); + eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); } uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); + return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); } uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); + return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); } uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { - return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append); + return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } void coverage_reset() { - eosio::coverage::coverage_reset(); + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); } template diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index 411890dcfb0..47f76608ef2 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -5,45 +5,32 @@ #include #include +using cov_map_t = std::unordered_map > >; + // rodeos lib is not the ideal location for this as it is also used by eosio-tester but rodeos lib keeps it out of nodeos namespace eosio { namespace coverage { -class coverage_maps { -public: - static coverage_maps& instance() { - static coverage_maps instance; - return instance; - } - coverage_maps(const coverage_maps&) = delete; - void operator=(const coverage_maps&) = delete; - - std::unordered_map > > funcnt_map; - std::unordered_map > > linecnt_map; -private: - coverage_maps() = default; -}; - -inline void coverage_inc_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num ) { - auto& code_map = coverage_maps::instance().funcnt_map[code]; +inline void coverage_inc_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num, cov_map_t& funcnt_map) { + auto& code_map = funcnt_map[code]; auto& funcnt = code_map[file_num]; funcnt[func_num]++; } -inline void coverage_inc_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num ) { - auto& code_map = coverage_maps::instance().linecnt_map[code]; +inline void coverage_inc_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num, cov_map_t& linecnt_map ) { + auto& code_map = linecnt_map[code]; auto& linecnt = code_map[file_num]; linecnt[line_num]++; } -inline uint32_t coverage_get_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num ) { - auto& code_map = coverage_maps::instance().funcnt_map[code]; +inline uint32_t coverage_get_fun_cnt( uint64_t code, uint32_t file_num, uint32_t func_num, cov_map_t& funcnt_map ) { + auto& code_map = funcnt_map[code]; auto& funcnt = code_map[file_num]; return funcnt[func_num]; } -inline uint32_t coverage_get_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num ) { - auto& code_map = coverage_maps::instance().linecnt_map[code]; +inline uint32_t coverage_get_line_cnt( uint64_t code, uint32_t file_num, uint32_t line_num, cov_map_t& linecnt_map ) { + auto& code_map = linecnt_map[code]; auto& linecnt = code_map[file_num]; return linecnt[line_num]; } @@ -52,9 +39,9 @@ inline uint32_t coverage_get_line_cnt( uint64_t code, uint32_t file_num, uint32_ // if code == 0, dump all coverage for all codes, constrained by max argument // max is only checked for every code, so it is possible to exceed the number // if code > 0, then only dump coverage for specific code and specific file_num -// in this mode, max is effectively ignored +// in this mode, max is effectively ignored (though should be > 0) // returns the next code, or 0 if at end -inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const char* file_name, uint32_t file_name_size, uint32_t max, bool append ) { +inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const char* file_name, uint32_t file_name_size, uint32_t max, bool append, cov_map_t& funcnt_map ) { std::ofstream out_bin_file; auto flags = std::ofstream::out | std::ofstream::binary; if (append) @@ -65,7 +52,6 @@ inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const cha ilog("coverage_dump_funcnt: file_name= ${f} max= ${max} ${app}", ("f", file_name)("nax", max)("app", append)); out_bin_file.open(file_name, flags ); uint32_t i = 0; - auto funcnt_map = coverage_maps::instance().funcnt_map; auto code_itr = funcnt_map.begin(); if (code > 0) { code_itr = funcnt_map.find(code); @@ -107,10 +93,5 @@ inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const cha return r; } -inline void coverage_reset() { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); -} - } // namespace coverage } // namespace eosio diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 59948335276..e5a20811a06 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -111,6 +111,22 @@ struct transaction_checktime_factory { // Defined here to keep it out of nodeos namespace eosio::chain::webassembly { +class coverage_maps { +public: + static coverage_maps& instance() { + static coverage_maps instance; + return instance; + } + coverage_maps(const coverage_maps&) = delete; + void operator=(const coverage_maps&) = delete; + + cov_map_t funcnt_map; + cov_map_t linecnt_map; +private: + coverage_maps() = default; +}; + + #define REGISTER_HOST_FUNCTION(NAME, ...) \ static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \ NAME##_registrator_impl() { \ @@ -127,27 +143,28 @@ REGISTER_HOST_FUNCTION(coverage_dump_funcnt) REGISTER_HOST_FUNCTION(coverage_reset) void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num); + eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); } void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num); + eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); } uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num); + return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); } uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num); + return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); } uint64_t interface::coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { - return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append); + return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } void interface::coverage_reset() { - eosio::coverage::coverage_reset(); + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); } } // namespace eosio::chain::webassembly From 13a47958fdc46637e1cbdc3e458dabb94cf6d97e Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Thu, 3 Feb 2022 18:19:16 -0500 Subject: [PATCH 27/33] reduce new coverage host functions to two --- .../eos-vm-oc/intrinsic_mapping.hpp | 8 +-- .../eosio/chain/webassembly/interface.hpp | 8 +-- .../include/b1/rodeos/callbacks/coverage.hpp | 58 ++++++++-------- libraries/rodeos/include/eosio/coverage.hpp | 64 ++++++++--------- programs/eosio-tester/main.cpp | 69 +++++++++---------- 5 files changed, 97 insertions(+), 110 deletions(-) diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 194a251e7d1..68b5f734ab9 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -277,12 +277,8 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "env.print_time_us"_s, "env.get_input_data"_s, "env.set_output_data"_s, - "env.coverage_inc_fun_cnt"_s, - "env.coverage_inc_line_cnt"_s, - "env.coverage_get_fun_cnt"_s, - "env.coverage_get_line_cnt"_s, - "env.coverage_dump_funcnt"_s, - "env.coverage_reset"_s + "env.coverage_getinc"_s, + "env.coverage_dump"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/webassembly/interface.hpp b/libraries/chain/include/eosio/chain/webassembly/interface.hpp index d58ca90d02a..f86f00cb973 100644 --- a/libraries/chain/include/eosio/chain/webassembly/interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/interface.hpp @@ -1898,12 +1898,8 @@ namespace eosio { namespace chain { namespace webassembly { int32_t __unordtf2(uint64_t, uint64_t, uint64_t, uint64_t) const; // code coverage support functions - void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num); - void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); - uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num); - uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num); - uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, span file_name, uint32_t max, bool append); - void coverage_reset(); + uint32_t coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc); + uint64_t coverage_dump(uint64_t code, uint32_t file_num, span file_name, uint32_t max, bool append, uint32_t mode, bool reset); private: apply_context& context; diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index 03f04513926..cce214b6f4b 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -27,40 +27,44 @@ template struct coverage_callbacks { Derived& derived() { return static_cast(*this); } - void coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); - } - - void coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); - } - - uint32_t coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); - } - - uint32_t coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); - } - - uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { - return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + uint32_t coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { + if(inc) { + if (mode == 0) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + } else if (mode == 1) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + } + } + else { + if (mode == 0) { + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + } + else if (mode == 1) { + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + } + } + return 0; } - void coverage_reset() { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); + uint64_t coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { + if (reset) { + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); + } + else if (mode == 0) { + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + } + else if (mode == 1) { + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); + } + return 0; } template static void register_callbacks() { // todo: preconditions - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_inc_fun_cnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_inc_line_cnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_fun_cnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_get_line_cnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_dump_funcnt); - RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_reset); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_getinc); + RODEOS_REGISTER_CALLBACK(Rft, Derived, coverage_dump); } }; // coverage_callbacks diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index 47f76608ef2..09b6dda4cbf 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -11,37 +11,25 @@ using cov_map_t = std::unordered_map 0, then only dump coverage for specific code and specific file_num -// in this mode, max is effectively ignored (though should be > 0) +// if max == 0, then only dump coverage for specific code and specific file_num +// in theis case code must be > 0 // returns the next code, or 0 if at end -inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const char* file_name, uint32_t file_name_size, uint32_t max, bool append, cov_map_t& funcnt_map ) { +inline uint64_t coverage_dump(uint64_t code, uint32_t file_num, const char* file_name, uint32_t file_name_size, uint32_t max, bool append, cov_map_t& cov_map) { std::ofstream out_bin_file; auto flags = std::ofstream::out | std::ofstream::binary; if (append) @@ -52,35 +40,39 @@ inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const cha ilog("coverage_dump_funcnt: file_name= ${f} max= ${max} ${app}", ("f", file_name)("nax", max)("app", append)); out_bin_file.open(file_name, flags ); uint32_t i = 0; - auto code_itr = funcnt_map.begin(); + auto code_itr = cov_map.begin(); + if (max == 0 && code == 0) { + elog("coverage_dump_funcnt: when max == 0, code must be > 0"); + return 0; + } if (code > 0) { - code_itr = funcnt_map.find(code); + code_itr = cov_map.find(code); } - while (code_itr != funcnt_map.end() && i < max) { + while (code_itr != cov_map.end() && (max == 0 || i < max)) { auto codenum = code_itr->first; - auto filenum_map = code_itr->second; + auto& filenum_map = code_itr->second; auto filenum_itr = filenum_map.begin(); - if (code > 0) { + if (max == 0) { filenum_itr = filenum_map.find(file_num); } while (filenum_itr != filenum_map.end()) { auto filenum = filenum_itr->first; - auto funcnum_map = filenum_itr->second; + auto& funcnum_map = filenum_itr->second; for (const auto& funcnum_itr : funcnum_map) { - auto funcnum = funcnum_itr.first; + auto func_or_line_num = funcnum_itr.first; auto calls = funcnum_itr.second; out_bin_file.write(reinterpret_cast(&codenum), sizeof(code)); out_bin_file.write(reinterpret_cast(&filenum), sizeof(filenum)); - out_bin_file.write(reinterpret_cast(&funcnum), sizeof(funcnum)); + out_bin_file.write(reinterpret_cast(&func_or_line_num), sizeof(func_or_line_num)); out_bin_file.write(reinterpret_cast(&calls), sizeof(calls)); ++i; } ++filenum_itr; - if (code > 0) + if (max == 0) break; } ++code_itr; - if (code > 0); + if (max == 0); break; } @@ -88,7 +80,7 @@ inline uint64_t coverage_dump_funcnt(uint64_t code, uint32_t file_num, const cha out_bin_file.close(); uint64_t r = 0; - if(code_itr != funcnt_map.end()) + if(code_itr != cov_map.end()) r = code_itr->first; return r; } diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index e5a20811a06..08dd1f53517 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -126,7 +126,6 @@ class coverage_maps { coverage_maps() = default; }; - #define REGISTER_HOST_FUNCTION(NAME, ...) \ static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \ NAME##_registrator_impl() { \ @@ -135,36 +134,40 @@ class coverage_maps { inline static auto NAME##_registrator = NAME##_registrator_impl(); // code coverage API -REGISTER_HOST_FUNCTION(coverage_inc_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_inc_line_cnt) -REGISTER_HOST_FUNCTION(coverage_get_fun_cnt) -REGISTER_HOST_FUNCTION(coverage_get_line_cnt) -REGISTER_HOST_FUNCTION(coverage_dump_funcnt) -REGISTER_HOST_FUNCTION(coverage_reset) - -void interface::coverage_inc_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - eosio::coverage::coverage_inc_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); -} - -void interface::coverage_inc_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - eosio::coverage::coverage_inc_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); -} - -uint32_t interface::coverage_get_fun_cnt(uint64_t code, uint32_t file_num, uint32_t func_num) { - return eosio::coverage::coverage_get_fun_cnt(code, file_num, func_num, coverage_maps::instance().funcnt_map); -} - -uint32_t interface::coverage_get_line_cnt(uint64_t code, uint32_t file_num, uint32_t line_num) { - return eosio::coverage::coverage_get_line_cnt(code, file_num, line_num, coverage_maps::instance().linecnt_map); -} - -uint64_t interface::coverage_dump_funcnt(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append) { - return eosio::coverage::coverage_dump_funcnt(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); +REGISTER_HOST_FUNCTION(coverage_getinc) +REGISTER_HOST_FUNCTION(coverage_dump) + +uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { + if(inc) { + if (mode == 0) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + } else if (mode == 1) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + } + } + else { + if (mode == 0) { + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + } + else if (mode == 1) { + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + } + } + return 0; } -void interface::coverage_reset() { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); +uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { + if (reset) { + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); + return 0; + } + if (mode == 0) { + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + } + else if (mode == 1) { + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); + } } } // namespace eosio::chain::webassembly @@ -303,12 +306,8 @@ struct test_chain { { *control->get_protocol_feature_manager().get_builtin_digest( eosio::chain::builtin_protocol_feature_t::preactivate_feature) }); control->mutable_db().modify( control->mutable_db().get(), [&]( auto& ps ) { - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_fun_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_inc_line_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_fun_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_get_line_cnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump_funcnt" ); - eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_reset" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_getinc" ); + eosio::chain::add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "coverage_dump" ); } ); } } From 7cd129d9a46830fa903155f953913601235b2548 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Fri, 4 Feb 2022 11:14:44 -0500 Subject: [PATCH 28/33] remove improper semicolon in libraries/rodeos/include/eosio/coverage.hpp --- libraries/rodeos/include/eosio/coverage.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index 09b6dda4cbf..01cbc58e1e6 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -72,7 +72,7 @@ inline uint64_t coverage_dump(uint64_t code, uint32_t file_num, const char* file break; } ++code_itr; - if (max == 0); + if (max == 0) break; } From 8308aa1f3ede7152394fe754c14055af5182bb01 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Fri, 4 Feb 2022 12:38:55 -0500 Subject: [PATCH 29/33] fix eosio-tester/main.cpp return paths --- programs/eosio-tester/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 7798b0b1191..2e5a35a450d 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -155,7 +155,6 @@ uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::s if (reset) { coverage_maps::instance().funcnt_map.clear(); coverage_maps::instance().linecnt_map.clear(); - return 0; } if (mode == 0) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); @@ -163,6 +162,7 @@ uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::s else if (mode == 1) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } + return 0; } } // namespace eosio::chain::webassembly From 2e3d942770880902ff3c2caa18c8b2eea43506f5 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 7 Feb 2022 13:25:38 -0500 Subject: [PATCH 30/33] address PR feedback --- .../include/b1/rodeos/callbacks/coverage.hpp | 16 ++++--- libraries/rodeos/include/eosio/coverage.hpp | 18 +++++++ programs/eosio-tester/main.cpp | 48 ++++++++----------- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index cce214b6f4b..def08a00150 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -5,6 +5,7 @@ namespace b1::rodeos { +template class coverage_maps { public: static coverage_maps& instance() { @@ -16,10 +17,13 @@ class coverage_maps { cov_map_t funcnt_map; cov_map_t linecnt_map; + eosio::name T; private: coverage_maps() = default; }; +enum class coverage_mode = { func, line }; + struct coverage_state { }; @@ -29,9 +33,9 @@ struct coverage_callbacks { uint32_t coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { if(inc) { - if (mode == 0) { + if (mode == coverage_mode::func) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); - } else if (mode == 1) { + } else if (mode == coverage_mode::line) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } @@ -48,14 +52,14 @@ struct coverage_callbacks { uint64_t coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { if (reset) { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); + coverage_maps<"rodeos"_n>::instance().funcnt_map.clear(); + coverage_maps<"rodeos"_n>::instance().linecnt_map.clear(); } else if (mode == 0) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps<"rodeos"_n>::instance().funcnt_map); } else if (mode == 1) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps<"rodeos"_n>::instance().linecnt_map); } return 0; } diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index 01cbc58e1e6..d8b7b9b7a38 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -11,6 +11,24 @@ using cov_map_t = std::unordered_map +class coverage_maps { + public: + static coverage_maps& instance() { + static coverage_maps instance; + return instance; + } + coverage_maps(const coverage_maps&) = delete; + void operator=(const coverage_maps&) = delete; + + cov_map_t funcnt_map; + cov_map_t linecnt_map; + private: + coverage_maps() = default; +}; + +enum coverage_mode { func, line }; + inline void coverage_inc_cnt( uint64_t code, uint32_t file_num, uint32_t func_or_line_num, cov_map_t& cov_map) { auto& code_map = cov_map[code]; auto& cnt_map = code_map[file_num]; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 2e5a35a450d..866a7dff212 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -106,21 +106,6 @@ struct transaction_checktime_factory { // Defined here to keep it out of nodeos namespace eosio::chain::webassembly { -class coverage_maps { -public: - static coverage_maps& instance() { - static coverage_maps instance; - return instance; - } - coverage_maps(const coverage_maps&) = delete; - void operator=(const coverage_maps&) = delete; - - cov_map_t funcnt_map; - cov_map_t linecnt_map; -private: - coverage_maps() = default; -}; - #define REGISTER_HOST_FUNCTION(NAME, ...) \ static host_function_registrator<&interface::NAME, core_precondition, context_aware_check, ##__VA_ARGS__> \ NAME##_registrator_impl() { \ @@ -132,35 +117,42 @@ class coverage_maps { REGISTER_HOST_FUNCTION(coverage_getinc) REGISTER_HOST_FUNCTION(coverage_dump) +using eosio::coverage::coverage_maps; +using eosio::coverage::coverage_mode; + +constexpr auto TESTCHAIN_N = eosio::name{"testchain"}.value; + uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { + uint32_t r = 0; if(inc) { - if (mode == 0) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); - } else if (mode == 1) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + if (mode == coverage_mode::func) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + } else if (mode == coverage_mode::line) { + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } else { - if (mode == 0) { - return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + if (mode == coverage_mode::func) { + r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } - else if (mode == 1) { - return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + else if (mode == coverage_mode::line) { + r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } - return 0; + return r; } uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { if (reset) { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); + return 0; } if (mode == 0) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } else if (mode == 1) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; } From ad98dff59ba6a84eb3bbee4768db777cb3e91f88 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 7 Feb 2022 15:44:42 -0500 Subject: [PATCH 31/33] address PR feedback --- .../include/b1/rodeos/callbacks/coverage.hpp | 36 ++++++------------- libraries/rodeos/include/eosio/coverage.hpp | 5 ++- programs/eosio-tester/main.cpp | 18 +++++----- 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index def08a00150..c0de00f60a8 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -5,24 +5,10 @@ namespace b1::rodeos { -template -class coverage_maps { - public: - static coverage_maps& instance() { - static coverage_maps instance; - return instance; - } - coverage_maps(const coverage_maps&) = delete; - void operator=(const coverage_maps&) = delete; - - cov_map_t funcnt_map; - cov_map_t linecnt_map; - eosio::name T; - private: - coverage_maps() = default; -}; +using eosio::coverage::coverage_maps; +using eosio::coverage::coverage_mode; -enum class coverage_mode = { func, line }; +constexpr auto rodeos_n = eosio::name{"rodeos"}.value; struct coverage_state { }; @@ -34,17 +20,17 @@ struct coverage_callbacks { uint32_t coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { if(inc) { if (mode == coverage_mode::func) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } else if (mode == coverage_mode::line) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } else { if (mode == 0) { - return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } else if (mode == 1) { - return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } return 0; @@ -52,14 +38,14 @@ struct coverage_callbacks { uint64_t coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { if (reset) { - coverage_maps<"rodeos"_n>::instance().funcnt_map.clear(); - coverage_maps<"rodeos"_n>::instance().linecnt_map.clear(); + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); } else if (mode == 0) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps<"rodeos"_n>::instance().funcnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } else if (mode == 1) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps<"rodeos"_n>::instance().linecnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; } diff --git a/libraries/rodeos/include/eosio/coverage.hpp b/libraries/rodeos/include/eosio/coverage.hpp index d8b7b9b7a38..3816dd897e7 100644 --- a/libraries/rodeos/include/eosio/coverage.hpp +++ b/libraries/rodeos/include/eosio/coverage.hpp @@ -27,7 +27,10 @@ class coverage_maps { coverage_maps() = default; }; -enum coverage_mode { func, line }; +enum class coverage_mode : uint32_t { + func=0, + line=1 +}; inline void coverage_inc_cnt( uint64_t code, uint32_t file_num, uint32_t func_or_line_num, cov_map_t& cov_map) { auto& code_map = cov_map[code]; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 866a7dff212..32a1f15b37c 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -120,23 +120,23 @@ REGISTER_HOST_FUNCTION(coverage_dump) using eosio::coverage::coverage_maps; using eosio::coverage::coverage_mode; -constexpr auto TESTCHAIN_N = eosio::name{"testchain"}.value; +constexpr auto testchain_n = eosio::name{"testchain"}.value; uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { uint32_t r = 0; if(inc) { if (mode == coverage_mode::func) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } else if (mode == coverage_mode::line) { - eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } else { if (mode == coverage_mode::func) { - r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); + r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } else if (mode == coverage_mode::line) { - r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); + r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } return r; @@ -144,15 +144,15 @@ uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t f uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { if (reset) { - coverage_maps::instance().funcnt_map.clear(); - coverage_maps::instance().linecnt_map.clear(); + coverage_maps::instance().funcnt_map.clear(); + coverage_maps::instance().linecnt_map.clear(); return 0; } if (mode == 0) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } else if (mode == 1) { - return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); + return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; } From 284f4783ebceabe75fceb7492ef025e240256d0c Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 7 Feb 2022 16:10:14 -0500 Subject: [PATCH 32/33] address PR feedback --- libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp | 8 ++++---- programs/eosio-tester/main.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index c0de00f60a8..b50141b2603 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -26,10 +26,10 @@ struct coverage_callbacks { } } else { - if (mode == 0) { + if (mode == coverage_mode::func) { return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } - else if (mode == 1) { + else if (mode == coverage_mode::line) { return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } @@ -41,10 +41,10 @@ struct coverage_callbacks { coverage_maps::instance().funcnt_map.clear(); coverage_maps::instance().linecnt_map.clear(); } - else if (mode == 0) { + else if (mode == coverage_mode::func) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } - else if (mode == 1) { + else if (mode == coverage_mode::line) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 32a1f15b37c..98fc739ab3b 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -148,10 +148,10 @@ uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::s coverage_maps::instance().linecnt_map.clear(); return 0; } - if (mode == 0) { + if (mode == coverage_mode::func) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } - else if (mode == 1) { + else if (mode == coverage_mode::line) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; From 60b86017b4ab58d0e7220548bced92dce065e341 Mon Sep 17 00:00:00 2001 From: Patrick Raphael Date: Mon, 7 Feb 2022 16:53:36 -0500 Subject: [PATCH 33/33] use static_cast to fix compile errors --- .../include/b1/rodeos/callbacks/coverage.hpp | 14 ++++++++------ programs/eosio-tester/main.cpp | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp index b50141b2603..188ca0a9eec 100644 --- a/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp +++ b/libraries/rodeos/include/b1/rodeos/callbacks/coverage.hpp @@ -18,18 +18,19 @@ struct coverage_callbacks { Derived& derived() { return static_cast(*this); } uint32_t coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { + auto cov_mode = static_cast(mode); if(inc) { - if (mode == coverage_mode::func) { + if (cov_mode == coverage_mode::func) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); - } else if (mode == coverage_mode::line) { + } else if (cov_mode == coverage_mode::line) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } else { - if (mode == coverage_mode::func) { + if (cov_mode == coverage_mode::func) { return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } - else if (mode == coverage_mode::line) { + else if (cov_mode == coverage_mode::line) { return eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } @@ -37,14 +38,15 @@ struct coverage_callbacks { } uint64_t coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { + auto cov_mode = static_cast(mode); if (reset) { coverage_maps::instance().funcnt_map.clear(); coverage_maps::instance().linecnt_map.clear(); } - else if (mode == coverage_mode::func) { + else if (cov_mode == coverage_mode::func) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } - else if (mode == coverage_mode::line) { + else if (cov_mode == coverage_mode::line) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0; diff --git a/programs/eosio-tester/main.cpp b/programs/eosio-tester/main.cpp index 98fc739ab3b..ed1179ec129 100644 --- a/programs/eosio-tester/main.cpp +++ b/programs/eosio-tester/main.cpp @@ -124,18 +124,19 @@ constexpr auto testchain_n = eosio::name{"testchain"}.value; uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t func_or_line_num, uint32_t mode, bool inc) { uint32_t r = 0; + auto cov_mode = static_cast(mode); if(inc) { - if (mode == coverage_mode::func) { + if (cov_mode == coverage_mode::func) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); - } else if (mode == coverage_mode::line) { + } else if (cov_mode == coverage_mode::line) { eosio::coverage::coverage_inc_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } else { - if (mode == coverage_mode::func) { + if (cov_mode == coverage_mode::func) { r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().funcnt_map); } - else if (mode == coverage_mode::line) { + else if (cov_mode == coverage_mode::line) { r = eosio::coverage::coverage_get_cnt(code, file_num, func_or_line_num, coverage_maps::instance().linecnt_map); } } @@ -143,15 +144,16 @@ uint32_t interface::coverage_getinc(uint64_t code, uint32_t file_num, uint32_t f } uint64_t interface::coverage_dump(uint64_t code, uint32_t file_num, eosio::vm::span file_name, uint32_t max, bool append, uint32_t mode, bool reset) { + auto cov_mode = static_cast(mode); if (reset) { coverage_maps::instance().funcnt_map.clear(); coverage_maps::instance().linecnt_map.clear(); return 0; } - if (mode == coverage_mode::func) { + if (cov_mode == coverage_mode::func) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().funcnt_map); } - else if (mode == coverage_mode::line) { + else if (cov_mode == coverage_mode::line) { return eosio::coverage::coverage_dump(code, file_num, file_name.data(), file_name.size(), max, append, coverage_maps::instance().linecnt_map); } return 0;