diff --git a/CHANGELOG.md b/CHANGELOG.md index 60083406a..0e000e9d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [6.0.0-dev] - unreleased +- Improved: [[#119](https://github.com/ethereum/evmc/pull/119)] + EVMC loader symbol searching has been generalized. + ## [5.2.0] - 2018-08-28 - Feature: [[#81](https://github.com/ethereum/evmc/pull/81)] diff --git a/include/evmc/loader.h b/include/evmc/loader.h index b6492635f..c9ff5090c 100644 --- a/include/evmc/loader.h +++ b/include/evmc/loader.h @@ -60,15 +60,16 @@ enum evmc_loader_error_code * "libexample-interpreter.so", * - the "lib" prefix and file extension are stripped from the name: * "example-interpreter" - * - all "-" are replaced with "_" to construct _full name_: + * - all "-" are replaced with "_" to construct _base name_: * "example_interpreter", - * - the _full name_ is split by "_" char and the last item is taken to form the _short name_: - * "interpreter", - * - the name "evmc_create_" + _full name_ is checked in the library: + * - the function name "evmc_create_" + _base name_ is searched in the library: * "evmc_create_example_interpreter", - * - then, the name "evmc_create_" + _short name_ is checked in the library: - * "evmc_create_interpreter". - * - lastly, the name "evmc_create" is checked in the library + * - if function not found, the _base name_ is shorten by skipping the first word separated by "_": + * "interpreter", + * - then, the function of the shorter name "evmc_create_" + _base name_ is searched in the library: + * "evmc_create_interpreter", + * - the name shortening continues until a function is found or the name cannot be shorten more, + * - lastly, when no function found, the function name "evmc_create" is searched in the library. * * If the create function is found in the library, the pointer to the function is returned. * Otherwise, the ::EVMC_LOADER_SYMBOL_NOT_FOUND error code is signaled and NULL is returned. diff --git a/lib/loader/loader.c b/lib/loader/loader.c index 76abd9061..12b7407b8 100644 --- a/lib/loader/loader.c +++ b/lib/loader/loader.c @@ -69,8 +69,8 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro // Create name buffer with the prefix. const char prefix[] = "evmc_create_"; const size_t prefix_length = strlen(prefix); - char name[sizeof(prefix) + PATH_MAX_LENGTH]; - strcpy_s(name, sizeof(name), prefix); + char prefixed_name[sizeof(prefix) + PATH_MAX_LENGTH]; + strcpy_s(prefixed_name, sizeof(prefixed_name), prefix); // Find filename in the path. const char* sep_pos = strrchr(filename, '/'); @@ -87,30 +87,28 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro if (strncmp(name_pos, lib_prefix, lib_prefix_length) == 0) name_pos += lib_prefix_length; - strcpy_s(name + prefix_length, PATH_MAX_LENGTH, name_pos); + char* base_name = prefixed_name + prefix_length; + strcpy_s(base_name, PATH_MAX_LENGTH, name_pos); // Trim the file extension. - char* ext_pos = strrchr(name, '.'); + char* ext_pos = strrchr(prefixed_name, '.'); if (ext_pos) *ext_pos = 0; // Replace all "-" with "_". - char* dash_pos = name; + char* dash_pos = base_name; while ((dash_pos = strchr(dash_pos, '-')) != NULL) *dash_pos++ = '_'; - // Search for the "full name" based function name. - create_fn = DLL_GET_CREATE_FN(handle, name); - if (!create_fn) + // Search for the built function name. + while ((create_fn = DLL_GET_CREATE_FN(handle, prefixed_name)) == NULL) { - // Try the "short name" based function name. - const char* short_name_pos = strrchr(name, '_'); - if (short_name_pos) - { - short_name_pos += 1; - memmove(name + prefix_length, short_name_pos, strlen(short_name_pos) + 1); - create_fn = DLL_GET_CREATE_FN(handle, name); - } + // Shorten the base name by skipping the `word_` segment. + const char* shorter_name_pos = strchr(base_name, '_'); + if (!shorter_name_pos) + break; + + memmove(base_name, shorter_name_pos + 1, strlen(shorter_name_pos) + 1); } if (!create_fn)