DynamicLoader.cxx 15 KB

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