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 }