Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loader: Expose DLL load error #230

Merged
merged 1 commit into from
Apr 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion bindings/go/evmc/evmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,13 @@ func Load(filename string) (instance *Instance, err error) {
case C.EVMC_LOADER_SUCCESS:
instance = &Instance{handle}
case C.EVMC_LOADER_CANNOT_OPEN:
err = fmt.Errorf("evmc loader: cannot open %s", filename)
optionalErrMsg := C.evmc_last_error_msg()
if optionalErrMsg != nil {
msg := C.GoString(optionalErrMsg)
err = fmt.Errorf("evmc loader: %s", msg)
chfast marked this conversation as resolved.
Show resolved Hide resolved
} else {
err = fmt.Errorf("evmc loader: cannot open %s", filename)
}
case C.EVMC_LOADER_SYMBOL_NOT_FOUND:
err = fmt.Errorf("evmc loader: the EVMC create function not found in %s", filename)
case C.EVMC_LOADER_INVALID_ARGUMENT:
Expand Down
17 changes: 15 additions & 2 deletions include/evmc/loader.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* EVMC: Ethereum Client-VM Connector API.
* Copyright 2018 The EVMC Authors.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
* Copyright 2019 The EVMC Authors.
* Licensed under the Apache License, Version 2.0.
*/

/**
Expand Down Expand Up @@ -103,6 +103,19 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
struct evmc_instance* evmc_load_and_create(const char* filename,
enum evmc_loader_error_code* error_code);

/**
* Returns the human-readable message describing the most recent error
* that occurred in EVMC loading.
*
* In case any loading function returned ::EVMC_LOADER_SUCCESS this function always returns NULL.
* In case of error code other than success returned, this function MAY return the error message.
* This function is not thread-safe.
*
* @return Error message or NULL if no additional information is available.
* The returned pointer MUST NOT be freed by the caller.
*/
const char* evmc_last_error_msg();

#if __cplusplus
}
#endif
Expand Down
14 changes: 14 additions & 0 deletions lib/loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ static void strcpy_s(char* dest, size_t destsz, const char* src)
}
#endif

static const char* last_error_msg = NULL;


evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* error_code)
{
last_error_msg = NULL; // Reset last error.
enum evmc_loader_error_code ec = EVMC_LOADER_SUCCESS;
evmc_create_fn create_fn = NULL;

Expand All @@ -66,6 +69,11 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
DLL_HANDLE handle = DLL_OPEN(filename);
if (!handle)
{
#if !defined(EVMC_LOADER_MOCK) && !_WIN32
// If available, get the error message from dlerror().
last_error_msg = dlerror();
#endif

ec = EVMC_LOADER_CANNOT_OPEN;
goto exit;
}
Expand Down Expand Up @@ -130,9 +138,15 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro
return create_fn;
}

const char* evmc_last_error_msg()
{
return last_error_msg;
}

struct evmc_instance* evmc_load_and_create(const char* filename,
enum evmc_loader_error_code* error_code)
{
// First load the DLL. This also resets the last_error_msg;
evmc_create_fn create_fn = evmc_load(filename, error_code);

if (!create_fn)
Expand Down
2 changes: 1 addition & 1 deletion test/vmtester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ add_test(NAME vmtester/help COMMAND evmc-vmtester --version --help)
set_tests_properties(vmtester/help PROPERTIES PASS_REGULAR_EXPRESSION "Usage:")

add_test(NAME vmtester/nonexistingvm COMMAND evmc-vmtester nonexistingvm)
set_tests_properties(vmtester/nonexistingvm PROPERTIES PASS_REGULAR_EXPRESSION "Cannot open")
set_tests_properties(vmtester/nonexistingvm PROPERTIES PASS_REGULAR_EXPRESSION "[Cc]annot open")

add_test(NAME vmtester/noarg COMMAND evmc-vmtester)
set_tests_properties(vmtester/noarg PROPERTIES PASS_REGULAR_EXPRESSION "is required")
Expand Down
8 changes: 7 additions & 1 deletion test/vmtester/vmtester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ int main(int argc, char* argv[])
case EVMC_LOADER_SUCCESS:
break;
case EVMC_LOADER_CANNOT_OPEN:
std::cerr << "Cannot open " << evmc_module << "\n";
{
const auto error = evmc_last_error_msg();
if (error)
std::cerr << error << "\n";
else
std::cerr << "Cannot open " << evmc_module << "\n";
return static_cast<int>(ec);
}
case EVMC_LOADER_SYMBOL_NOT_FOUND:
std::cerr << "EVMC create function not found in " << evmc_module << "\n";
return static_cast<int>(ec);
Expand Down