1 /** 2 * Dynamically Loaded Object 3 * 4 * Copyright: 5 * (C) 2010 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.utils.dyn_load.dyn_load; 12 //todo : Mac OSX 13 import std.exception; 14 import std..string : toStringz, fromStringz; 15 version(linux) 16 import core.sys.linux.dlfcn; 17 version(Windows) 18 import core.sys.windows.windows; 19 20 void raiseRuntimeLoaderException(in string lib_name, string msg) 21 { 22 throw new Exception("Failed to load " ~ lib_name ~ ": " ~ (msg ? msg : "Unknown error")); 23 } 24 25 /** 26 * Represents a DLL or shared object 27 */ 28 class DynamicallyLoadedLibrary 29 { 30 public: 31 /** 32 * Load a DLL (or fail with an exception) 33 * Params: 34 * library = name or path to a library 35 * 36 * Notes: If you don't use a full path, the search order will be defined 37 * by whatever the system linker does by default. Always using fully 38 * qualified pathnames can help prevent code injection attacks (eg 39 * via manipulation of LD_LIBRARY_PATH on Linux) 40 */ 41 this(in string library) 42 { 43 lib_name = library; 44 45 version(linux) { 46 lib = dlopen(lib_name.toStringz, RTLD_LAZY); 47 48 if (!lib) 49 raiseRuntimeLoaderException(lib_name, cast(string)fromStringz(dlerror())); 50 51 } 52 version(Windows) { 53 54 lib = LoadLibraryA(lib_name.toStringz); 55 56 if (!lib) 57 raiseRuntimeLoaderException(lib_name, "LoadLibrary failed"); 58 } 59 60 if (!lib) 61 raiseRuntimeLoaderException(lib_name, "Dynamic load not supported"); 62 } 63 64 /** 65 * Unload the DLL 66 * Notes: 67 * Any pointers returned by resolve()/resolveSymbol() 68 * should not be used after this destructor runs. 69 */ 70 ~this() 71 { 72 version(linux) 73 dlclose(lib); 74 version(Windows) 75 FreeLibrary(cast(HMODULE)lib); 76 } 77 78 /** 79 * Load a symbol (or fail with an exception) 80 * Params: 81 * symbol = names the symbol to load 82 * Returns: address of the loaded symbol 83 */ 84 void* resolveSymbol(in string symbol) 85 { 86 void* addr = null; 87 88 version(linux) 89 addr = dlsym(lib, symbol.toStringz); 90 version(Windows) 91 addr = cast(void*)(GetProcAddress(cast(HMODULE)lib, symbol.toStringz)); 92 if (!addr) 93 throw new Exception("Failed to resolve symbol " ~ symbol ~ " in " ~ lib_name); 94 95 return addr; 96 } 97 98 /** 99 * Convenience function for casting symbol to the right type 100 * Params: 101 * symbol = names the symbol to load 102 * Returns: address of the loaded symbol 103 */ 104 T resolve(T)(in string symbol) 105 { 106 return cast(T)(resolveSymbol(symbol)); 107 } 108 109 private: 110 string lib_name; 111 void* lib; 112 }