Skip to content

Commit

Permalink
loader: Add Windows support
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Jul 5, 2018
1 parent 37f5f33 commit 0d6ce13
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 28 deletions.
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ build_script: |
cmake --build . --config %CONFIGURATION% --target install
after_build: |
C:\projects\evmc\build\test\Release\evmc-test.exe
cd C:\projects\evmc\build\test
Release\evmc-test.exe
C:\install\bin\evmc-vmtester.exe C:\install\bin\evmc-examplevm.dll
4 changes: 1 addition & 3 deletions lib/loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ add_library(
add_library(evmc::loader ALIAS loader)
set_target_properties(loader PROPERTIES OUTPUT_NAME evmc-loader)
target_include_directories(loader PUBLIC $<BUILD_INTERFACE:${include_dir}>$<INSTALL_INTERFACE:include>)
if(CMAKE_DL_LIBS)
target_link_libraries(loader INTERFACE ${CMAKE_DL_LIBS})
endif()
target_link_libraries(loader INTERFACE ${CMAKE_DL_LIBS})

install(TARGETS loader EXPORT evmcTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
42 changes: 32 additions & 10 deletions lib/loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,34 @@
#include <stdint.h>
#include <string.h>

#if _WIN32
#include <Windows.h>
#define DLL_HANDLE HMODULE
#define DLL_OPEN(filename) LoadLibrary(filename)
#define DLL_CLOSE(handle) FreeLibrary(handle)
#define DLL_GET_CREATE_FN(handle, name) (evmc_create_fn) GetProcAddress(handle, name)
#define HAVE_STRCPY_S 1
#else
#include <dlfcn.h>
#define DLL_HANDLE void*
#define DLL_OPEN(filename) dlopen(filename, RTLD_LAZY)
#define DLL_CLOSE(handle) dlclose(handle)
#define DLL_GET_CREATE_FN(handle, name) (evmc_create_fn)(uintptr_t) dlsym(handle, name)
#define HAVE_STRCPY_S 0
#endif

#define PATH_MAX_LENGHT 4096

#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
#if !HAVE_STRCPY_S
static void strcpy_s(char* dest, size_t destsz, const char* src)
{
size_t len = strlen(src);
if (len > destsz - 1)
len = destsz - 1;
memcpy(dest, src, len);
dest[len] = 0;
}
#endif

typedef struct evmc_instance* (*evmc_create_fn)();

Expand All @@ -34,7 +57,7 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
goto exit;
}

void* handle = dlopen(filename, RTLD_LAZY);
DLL_HANDLE handle = DLL_OPEN(filename);
if (!handle)
{
ec = EVMC_ERRC_CANNOT_OPEN;
Expand All @@ -44,7 +67,7 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
const char prefix[] = "evmc_create_";
const size_t prefix_length = strlen(prefix);
char name[sizeof(prefix) + PATH_MAX_LENGHT];
strcpy(name, prefix);
strcpy_s(name, sizeof(name), prefix);

const char* sep_pos = strrchr(filename, '/');
const char* name_pos = sep_pos ? sep_pos + 1 : filename;
Expand All @@ -54,7 +77,7 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
if (strncmp(name_pos, lib_prefix, lib_prefix_length) == 0)
name_pos += lib_prefix_length;

strncpy(name + prefix_length, name_pos, PATH_MAX_LENGHT);
strcpy_s(name + prefix_length, PATH_MAX_LENGHT, name_pos);

char* ext_pos = strrchr(name, '.');
if (ext_pos)
Expand All @@ -64,26 +87,25 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
while ((dash_pos = strchr(dash_pos, '-')) != NULL)
*dash_pos++ = '_';

const void* symbol = dlsym(handle, name);
if (!symbol)
evmc_create_fn create_fn = DLL_GET_CREATE_FN(handle, name);
if (!create_fn)
{
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);
symbol = dlsym(handle, name);
create_fn = DLL_GET_CREATE_FN(handle, name);
}
}

if (symbol)
if (create_fn)
{
evmc_create_fn create_fn = (evmc_create_fn)(uintptr_t)symbol;
instance = create_fn();
}
else
{
dlclose(handle);
DLL_CLOSE(handle);
ec = EVMC_ERRC_SYMBOL_NOT_FOUND;
}

Expand Down
17 changes: 9 additions & 8 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Licensed under the MIT License. See the LICENSE file.

add_library(vm-mock SHARED vm_mock.c)
target_link_libraries(vm-mock PRIVATE evmc)

if(UNIX)
set(cmd create_symlink)
Expand All @@ -12,14 +13,14 @@ endif()

add_custom_command(
TARGET vm-mock POST_BUILD
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> ${CMAKE_SHARED_LIBRARY_PREFIX}aaa${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> double_prefix_aaa.evm
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> double-prefix-aaa.evm
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> eee-bbb.dll
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> ${CMAKE_SHARED_LIBRARY_PREFIX}eee1${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> eee2${CMAKE_SHARED_LIBRARY_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> ${CMAKE_SHARED_LIBRARY_PREFIX}eee3
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE_NAME:vm-mock> eee4
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> libaaa.so
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> double_prefix_aaa.evm
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> double-prefix-aaa.evm
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> eee-bbb.dll
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> libeee1.so
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> eee2.so
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> libeee3.x
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> eee4
COMMAND ${CMAKE_COMMAND} -E ${cmd} $<TARGET_FILE:vm-mock> ../aaa.evm
COMMAND ${CMAKE_COMMAND} -E touch empty.file
)
Expand Down
13 changes: 9 additions & 4 deletions test/unittests/test_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ TEST(loader, eee_bbb)
EXPECT_EQ(x, 0xeeebbb);
}

TEST(loader, DISABLED_nextto)
#if _WIN32
TEST(loader, nextto)
{
// FIXME: Does not work because dlopen searches only system paths.
// On Unix dlopen searches for system libs when the path does not contain "/".

auto path = "aaa.evm";

Expand All @@ -122,6 +123,7 @@ TEST(loader, DISABLED_nextto)
x = (uintptr_t)evmc_load(path, nullptr);
EXPECT_EQ(x, 0xaaa);
}
#endif

TEST(loader, eee1)
{
Expand Down Expand Up @@ -151,7 +153,7 @@ TEST(loader, eee2)

TEST(loader, eee3)
{
auto path = "unittests/libeee3";
auto path = "unittests/libeee3.x";

evmc_loader_error_code ec;
auto x = evmc_load(path, &ec);
Expand All @@ -162,8 +164,10 @@ TEST(loader, eee3)
EXPECT_EQ(x, nullptr);
}

#if !_WIN32
TEST(loader, eee4)
{
// Windows is not loading DLLs without extensions.
auto path = "unittests/eee4";

evmc_loader_error_code ec;
Expand All @@ -173,4 +177,5 @@ TEST(loader, eee4)

x = evmc_load(path, nullptr);
EXPECT_EQ(x, nullptr);
}
}
#endif
6 changes: 4 additions & 2 deletions test/unittests/vm_mock.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
* Licensed under the MIT License. See the LICENSE file.
*/

void* evmc_create_aaa()
#include <evmc/utils.h>

EVMC_EXPORT void* evmc_create_aaa()
{
return (void*)0xaaa;
}

void* evmc_create_eee_bbb()
EVMC_EXPORT void* evmc_create_eee_bbb()
{
return (void*)0xeeebbb;
}

0 comments on commit 0d6ce13

Please sign in to comment.