1 /* Distributed under the OSI-approved BSD 3-Clause License.
2 See https://cmake.org/licensing#kwsys for details. */
3 #if defined(_WIN32)
4 # define NOMINMAX // hide min,max to not conflict with <limits>
5 #endif
6
7 #include <DynamicLoader.hxx>
8
9 #if defined(__hpux)
10 # include <dl.h>
11
OpenLibrary(const std::string & libname)12 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
13 const std::string& libname)
14 {
15 return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
16 }
17
CloseLibrary(DynamicLoader::LibraryHandle lib)18 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
19 {
20 if (!lib) {
21 return 0;
22 }
23 return !shl_unload(lib);
24 }
25
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)26 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
27 DynamicLoader::LibraryHandle lib, const std::string& sym)
28 {
29 void* addr;
30 int status;
31
32 /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
33 * TYPE_DATA Look for a symbol in the data segment (for example,
34 * variables).
35 * TYPE_UNDEFINED Look for any symbol.
36 */
37 status = shl_findsym(&lib, sym.c_str(), TYPE_UNDEFINED, &addr);
38 void* result = (status < 0) ? (void*)0 : addr;
39
40 // Hack to cast pointer-to-data to pointer-to-function.
41 return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
42 }
43
44 #elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
45 # include <mach-o/dyld.h>
46
OpenLibrary(const std::string & libname)47 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
48 const std::string& libname)
49 {
50 NSObjectFileImageReturnCode rc;
51 NSObjectFileImage image = 0;
52
53 rc = NSCreateObjectFileImageFromFile(libname.c_str(), &image);
54 // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
55 if (rc != NSObjectFileImageSuccess) {
56 return 0;
57 }
58 NSModule handle = NSLinkModule(image, libname.c_str(),
59 NSLINKMODULE_OPTION_BINDNOW |
60 NSLINKMODULE_OPTION_RETURN_ON_ERROR);
61 NSDestroyObjectFileImage(image);
62 return handle;
63 }
64
CloseLibrary(DynamicLoader::LibraryHandle lib)65 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
66 {
67 bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
68 return success;
69 }
70
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)71 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
72 DynamicLoader::LibraryHandle lib, const std::string& sym)
73 {
74 void* result = 0;
75 // Need to prepend symbols with '_' on Apple-gcc compilers
76 std::string rsym = '_' + sym;
77
78 NSSymbol symbol = NSLookupSymbolInModule(lib, rsym.c_str());
79 if (symbol) {
80 result = NSAddressOfSymbol(symbol);
81 }
82
83 // Hack to cast pointer-to-data to pointer-to-function.
84 return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
85 }
86
87 #elif defined(_WIN32) && !defined(__CYGWIN__)
88 # include <windows.h>
89
90 # include <stdio.h>
91
OpenLibrary(const std::string & libname)92 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
93 const std::string& libname)
94 {
95 DynamicLoader::LibraryHandle lh;
96 int length = MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, NULL, 0);
97 wchar_t* wchars = new wchar_t[length + 1];
98 wchars[0] = '\0';
99 MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, wchars, length);
100 lh = LoadLibraryW(wchars);
101 delete[] wchars;
102 return lh;
103 }
104
CloseLibrary(DynamicLoader::LibraryHandle lib)105 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
106 {
107 return (int)FreeLibrary(lib);
108 }
109
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)110 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
111 DynamicLoader::LibraryHandle lib, const std::string& sym)
112 {
113 void* result;
114 # if defined(__BORLANDC__) || defined(__WATCOMC__)
115 // Need to prepend symbols with '_'
116 std::string ssym = '_' + sym;
117 const char* rsym = ssym.c_str();
118 # else
119 const char* rsym = sym.c_str();
120 # endif
121 result = (void*)GetProcAddress(lib, rsym);
122 // Hack to cast pointer-to-data to pointer-to-function.
123 # ifdef __WATCOMC__
124 return *(DynamicLoader::SymbolPointer*)(&result);
125 # else
126 return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
127 # endif
128 }
129
130 #elif defined(__BEOS__)
131 # include <be/kernel/image.h>
132 # include <be/support/Errors.h>
133
134 static image_id last_dynamic_err = B_OK;
135
OpenLibrary(const std::string & libname)136 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
137 const std::string& libname)
138 {
139 // image_id's are integers, errors are negative. Add one just in case we
140 // get a valid image_id of zero (is that even possible?).
141 image_id rc = load_add_on(libname.c_str());
142 if (rc < 0) {
143 last_dynamic_err = rc;
144 return 0;
145 }
146
147 return rc + 1;
148 }
149
CloseLibrary(DynamicLoader::LibraryHandle lib)150 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
151 {
152 if (!lib) {
153 last_dynamic_err = B_BAD_VALUE;
154 return 0;
155 } else {
156 // The function dlclose() returns 0 on success, and non-zero on error.
157 status_t rc = unload_add_on(lib - 1);
158 if (rc != B_OK) {
159 last_dynamic_err = rc;
160 return 0;
161 }
162 }
163
164 return 1;
165 }
166
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)167 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
168 DynamicLoader::LibraryHandle lib, const std::string& sym)
169 {
170 // Hack to cast pointer-to-data to pointer-to-function.
171 union
172 {
173 void* pvoid;
174 DynamicLoader::SymbolPointer psym;
175 } result;
176
177 result.psym = NULL;
178
179 if (!lib) {
180 last_dynamic_err = B_BAD_VALUE;
181 } else {
182 // !!! FIXME: BeOS can do function-only lookups...does this ever
183 // !!! FIXME: actually _want_ a data symbol lookup, or was this union
184 // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
185 status_t rc =
186 get_image_symbol(lib - 1, sym.c_str(), B_SYMBOL_TYPE_ANY, &result.pvoid);
187 if (rc != B_OK) {
188 last_dynamic_err = rc;
189 result.psym = NULL;
190 }
191 }
192 return result.psym;
193 }
194
195 #elif defined(__MINT__)
196 # define _GNU_SOURCE /* for program_invocation_name */
197 # include <dld.h>
198 # include <errno.h>
199 # include <malloc.h>
200
OpenLibrary(const std::string & libname)201 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
202 const std::string& libname)
203 {
204 char* name = (char*)calloc(1, libname.size() + 1);
205 dld_init(program_invocation_name);
206 strncpy(name, libname.c_str(), libname.size());
207 dld_link(libname.c_str());
208 return (void*)name;
209 }
210
CloseLibrary(DynamicLoader::LibraryHandle lib)211 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
212 {
213 dld_unlink_by_file((char*)lib, 0);
214 free(lib);
215 return 0;
216 }
217
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)218 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
219 DynamicLoader::LibraryHandle lib, const std::string& sym)
220 {
221 // Hack to cast pointer-to-data to pointer-to-function.
222 union
223 {
224 void* pvoid;
225 DynamicLoader::SymbolPointer psym;
226 } result;
227 result.pvoid = dld_get_symbol(sym.c_str());
228 return result.psym;
229 }
230
231 #else
232 # include <dlfcn.h>
233
OpenLibrary(const std::string & libname)234 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
235 const std::string& libname)
236 {
237 return dlopen(libname.c_str(), RTLD_LAZY);
238 }
239
CloseLibrary(DynamicLoader::LibraryHandle lib)240 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
241 {
242 if (lib) {
243 // The function dlclose() returns 0 on success, and non-zero on error.
244 return !dlclose(lib);
245 }
246 // else
247 return 0;
248 }
249
GetSymbolAddress(DynamicLoader::LibraryHandle lib,const std::string & sym)250 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
251 DynamicLoader::LibraryHandle lib, const std::string& sym)
252 {
253 // Hack to cast pointer-to-data to pointer-to-function.
254 union
255 {
256 void* pvoid;
257 DynamicLoader::SymbolPointer psym;
258 } result;
259 result.pvoid = dlsym(lib, sym.c_str());
260 return result.psym;
261 }
262
263 #endif
264