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 }