Merge pull request #38 from ethereum/create-fn-search

"Create" function name search heuristic
This commit is contained in:
Paweł Bylica 2018-06-26 18:17:04 +02:00 committed by GitHub
commit 5ee6915250
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 29 deletions

View File

@ -99,7 +99,7 @@ WARN_LOGFILE =
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the input files # Configuration options related to the input files
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
INPUT = include/evmc/evmc.h INPUT = include/evmc/
INPUT_ENCODING = UTF-8 INPUT_ENCODING = UTF-8
FILE_PATTERNS = FILE_PATTERNS =
RECURSIVE = NO RECURSIVE = NO
@ -264,7 +264,7 @@ EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES SEARCH_INCLUDES = YES
INCLUDE_PATH = INCLUDE_PATH =
INCLUDE_FILE_PATTERNS = INCLUDE_FILE_PATTERNS =
PREDEFINED = PREDEFINED = EVMC_DOCUMENTATION=1
EXPAND_AS_DEFINED = EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES SKIP_FUNCTION_MACROS = YES
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
# EVMC -- Ethereum Client-VM Connector API # EVMC: Ethereum Client-VM Connector API
# Copyright 2018 Pawel Bylica. # Copyright 2018 Pawel Bylica.
# Licensed under the MIT License. See the LICENSE file. # Licensed under the MIT License. See the LICENSE file.
@ -6,9 +6,16 @@ include(GNUInstallDirs)
add_library(evmc-examplevm examplevm.c) add_library(evmc-examplevm examplevm.c)
target_link_libraries(evmc-examplevm PRIVATE evmc) target_link_libraries(evmc-examplevm PRIVATE evmc)
set_target_properties(evmc-examplevm PROPERTIES DEBUG_POSTFIX "") set_target_properties(
evmc-examplevm PROPERTIES
DEBUG_POSTFIX ""
RUNTIME_OUTPUT_DIRECTORY ..
LIBRARY_OUTPUT_DIRECTORY ..
)
install(TARGETS evmc-examplevm install(
TARGETS evmc-examplevm
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

View File

@ -11,7 +11,7 @@ struct examplevm
int verbose; int verbose;
}; };
static void evmc_destroy(struct evmc_instance* evm) static void destroy(struct evmc_instance* evm)
{ {
free(evm); free(evm);
} }
@ -19,7 +19,7 @@ static void evmc_destroy(struct evmc_instance* evm)
/// Example options. /// Example options.
/// ///
/// VMs are allowed to omit this function implementation. /// VMs are allowed to omit this function implementation.
int evmc_set_option(struct evmc_instance* instance, char const* name, char const* value) static int set_option(struct evmc_instance* instance, char const* name, char const* value)
{ {
struct examplevm* vm = (struct examplevm*)instance; struct examplevm* vm = (struct examplevm*)instance;
if (strcmp(name, "verbose") == 0) if (strcmp(name, "verbose") == 0)
@ -34,7 +34,7 @@ int evmc_set_option(struct evmc_instance* instance, char const* name, char const
return 0; return 0;
} }
static void evmc_release_result(struct evmc_result const* result) static void release_result(struct evmc_result const* result)
{ {
(void)result; (void)result;
} }
@ -103,7 +103,7 @@ static struct evmc_result execute(struct evmc_instance* instance,
return ret; return ret;
} }
ret.release = evmc_release_result; ret.release = release_result;
ret.status_code = EVMC_FAILURE; ret.status_code = EVMC_FAILURE;
ret.gas_left = 0; ret.gas_left = 0;
@ -119,9 +119,9 @@ struct evmc_instance* evmc_create_examplevm()
.abi_version = EVMC_ABI_VERSION, .abi_version = EVMC_ABI_VERSION,
.name = "examplevm", .name = "examplevm",
.version = "0.0.0", .version = "0.0.0",
.destroy = evmc_destroy, .destroy = destroy,
.execute = execute, .execute = execute,
.set_option = evmc_set_option, .set_option = set_option,
}; };
struct examplevm* vm = calloc(1, sizeof(struct examplevm)); struct examplevm* vm = calloc(1, sizeof(struct examplevm));
struct evmc_instance* interface = &vm->instance; struct evmc_instance* interface = &vm->instance;

View File

@ -732,16 +732,24 @@ struct evmc_instance
/* END Python CFFI declarations */ /* END Python CFFI declarations */
#if EVMC_DOCUMENTATION
/** /**
* Example of a function creating an instance of an example EVM implementation. * Example of a function creating an instance of an example EVM implementation.
* *
* Each EVM implementation MUST provide a function returning an EVM instance. * Each EVM implementation MUST provide a function returning an EVM instance.
* The function SHOULD be named `evmc_create_<vm-name>(void)`. * The function SHOULD be named `evmc_create_<vm-name>(void)`. If the VM name contains hyphens
* replaces them with underscores in the function names.
* *
* @return EVM instance or NULL indicating instance creation failure. * @par Binaries naming convention
* For VMs distributed as shared libraries, the name of the library SHOULD match the VM name.
* The convetional library filename prefixes and extensions SHOULD be ignored by the Client.
* For example, the shared library with the "beta-interpreter" implementation may be named
* `libbeta-interpreter.so`.
* *
* struct evmc_instance* evmc_create_examplevm(void); * @return EVM instance or NULL indicating instance creation failure.
*/ */
struct evmc_instance* evmc_create_examplevm(void);
#endif
#if __cplusplus #if __cplusplus
} }

View File

@ -8,5 +8,5 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#define EVMC_EXPORT __declspec(dllexport) #define EVMC_EXPORT __declspec(dllexport)
#else #else
#define EVMC_EXPORT __attribute__ ((visibility ("default"))) #define EVMC_EXPORT __attribute__((visibility("default")))
#endif #endif

View File

@ -8,6 +8,7 @@ hunter_add_package(Boost COMPONENTS program_options filesystem system)
find_package(Boost CONFIG REQUIRED program_options filesystem system) find_package(Boost CONFIG REQUIRED program_options filesystem system)
add_executable(evmc-vmtester vmtester.hpp vmtester.cpp tests.cpp) add_executable(evmc-vmtester vmtester.hpp vmtester.cpp tests.cpp)
set_target_properties(evmc-vmtester PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
target_link_libraries( target_link_libraries(
evmc-vmtester evmc-vmtester

View File

@ -35,6 +35,38 @@ evmc_instance* get_vm_instance()
return vm.get(); return vm.get();
} }
std::vector<std::string> get_vm_names(const fs::path path)
{
std::vector<std::string> names;
// Get the filename without extension.
auto name = path.stem().string();
// Skip the optional library name prefix.
const std::string lib_name_prefix{"lib"};
if (name.find(lib_name_prefix) == 0)
name = name.substr(lib_name_prefix.size());
size_t hyphen_pos = 0;
const std::string hyphen{"-"};
if ((hyphen_pos = name.find(hyphen)) != std::string::npos)
{
// Replace the hyphen with underscore.
name.replace(hyphen_pos, hyphen.size(), "_");
names.emplace_back(name);
// Also add the name without the hyphen-separated prefix.
names.emplace_back(name.substr(hyphen_pos + hyphen.size()));
}
else
{
// Add the filename as the name.
names.emplace_back(std::move(name));
}
return names;
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
try try
@ -65,23 +97,37 @@ int main(int argc, char* argv[])
opts::notify(variables_map); opts::notify(variables_map);
auto symbols = dll::library_info{vm_path}.symbols(); std::cout << "Testing " << vm_path.filename().string() << "\n"
auto it = std::find_if(symbols.begin(), symbols.end(), [](const std::string& symbol) { << "Path: " << vm_path.string() << "\n";
return symbol.find("evmc_create_") == 0;
}); for (auto&& name : get_vm_names(vm_path))
if (it == symbols.end()) {
try
{
const std::string create_fn_name = "evmc_create_" + name;
std::cout << "Seeking `" << create_fn_name << "`... ";
create_fn = dll::import<evmc_create_fn>(vm_path, create_fn_name);
std::cout << "found.\n";
break;
}
catch (boost::system::system_error& err)
{
using namespace boost::system;
const error_code windows_error{127, system_category()};
constexpr auto posix_error = errc::invalid_seek;
if (err.code() != posix_error && err.code() != windows_error)
throw; // Error other than "symbol not found".
std::cout << "not found.\n";
}
}
if (!create_fn)
{ {
std::cerr << "EVMC create function not found in " << vm_path.string() << "\n"; std::cerr << "EVMC create function not found in " << vm_path.string() << "\n";
return 2; return 2;
} }
const std::string& create_fn_name = *it;
std::cout << "Testing " << vm_path.filename().string() << "\n "
<< "Path: " << vm_path.string() << "\n "
<< "Create function: " << create_fn_name << "()\n\n";
create_fn = dll::import<evmc_create_fn>(vm_path, create_fn_name);
std::cout << std::endl;
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
catch (const std::exception& ex) catch (const std::exception& ex)