DynamicLoader.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
  5. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  8. PURPOSE. See the above copyright notices for more information.
  9. =========================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(DynamicLoader.hxx)
  12. #include KWSYS_HEADER(Configure.hxx)
  13. // Work-around CMake dependency scanning limitation. This must
  14. // duplicate the above list of headers.
  15. #if 0
  16. # include "DynamicLoader.hxx.in"
  17. # include "Configure.hxx.in"
  18. #endif
  19. // This file is actually 3 different implementations.
  20. // 1. HP machines which uses shl_load
  21. // 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
  22. // 3. Windows which uses LoadLibrary
  23. // 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen
  24. // (default) Each part of the ifdef contains a complete implementation for
  25. // the static methods of DynamicLoader.
  26. namespace KWSYS_NAMESPACE
  27. {
  28. //----------------------------------------------------------------------------
  29. DynamicLoader::DynamicLoader()
  30. {
  31. }
  32. //----------------------------------------------------------------------------
  33. DynamicLoader::~DynamicLoader()
  34. {
  35. }
  36. }
  37. // ---------------------------------------------------------------
  38. // 1. Implementation for HPUX machines
  39. #ifdef __hpux
  40. #include <errno.h>
  41. #include <dl.h>
  42. #define DYNAMICLOADER_DEFINED 1
  43. namespace KWSYS_NAMESPACE
  44. {
  45. //----------------------------------------------------------------------------
  46. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  47. {
  48. return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
  49. }
  50. //----------------------------------------------------------------------------
  51. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  52. {
  53. return !shl_unload(lib);
  54. }
  55. //----------------------------------------------------------------------------
  56. DynamicLoader::SymbolPointer
  57. DynamicLoader::GetSymbolAddress(DynamicLoader::LibraryHandle lib, const char* sym)
  58. {
  59. void* addr;
  60. int status;
  61. /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
  62. * TYPE_DATA Look for a symbol in the data segment (for example, variables).
  63. * TYPE_UNDEFINED Look for any symbol.
  64. */
  65. status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
  66. void* result = (status < 0) ? (void*)0 : addr;
  67. // Hack to cast pointer-to-data to pointer-to-function.
  68. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  69. }
  70. //----------------------------------------------------------------------------
  71. const char* DynamicLoader::LibPrefix()
  72. {
  73. return "lib";
  74. }
  75. //----------------------------------------------------------------------------
  76. const char* DynamicLoader::LibExtension()
  77. {
  78. return ".sl";
  79. }
  80. //----------------------------------------------------------------------------
  81. const char* DynamicLoader::LastError()
  82. {
  83. // TODO: Need implementation with errno/strerror
  84. /* If successful, shl_findsym returns an integer (int) value zero. If
  85. * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
  86. * If any other errors occur, shl_findsym returns -1 and sets errno to one
  87. * of these values (defined in <errno.h>):
  88. * ENOEXEC
  89. * A format error was detected in the specified library.
  90. * ENOSYM
  91. * A symbol on which sym depends could not be found.
  92. * EINVAL
  93. * The specified handle is invalid.
  94. */
  95. if( errno == ENOEXEC
  96. || errno == ENOSYM
  97. || errno == EINVAL )
  98. {
  99. return strerror(errno);
  100. }
  101. // else
  102. return 0;
  103. }
  104. } // namespace KWSYS_NAMESPACE
  105. #endif //__hpux
  106. // ---------------------------------------------------------------
  107. // 2. Implementation for Mac OS X 10.2.x and earlier
  108. #ifdef __APPLE__
  109. #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
  110. #include <string.h> // for strlen
  111. #include <mach-o/dyld.h>
  112. #define DYNAMICLOADER_DEFINED 1
  113. namespace KWSYS_NAMESPACE
  114. {
  115. //----------------------------------------------------------------------------
  116. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  117. {
  118. NSObjectFileImageReturnCode rc;
  119. NSObjectFileImage image = 0;
  120. rc = NSCreateObjectFileImageFromFile(libname, &image);
  121. // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
  122. if( rc != NSObjectFileImageSuccess )
  123. {
  124. return 0;
  125. }
  126. NSModule handle = NSLinkModule(image, libname,
  127. NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR);
  128. NSDestroyObjectFileImage(image);
  129. return handle;
  130. }
  131. //----------------------------------------------------------------------------
  132. int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib)
  133. {
  134. // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
  135. // With this option the memory for the module is not deallocated
  136. // allowing pointers into the module to still be valid.
  137. // You should use this option instead if your code experience some problems
  138. // reported against Panther 10.3.9 (fixed in Tiger 10.4.2 and up)
  139. bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  140. return success;
  141. }
  142. //----------------------------------------------------------------------------
  143. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  144. DynamicLoader::LibraryHandle lib, const char* sym)
  145. {
  146. void *result=0;
  147. // Need to prepend symbols with '_' on Apple-gcc compilers
  148. size_t len = strlen(sym);
  149. char *rsym = new char[len + 1 + 1];
  150. strcpy(rsym, "_");
  151. strcat(rsym+1, sym);
  152. NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  153. if(symbol)
  154. {
  155. result = NSAddressOfSymbol(symbol);
  156. }
  157. delete[] rsym;
  158. // Hack to cast pointer-to-data to pointer-to-function.
  159. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  160. }
  161. //----------------------------------------------------------------------------
  162. const char* DynamicLoader::LibPrefix()
  163. {
  164. return "lib";
  165. }
  166. //----------------------------------------------------------------------------
  167. const char* DynamicLoader::LibExtension()
  168. {
  169. // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  170. // it returns NSObjectFileImageInappropriateFile
  171. //return ".dylib";
  172. return ".so";
  173. }
  174. //----------------------------------------------------------------------------
  175. const char* DynamicLoader::LastError()
  176. {
  177. return 0;
  178. }
  179. } // namespace KWSYS_NAMESPACE
  180. #endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030
  181. #endif // __APPLE__
  182. // ---------------------------------------------------------------
  183. // 3. Implementation for Windows win32 code
  184. #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
  185. #include <windows.h>
  186. #define DYNAMICLOADER_DEFINED 1
  187. namespace KWSYS_NAMESPACE
  188. {
  189. //----------------------------------------------------------------------------
  190. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname)
  191. {
  192. DynamicLoader::LibraryHandle lh;
  193. #ifdef UNICODE
  194. wchar_t libn[MB_CUR_MAX];
  195. mbstowcs(libn, libname, MB_CUR_MAX);
  196. lh = LoadLibrary(libn);
  197. #else
  198. lh = LoadLibrary(libname);
  199. #endif
  200. return lh;
  201. }
  202. //----------------------------------------------------------------------------
  203. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  204. {
  205. return (int)FreeLibrary(lib);
  206. }
  207. //----------------------------------------------------------------------------
  208. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  209. DynamicLoader::LibraryHandle lib, const char* sym)
  210. {
  211. void *result;
  212. #ifdef __BORLANDC__
  213. // Need to prepend symbols with '_' on borland compilers
  214. size_t len = strlen(sym);
  215. char *rsym = new char[len + 1 + 1];
  216. strcpy(rsym, "_");
  217. strcat(rsym+1, sym);
  218. #else
  219. const char *rsym = sym;
  220. #endif
  221. #ifdef UNICODE
  222. wchar_t wsym[MB_CUR_MAX];
  223. mbstowcs(wsym, rsym, MB_CUR_MAX);
  224. result = GetProcAddress(lib, wsym);
  225. #else
  226. result = (void*)GetProcAddress(lib, rsym);
  227. #endif
  228. #ifdef __BORLANDC__
  229. delete[] rsym;
  230. #endif
  231. // Hack to cast pointer-to-data to pointer-to-function.
  232. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  233. }
  234. //----------------------------------------------------------------------------
  235. const char* DynamicLoader::LibPrefix()
  236. {
  237. #ifdef __MINGW32__
  238. return "lib";
  239. #else
  240. return "";
  241. #endif
  242. }
  243. //----------------------------------------------------------------------------
  244. const char* DynamicLoader::LibExtension()
  245. {
  246. return ".dll";
  247. }
  248. //----------------------------------------------------------------------------
  249. const char* DynamicLoader::LastError()
  250. {
  251. LPVOID lpMsgBuf;
  252. FormatMessage(
  253. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  254. NULL,
  255. GetLastError(),
  256. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  257. (LPTSTR) &lpMsgBuf,
  258. 0,
  259. NULL
  260. );
  261. static char* str = 0;
  262. delete [] str;
  263. str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  264. // Free the buffer.
  265. LocalFree( lpMsgBuf );
  266. return str;
  267. }
  268. } // namespace KWSYS_NAMESPACE
  269. #endif //_WIN32
  270. // ---------------------------------------------------------------
  271. // 4. Implementation for BeOS
  272. #ifdef __BEOS__
  273. #include <string.h> // for strerror()
  274. #include <be/kernel/image.h>
  275. #include <be/support/Errors.h>
  276. #define DYNAMICLOADER_DEFINED 1
  277. namespace KWSYS_NAMESPACE
  278. {
  279. static image_id last_dynamic_err = B_OK;
  280. //----------------------------------------------------------------------------
  281. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  282. {
  283. // image_id's are integers, errors are negative. Add one just in case we
  284. // get a valid image_id of zero (is that even possible?).
  285. image_id rc = load_add_on(libname);
  286. if (rc < 0)
  287. {
  288. last_dynamic_err = rc;
  289. return 0;
  290. }
  291. return rc+1;
  292. }
  293. //----------------------------------------------------------------------------
  294. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  295. {
  296. if (!lib)
  297. {
  298. last_dynamic_err = B_BAD_VALUE;
  299. return 0;
  300. }
  301. else
  302. {
  303. // The function dlclose() returns 0 on success, and non-zero on error.
  304. status_t rc = unload_add_on(lib-1);
  305. if (rc != B_OK)
  306. {
  307. last_dynamic_err = rc;
  308. return 0;
  309. }
  310. }
  311. return 1;
  312. }
  313. //----------------------------------------------------------------------------
  314. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  315. DynamicLoader::LibraryHandle lib, const char* sym)
  316. {
  317. // Hack to cast pointer-to-data to pointer-to-function.
  318. union
  319. {
  320. void* pvoid;
  321. DynamicLoader::SymbolPointer psym;
  322. } result;
  323. result.psym = NULL;
  324. if (!lib)
  325. {
  326. last_dynamic_err = B_BAD_VALUE;
  327. }
  328. else
  329. {
  330. // !!! FIXME: BeOS can do function-only lookups...does this ever
  331. // !!! FIXME: actually _want_ a data symbol lookup, or was this union
  332. // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
  333. status_t rc = get_image_symbol(lib-1,sym,B_SYMBOL_TYPE_ANY,&result.pvoid);
  334. if (rc != B_OK)
  335. {
  336. last_dynamic_err = rc;
  337. result.psym = NULL;
  338. }
  339. }
  340. return result.psym;
  341. }
  342. //----------------------------------------------------------------------------
  343. const char* DynamicLoader::LibPrefix()
  344. {
  345. return "lib";
  346. }
  347. //----------------------------------------------------------------------------
  348. const char* DynamicLoader::LibExtension()
  349. {
  350. return ".so";
  351. }
  352. //----------------------------------------------------------------------------
  353. const char* DynamicLoader::LastError()
  354. {
  355. const char *retval = strerror(last_dynamic_err);
  356. last_dynamic_err = B_OK;
  357. return retval;
  358. }
  359. } // namespace KWSYS_NAMESPACE
  360. #endif
  361. // ---------------------------------------------------------------
  362. // 5. Implementation for default UNIX machines.
  363. // if nothing has been defined then use this
  364. #ifndef DYNAMICLOADER_DEFINED
  365. #define DYNAMICLOADER_DEFINED 1
  366. // Setup for most unix machines
  367. #include <dlfcn.h>
  368. namespace KWSYS_NAMESPACE
  369. {
  370. //----------------------------------------------------------------------------
  371. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  372. {
  373. return dlopen(libname, RTLD_LAZY);
  374. }
  375. //----------------------------------------------------------------------------
  376. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  377. {
  378. if (lib)
  379. {
  380. // The function dlclose() returns 0 on success, and non-zero on error.
  381. return !dlclose(lib);
  382. }
  383. // else
  384. return 0;
  385. }
  386. //----------------------------------------------------------------------------
  387. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  388. DynamicLoader::LibraryHandle lib, const char* sym)
  389. {
  390. // Hack to cast pointer-to-data to pointer-to-function.
  391. union
  392. {
  393. void* pvoid;
  394. DynamicLoader::SymbolPointer psym;
  395. } result;
  396. result.pvoid = dlsym(lib, sym);
  397. return result.psym;
  398. }
  399. //----------------------------------------------------------------------------
  400. const char* DynamicLoader::LibPrefix()
  401. {
  402. return "lib";
  403. }
  404. //----------------------------------------------------------------------------
  405. const char* DynamicLoader::LibExtension()
  406. {
  407. #ifdef __CYGWIN__
  408. return ".dll";
  409. #else
  410. return ".so";
  411. #endif
  412. }
  413. //----------------------------------------------------------------------------
  414. const char* DynamicLoader::LastError()
  415. {
  416. return dlerror();
  417. }
  418. } // namespace KWSYS_NAMESPACE
  419. #endif