DynamicLoader.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*============================================================================
  2. KWSys - Kitware System Library
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License 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. // ---------------------------------------------------------------
  27. // 1. Implementation for HPUX machines
  28. #ifdef __hpux
  29. #include <errno.h>
  30. #include <dl.h>
  31. #define DYNAMICLOADER_DEFINED 1
  32. namespace KWSYS_NAMESPACE
  33. {
  34. //----------------------------------------------------------------------------
  35. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  36. {
  37. return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
  38. }
  39. //----------------------------------------------------------------------------
  40. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  41. {
  42. return !shl_unload(lib);
  43. }
  44. //----------------------------------------------------------------------------
  45. DynamicLoader::SymbolPointer
  46. DynamicLoader::GetSymbolAddress(DynamicLoader::LibraryHandle lib, const char* sym)
  47. {
  48. void* addr;
  49. int status;
  50. /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
  51. * TYPE_DATA Look for a symbol in the data segment (for example, variables).
  52. * TYPE_UNDEFINED Look for any symbol.
  53. */
  54. status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
  55. void* result = (status < 0) ? (void*)0 : addr;
  56. // Hack to cast pointer-to-data to pointer-to-function.
  57. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  58. }
  59. //----------------------------------------------------------------------------
  60. const char* DynamicLoader::LibPrefix()
  61. {
  62. return "lib";
  63. }
  64. //----------------------------------------------------------------------------
  65. const char* DynamicLoader::LibExtension()
  66. {
  67. return ".sl";
  68. }
  69. //----------------------------------------------------------------------------
  70. const char* DynamicLoader::LastError()
  71. {
  72. // TODO: Need implementation with errno/strerror
  73. /* If successful, shl_findsym returns an integer (int) value zero. If
  74. * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
  75. * If any other errors occur, shl_findsym returns -1 and sets errno to one
  76. * of these values (defined in <errno.h>):
  77. * ENOEXEC
  78. * A format error was detected in the specified library.
  79. * ENOSYM
  80. * A symbol on which sym depends could not be found.
  81. * EINVAL
  82. * The specified handle is invalid.
  83. */
  84. if( errno == ENOEXEC
  85. || errno == ENOSYM
  86. || errno == EINVAL )
  87. {
  88. return strerror(errno);
  89. }
  90. // else
  91. return 0;
  92. }
  93. } // namespace KWSYS_NAMESPACE
  94. #endif //__hpux
  95. // ---------------------------------------------------------------
  96. // 2. Implementation for Mac OS X 10.2.x and earlier
  97. #ifdef __APPLE__
  98. #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
  99. #include <string.h> // for strlen
  100. #include <mach-o/dyld.h>
  101. #define DYNAMICLOADER_DEFINED 1
  102. namespace KWSYS_NAMESPACE
  103. {
  104. //----------------------------------------------------------------------------
  105. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  106. {
  107. NSObjectFileImageReturnCode rc;
  108. NSObjectFileImage image = 0;
  109. rc = NSCreateObjectFileImageFromFile(libname, &image);
  110. // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
  111. if( rc != NSObjectFileImageSuccess )
  112. {
  113. return 0;
  114. }
  115. NSModule handle = NSLinkModule(image, libname,
  116. NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR);
  117. NSDestroyObjectFileImage(image);
  118. return handle;
  119. }
  120. //----------------------------------------------------------------------------
  121. int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib)
  122. {
  123. // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
  124. // With this option the memory for the module is not deallocated
  125. // allowing pointers into the module to still be valid.
  126. // You should use this option instead if your code experience some problems
  127. // reported against Panther 10.3.9 (fixed in Tiger 10.4.2 and up)
  128. bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  129. return success;
  130. }
  131. //----------------------------------------------------------------------------
  132. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  133. DynamicLoader::LibraryHandle lib, const char* sym)
  134. {
  135. void *result=0;
  136. // Need to prepend symbols with '_' on Apple-gcc compilers
  137. size_t len = strlen(sym);
  138. char *rsym = new char[len + 1 + 1];
  139. strcpy(rsym, "_");
  140. strcat(rsym+1, sym);
  141. NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  142. if(symbol)
  143. {
  144. result = NSAddressOfSymbol(symbol);
  145. }
  146. delete[] rsym;
  147. // Hack to cast pointer-to-data to pointer-to-function.
  148. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  149. }
  150. //----------------------------------------------------------------------------
  151. const char* DynamicLoader::LibPrefix()
  152. {
  153. return "lib";
  154. }
  155. //----------------------------------------------------------------------------
  156. const char* DynamicLoader::LibExtension()
  157. {
  158. // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  159. // it returns NSObjectFileImageInappropriateFile
  160. //return ".dylib";
  161. return ".so";
  162. }
  163. //----------------------------------------------------------------------------
  164. const char* DynamicLoader::LastError()
  165. {
  166. return 0;
  167. }
  168. } // namespace KWSYS_NAMESPACE
  169. #endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030
  170. #endif // __APPLE__
  171. // ---------------------------------------------------------------
  172. // 3. Implementation for Windows win32 code but not cygwin
  173. #if defined(_WIN32) && !defined(__CYGWIN__)
  174. #include <windows.h>
  175. #define DYNAMICLOADER_DEFINED 1
  176. namespace KWSYS_NAMESPACE
  177. {
  178. //----------------------------------------------------------------------------
  179. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname)
  180. {
  181. DynamicLoader::LibraryHandle lh;
  182. #ifdef UNICODE
  183. wchar_t libn[MB_CUR_MAX];
  184. mbstowcs(libn, libname, MB_CUR_MAX);
  185. lh = LoadLibrary(libn);
  186. #else
  187. lh = LoadLibrary(libname);
  188. #endif
  189. return lh;
  190. }
  191. //----------------------------------------------------------------------------
  192. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  193. {
  194. return (int)FreeLibrary(lib);
  195. }
  196. //----------------------------------------------------------------------------
  197. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  198. DynamicLoader::LibraryHandle lib, const char* sym)
  199. {
  200. // TODO: The calling convention affects the name of the symbol. We
  201. // should have a tool to help get the symbol with the desired
  202. // calling convention. Currently we assume cdecl.
  203. //
  204. // Borland:
  205. // __cdecl = "_func" (default)
  206. // __fastcall = "@_func"
  207. // __stdcall = "func"
  208. //
  209. // Watcom:
  210. // __cdecl = "_func"
  211. // __fastcall = "@_func@X"
  212. // __stdcall = "_func@X"
  213. // __watcall = "func_" (default)
  214. //
  215. // MSVC:
  216. // __cdecl = "func" (default)
  217. // __fastcall = "@_func@X"
  218. // __stdcall = "_func@X"
  219. //
  220. // Note that the "@X" part of the name above is the total size (in
  221. // bytes) of the arguments on the stack.
  222. void *result;
  223. #if defined(__BORLANDC__) || defined(__WATCOMC__)
  224. // Need to prepend symbols with '_'
  225. size_t len = strlen(sym);
  226. char *rsym = new char[len + 1 + 1];
  227. strcpy(rsym, "_");
  228. strcat(rsym, sym);
  229. #else
  230. const char *rsym = sym;
  231. #endif
  232. #ifdef UNICODE
  233. wchar_t wsym[MB_CUR_MAX];
  234. mbstowcs(wsym, rsym, MB_CUR_MAX);
  235. result = GetProcAddress(lib, wsym);
  236. #else
  237. result = (void*)GetProcAddress(lib, rsym);
  238. #endif
  239. #if defined(__BORLANDC__) || defined(__WATCOMC__)
  240. delete[] rsym;
  241. #endif
  242. // Hack to cast pointer-to-data to pointer-to-function.
  243. #ifdef __WATCOMC__
  244. return *(DynamicLoader::SymbolPointer*)(&result);
  245. #else
  246. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  247. #endif
  248. }
  249. //----------------------------------------------------------------------------
  250. const char* DynamicLoader::LibPrefix()
  251. {
  252. #ifdef __MINGW32__
  253. return "lib";
  254. #else
  255. return "";
  256. #endif
  257. }
  258. //----------------------------------------------------------------------------
  259. const char* DynamicLoader::LibExtension()
  260. {
  261. return ".dll";
  262. }
  263. //----------------------------------------------------------------------------
  264. const char* DynamicLoader::LastError()
  265. {
  266. LPVOID lpMsgBuf=NULL;
  267. FormatMessage(
  268. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  269. NULL,
  270. GetLastError(),
  271. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  272. (LPTSTR) &lpMsgBuf,
  273. 0,
  274. NULL
  275. );
  276. if(!lpMsgBuf)
  277. {
  278. return NULL;
  279. }
  280. static char* str = 0;
  281. delete [] str;
  282. str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  283. // Free the buffer.
  284. LocalFree( lpMsgBuf );
  285. return str;
  286. }
  287. } // namespace KWSYS_NAMESPACE
  288. #endif //_WIN32
  289. // ---------------------------------------------------------------
  290. // 4. Implementation for BeOS
  291. #if defined __BEOS__
  292. #include <string.h> // for strerror()
  293. #include <be/kernel/image.h>
  294. #include <be/support/Errors.h>
  295. #define DYNAMICLOADER_DEFINED 1
  296. namespace KWSYS_NAMESPACE
  297. {
  298. static image_id last_dynamic_err = B_OK;
  299. //----------------------------------------------------------------------------
  300. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  301. {
  302. // image_id's are integers, errors are negative. Add one just in case we
  303. // get a valid image_id of zero (is that even possible?).
  304. image_id rc = load_add_on(libname);
  305. if (rc < 0)
  306. {
  307. last_dynamic_err = rc;
  308. return 0;
  309. }
  310. return rc+1;
  311. }
  312. //----------------------------------------------------------------------------
  313. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  314. {
  315. if (!lib)
  316. {
  317. last_dynamic_err = B_BAD_VALUE;
  318. return 0;
  319. }
  320. else
  321. {
  322. // The function dlclose() returns 0 on success, and non-zero on error.
  323. status_t rc = unload_add_on(lib-1);
  324. if (rc != B_OK)
  325. {
  326. last_dynamic_err = rc;
  327. return 0;
  328. }
  329. }
  330. return 1;
  331. }
  332. //----------------------------------------------------------------------------
  333. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  334. DynamicLoader::LibraryHandle lib, const char* sym)
  335. {
  336. // Hack to cast pointer-to-data to pointer-to-function.
  337. union
  338. {
  339. void* pvoid;
  340. DynamicLoader::SymbolPointer psym;
  341. } result;
  342. result.psym = NULL;
  343. if (!lib)
  344. {
  345. last_dynamic_err = B_BAD_VALUE;
  346. }
  347. else
  348. {
  349. // !!! FIXME: BeOS can do function-only lookups...does this ever
  350. // !!! FIXME: actually _want_ a data symbol lookup, or was this union
  351. // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
  352. status_t rc = get_image_symbol(lib-1,sym,B_SYMBOL_TYPE_ANY,&result.pvoid);
  353. if (rc != B_OK)
  354. {
  355. last_dynamic_err = rc;
  356. result.psym = NULL;
  357. }
  358. }
  359. return result.psym;
  360. }
  361. //----------------------------------------------------------------------------
  362. const char* DynamicLoader::LibPrefix()
  363. {
  364. return "lib";
  365. }
  366. //----------------------------------------------------------------------------
  367. const char* DynamicLoader::LibExtension()
  368. {
  369. return ".so";
  370. }
  371. //----------------------------------------------------------------------------
  372. const char* DynamicLoader::LastError()
  373. {
  374. const char *retval = strerror(last_dynamic_err);
  375. last_dynamic_err = B_OK;
  376. return retval;
  377. }
  378. } // namespace KWSYS_NAMESPACE
  379. #endif
  380. // ---------------------------------------------------------------
  381. // 5. Implementation for systems without dynamic libs
  382. // __gnu_blrts__ is IBM BlueGene/L
  383. // __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes
  384. #if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__)
  385. #include <string.h> // for strerror()
  386. #define DYNAMICLOADER_DEFINED 1
  387. namespace KWSYS_NAMESPACE
  388. {
  389. //----------------------------------------------------------------------------
  390. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  391. {
  392. return 0;
  393. }
  394. //----------------------------------------------------------------------------
  395. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  396. {
  397. if (!lib)
  398. {
  399. return 0;
  400. }
  401. return 1;
  402. }
  403. //----------------------------------------------------------------------------
  404. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  405. DynamicLoader::LibraryHandle lib, const char* sym)
  406. {
  407. return 0;
  408. }
  409. //----------------------------------------------------------------------------
  410. const char* DynamicLoader::LibPrefix()
  411. {
  412. return "lib";
  413. }
  414. //----------------------------------------------------------------------------
  415. const char* DynamicLoader::LibExtension()
  416. {
  417. return ".a";
  418. }
  419. //----------------------------------------------------------------------------
  420. const char* DynamicLoader::LastError()
  421. {
  422. return "General error";
  423. }
  424. } // namespace KWSYS_NAMESPACE
  425. #endif
  426. // ---------------------------------------------------------------
  427. // 6. Implementation for default UNIX machines.
  428. // if nothing has been defined then use this
  429. #ifndef DYNAMICLOADER_DEFINED
  430. #define DYNAMICLOADER_DEFINED 1
  431. // Setup for most unix machines
  432. #include <dlfcn.h>
  433. namespace KWSYS_NAMESPACE
  434. {
  435. //----------------------------------------------------------------------------
  436. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  437. {
  438. return dlopen(libname, RTLD_LAZY);
  439. }
  440. //----------------------------------------------------------------------------
  441. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  442. {
  443. if (lib)
  444. {
  445. // The function dlclose() returns 0 on success, and non-zero on error.
  446. return !dlclose(lib);
  447. }
  448. // else
  449. return 0;
  450. }
  451. //----------------------------------------------------------------------------
  452. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  453. DynamicLoader::LibraryHandle lib, const char* sym)
  454. {
  455. // Hack to cast pointer-to-data to pointer-to-function.
  456. union
  457. {
  458. void* pvoid;
  459. DynamicLoader::SymbolPointer psym;
  460. } result;
  461. result.pvoid = dlsym(lib, sym);
  462. return result.psym;
  463. }
  464. //----------------------------------------------------------------------------
  465. const char* DynamicLoader::LibPrefix()
  466. {
  467. return "lib";
  468. }
  469. //----------------------------------------------------------------------------
  470. const char* DynamicLoader::LibExtension()
  471. {
  472. #ifdef __CYGWIN__
  473. return ".dll";
  474. #else
  475. return ".so";
  476. #endif
  477. }
  478. //----------------------------------------------------------------------------
  479. const char* DynamicLoader::LastError()
  480. {
  481. return dlerror();
  482. }
  483. } // namespace KWSYS_NAMESPACE
  484. #endif