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