DynamicLoader.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  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 but not cygwin
  184. #if defined(_WIN32) && !defined(__CYGWIN__)
  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. // TODO: The calling convention affects the name of the symbol. We
  212. // should have a tool to help get the symbol with the desired
  213. // calling convention. Currently we assume cdecl.
  214. //
  215. // Borland:
  216. // __cdecl = "_func" (default)
  217. // __fastcall = "@_func"
  218. // __stdcall = "func"
  219. //
  220. // Watcom:
  221. // __cdecl = "_func"
  222. // __fastcall = "@_func@X"
  223. // __stdcall = "_func@X"
  224. // __watcall = "func_" (default)
  225. //
  226. // MSVC:
  227. // __cdecl = "func" (default)
  228. // __fastcall = "@_func@X"
  229. // __stdcall = "_func@X"
  230. //
  231. // Note that the "@X" part of the name above is the total size (in
  232. // bytes) of the arguments on the stack.
  233. void *result;
  234. #if defined(__BORLANDC__) || defined(__WATCOMC__)
  235. // Need to prepend symbols with '_'
  236. size_t len = strlen(sym);
  237. char *rsym = new char[len + 1 + 1];
  238. strcpy(rsym, "_");
  239. strcat(rsym, sym);
  240. #else
  241. const char *rsym = sym;
  242. #endif
  243. #ifdef UNICODE
  244. wchar_t wsym[MB_CUR_MAX];
  245. mbstowcs(wsym, rsym, MB_CUR_MAX);
  246. result = GetProcAddress(lib, wsym);
  247. #else
  248. result = (void*)GetProcAddress(lib, rsym);
  249. #endif
  250. #if defined(__BORLANDC__) || defined(__WATCOMC__)
  251. delete[] rsym;
  252. #endif
  253. // Hack to cast pointer-to-data to pointer-to-function.
  254. #ifdef __WATCOMC__
  255. return *(DynamicLoader::SymbolPointer*)(&result);
  256. #else
  257. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  258. #endif
  259. }
  260. //----------------------------------------------------------------------------
  261. const char* DynamicLoader::LibPrefix()
  262. {
  263. #ifdef __MINGW32__
  264. return "lib";
  265. #else
  266. return "";
  267. #endif
  268. }
  269. //----------------------------------------------------------------------------
  270. const char* DynamicLoader::LibExtension()
  271. {
  272. return ".dll";
  273. }
  274. //----------------------------------------------------------------------------
  275. const char* DynamicLoader::LastError()
  276. {
  277. LPVOID lpMsgBuf;
  278. FormatMessage(
  279. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  280. NULL,
  281. GetLastError(),
  282. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  283. (LPTSTR) &lpMsgBuf,
  284. 0,
  285. NULL
  286. );
  287. static char* str = 0;
  288. delete [] str;
  289. str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  290. // Free the buffer.
  291. LocalFree( lpMsgBuf );
  292. return str;
  293. }
  294. } // namespace KWSYS_NAMESPACE
  295. #endif //_WIN32
  296. // ---------------------------------------------------------------
  297. // 4. Implementation for BeOS
  298. #ifdef __BEOS__
  299. #include <string.h> // for strerror()
  300. #include <be/kernel/image.h>
  301. #include <be/support/Errors.h>
  302. #define DYNAMICLOADER_DEFINED 1
  303. namespace KWSYS_NAMESPACE
  304. {
  305. static image_id last_dynamic_err = B_OK;
  306. //----------------------------------------------------------------------------
  307. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  308. {
  309. // image_id's are integers, errors are negative. Add one just in case we
  310. // get a valid image_id of zero (is that even possible?).
  311. image_id rc = load_add_on(libname);
  312. if (rc < 0)
  313. {
  314. last_dynamic_err = rc;
  315. return 0;
  316. }
  317. return rc+1;
  318. }
  319. //----------------------------------------------------------------------------
  320. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  321. {
  322. if (!lib)
  323. {
  324. last_dynamic_err = B_BAD_VALUE;
  325. return 0;
  326. }
  327. else
  328. {
  329. // The function dlclose() returns 0 on success, and non-zero on error.
  330. status_t rc = unload_add_on(lib-1);
  331. if (rc != B_OK)
  332. {
  333. last_dynamic_err = rc;
  334. return 0;
  335. }
  336. }
  337. return 1;
  338. }
  339. //----------------------------------------------------------------------------
  340. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  341. DynamicLoader::LibraryHandle lib, const char* sym)
  342. {
  343. // Hack to cast pointer-to-data to pointer-to-function.
  344. union
  345. {
  346. void* pvoid;
  347. DynamicLoader::SymbolPointer psym;
  348. } result;
  349. result.psym = NULL;
  350. if (!lib)
  351. {
  352. last_dynamic_err = B_BAD_VALUE;
  353. }
  354. else
  355. {
  356. // !!! FIXME: BeOS can do function-only lookups...does this ever
  357. // !!! FIXME: actually _want_ a data symbol lookup, or was this union
  358. // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
  359. status_t rc = get_image_symbol(lib-1,sym,B_SYMBOL_TYPE_ANY,&result.pvoid);
  360. if (rc != B_OK)
  361. {
  362. last_dynamic_err = rc;
  363. result.psym = NULL;
  364. }
  365. }
  366. return result.psym;
  367. }
  368. //----------------------------------------------------------------------------
  369. const char* DynamicLoader::LibPrefix()
  370. {
  371. return "lib";
  372. }
  373. //----------------------------------------------------------------------------
  374. const char* DynamicLoader::LibExtension()
  375. {
  376. return ".so";
  377. }
  378. //----------------------------------------------------------------------------
  379. const char* DynamicLoader::LastError()
  380. {
  381. const char *retval = strerror(last_dynamic_err);
  382. last_dynamic_err = B_OK;
  383. return retval;
  384. }
  385. } // namespace KWSYS_NAMESPACE
  386. #endif
  387. // ---------------------------------------------------------------
  388. // 5. Implementation for default UNIX machines.
  389. // if nothing has been defined then use this
  390. #ifndef DYNAMICLOADER_DEFINED
  391. #define DYNAMICLOADER_DEFINED 1
  392. // Setup for most unix machines
  393. #include <dlfcn.h>
  394. namespace KWSYS_NAMESPACE
  395. {
  396. //----------------------------------------------------------------------------
  397. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  398. {
  399. return dlopen(libname, RTLD_LAZY);
  400. }
  401. //----------------------------------------------------------------------------
  402. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  403. {
  404. if (lib)
  405. {
  406. // The function dlclose() returns 0 on success, and non-zero on error.
  407. return !dlclose(lib);
  408. }
  409. // else
  410. return 0;
  411. }
  412. //----------------------------------------------------------------------------
  413. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  414. DynamicLoader::LibraryHandle lib, const char* sym)
  415. {
  416. // Hack to cast pointer-to-data to pointer-to-function.
  417. union
  418. {
  419. void* pvoid;
  420. DynamicLoader::SymbolPointer psym;
  421. } result;
  422. result.pvoid = dlsym(lib, sym);
  423. return result.psym;
  424. }
  425. //----------------------------------------------------------------------------
  426. const char* DynamicLoader::LibPrefix()
  427. {
  428. return "lib";
  429. }
  430. //----------------------------------------------------------------------------
  431. const char* DynamicLoader::LibExtension()
  432. {
  433. #ifdef __CYGWIN__
  434. return ".dll";
  435. #else
  436. return ".so";
  437. #endif
  438. }
  439. //----------------------------------------------------------------------------
  440. const char* DynamicLoader::LastError()
  441. {
  442. return dlerror();
  443. }
  444. } // namespace KWSYS_NAMESPACE
  445. #endif